@ -2,34 +2,78 @@
$ ( document ) . ready ( function ( ) {
// ------------------ query params (hash) ----------------
function getQueryParams ( ) {
var qs = window . location . hash . substr ( 1 ) ;
if ( window . location . search . length > 0 ) {
// use legacy query params instead of hash
window . location . hash = window . location . search . substr ( 1 ) ;
window . location . search = "" ;
}
var params = { } ;
var parts = qs . split ( "&" ) ;
for ( var x in parts ) {
var keyValue = parts [ x ] . split ( "=" ) ;
if ( keyValue [ 0 ] !== "" ) params [ keyValue [ 0 ] ] = keyValue [ 1 ] ;
}
return params ;
}
function updateQueryParams ( params ) {
var currentParams = getQueryParams ( ) ;
var keys = Object . keys ( params ) ;
for ( var x in keys ) {
currentParams [ keys [ x ] ] = params [ keys [ x ] ] ;
}
var queryString = "#" ;
var updatedKeys = Object . keys ( currentParams ) ;
for ( var y in updatedKeys ) {
queryString += updatedKeys [ y ] + "=" + currentParams [ updatedKeys [ y ] ] + "&" ;
}
window . location . hash = queryString . slice ( 0 , - 1 ) ;
}
function syncQueryParams ( ) {
$ ( '#optimize' ) . attr ( 'checked' , ( getQueryParams ( ) . optimize == "true" ) ) ;
}
window . onhashchange = syncQueryParams ;
syncQueryParams ( ) ;
// ------------------ gist load ----------------
function getGistId ( str ) {
var idr = /[0-9A-Fa-f]{8,}/ ;
var match = idr . exec ( str ) [ 0 ] ;
return match ;
}
var location _query _params = window . location . search . substr ( 1 ) . split ( "=" ) ;
var loadingFromGist = false ;
if ( location _query _params . indexOf ( 'gist' ) !== - 1 && location _query _params . length >= 2 ) {
var index = location _query _params . indexOf ( 'gist' ) ;
var gistId ;
var key = location _query _params [ index + 1 ] ;
if ( key === '' ) {
var str = prompt ( "Enter the URL or ID of the Gist you would like to load." ) ;
function getGistId ( str ) {
var idr = /[0-9A-Fa-f]{8,}/ ;
var match = idr . exec ( str ) ;
return match ? match [ 0 ] : null ;
}
var queryParams = getQueryParams ( ) ;
var loadingFromGist = false ;
if ( typeof queryParams [ 'gist' ] != undefined ) {
var gistId ;
if ( queryParams [ 'gist' ] === '' ) {
var str = prompt ( "Enter the URL or ID of the Gist you would like to load." ) ;
if ( str !== '' ) {
gistId = getGistId ( str ) ;
loadingFromGist = ! ! gistId ;
}
} else {
gistId = getGistId ( key ) ;
loadingFromGist = ! ! gistId ;
}
$ . ajax ( {
url : 'https://api.github.com/gists/' + gistId ,
jsonp : 'callback' ,
dataType : 'jsonp' ,
gistId = queryParams [ 'gist' ] ;
loadingFromGist = ! ! gistId ;
}
if ( loadingFromGist ) $ . ajax ( {
url : 'https://api.github.com/gists/' + gistId ,
jsonp : 'callback' ,
dataType : 'jsonp' ,
success : function ( response ) {
if ( response . data ) {
for ( var f in response . data . files ) {
@ -43,14 +87,62 @@
}
window . localStorage [ key ] = content ;
}
SOL _CACHE _FILE = fileKey ( Object . keys ( response . data . files ) [ 0 ] ) ;
updateFiles ( ) ;
if ( ! response . data . files ) {
alert ( "Gist load error: " + response . data . message )
} else {
SOL _CACHE _FILE = fileKey ( Object . keys ( response . data . files ) [ 0 ] ) ;
updateFiles ( ) ;
}
}
}
} ) ;
}
// ----------------- storage --------------------
function syncStorage ( ) {
if ( typeof chrome === 'undefined' || ! chrome || ! chrome . storage || ! chrome . storage . sync ) return ;
var obj = { }
var done = false ;
var count = 0
var dont = 0 ;
function check ( key ) {
chrome . storage . sync . get ( key , function ( resp ) {
console . log ( "comparing to cloud" , key , resp )
if ( typeof resp [ key ] != 'undefined' && obj [ key ] !== resp [ key ] && confirm ( "Overwrite '" + fileNameFromKey ( key ) + "'? Click Ok to overwrite local file with file from cloud. Cancel will push your local file to the cloud." ) ) {
console . log ( "Overwriting" , key )
localStorage . setItem ( key , resp [ key ] ) ;
updateFiles ( ) ;
} else {
console . log ( "add to obj" , obj , key )
obj [ key ] = localStorage [ key ] ;
}
done ++
if ( done >= count ) chrome . storage . sync . set ( obj , function ( ) {
console . log ( "updated cloud files with: " , obj , this , arguments )
} )
} )
}
for ( var y in window . localStorage ) {
console . log ( "checking" , y )
obj [ y ] = window . localStorage . getItem ( y ) ;
if ( y . indexOf ( SOL _CACHE _FILE _PREFIX ) !== 0 ) continue ;
count ++ ;
check ( y )
}
}
window . syncStorage = syncStorage ;
syncStorage ( )
// ----------------- editor ----------------------
@ -59,7 +151,8 @@
var SOL _CACHE _FILE = null ;
var editor = ace . edit ( "input" ) ;
var session = editor . getSession ( ) ;
var sessions = { } ;
var Range = ace . require ( 'ace/range' ) . Range ;
var errMarkerId = null ;
@ -76,11 +169,22 @@
SOL _CACHE _FILE = getFiles ( ) [ 0 ] ;
editor . setValue ( window . localStorage [ SOL _CACHE _FILE ] , - 1 ) ;
var files = getFiles ( ) ;
for ( var x in files ) {
sessions [ files [ x ] ] = newEditorSession ( files [ x ] )
}
editor . setSession ( sessions [ SOL _CACHE _FILE ] ) ;
editor . resize ( true ) ;
session . setMode ( "ace/mode/javascript" ) ;
session . setTabSize ( 4 ) ;
session . setUseSoftTabs ( true ) ;
function newEditorSession ( filekey ) {
var s = new ace . EditSession ( window . localStorage [ filekey ] , "ace/mode/javascript" )
s . setTabSize ( 4 ) ;
s . setUseSoftTabs ( true ) ;
sessions [ filekey ] = s ;
return s ;
}
@ -88,7 +192,9 @@
$ ( '#options li' ) . click ( function ( ev ) {
var $el = $ ( this ) ;
var cls = /[a-z]+View/ . exec ( $el . get ( 0 ) . className ) [ 0 ] ;
var match = /[a-z]+View/ . exec ( $el . get ( 0 ) . className ) ;
if ( ! match ) return ;
var cls = match [ 0 ] ;
if ( ! $el . hasClass ( 'active' ) ) {
$el . parent ( ) . find ( 'li' ) . removeClass ( 'active' ) ;
$ ( '#optionViews' ) . attr ( 'class' , '' ) . addClass ( cls ) ;
@ -141,13 +247,13 @@
$ ( '#gist' ) . click ( function ( ) {
if ( confirm ( "Are you sure you want to publish all your files anonymously as a public gist on github.com?" ) ) {
var files = { } ;
var filesArr = getFiles ( ) ;
var description = "Created using soleditor : Realtime Ethereum Contract Compiler and Runtime. Load this file by pasting this gists URL or ID at https://chriseth.github.io/browser-solidity/? gist=" ;
for ( var f in filesArr ) {
files [ fileNameFromKey ( filesArr [ f ] ) ] = {
var files = { } ;
var filesArr = getFiles ( ) ;
var description = "Created using browser-solidity : Realtime Ethereum Contract Compiler and Runtime. \n Load this file by pasting this gists URL or ID at https://chriseth.github.io/browser-solidity/#version=" + getQueryParams ( ) . version + "&optimize=" + getQueryParams ( ) . optimize + "& gist=" ;
for ( var f in filesArr ) {
files [ fileNameFromKey ( filesArr [ f ] ) ] = {
content : localStorage [ filesArr [ f ] ]
} ;
}
@ -170,13 +276,20 @@
// ----------------- file selector-------------
var $filesEl = $ ( '#files' ) ;
$filesEl . on ( 'click' , '.newFile' , function ( ) {
var FILE _SCROLL _DELTA = 300 ;
$ ( '.newFile' ) . on ( 'click' , function ( ) {
while ( window . localStorage [ SOL _CACHE _UNTITLED + untitledCount ] )
untitledCount = ( untitledCount - 0 ) + 1 ;
SOL _CACHE _FILE = SOL _CACHE _UNTITLED + untitledCount ;
window . localStorage [ SOL _CACHE _FILE ] = '' ;
updateFiles ( ) ;
$filesEl . animate ( { left : Math . max ( ( 0 - activeFilePos ( ) + ( FILE _SCROLL _DELTA / 2 ) ) , 0 ) + "px" } , "slow" , function ( ) {
reAdjust ( ) ;
} )
} ) ;
$filesEl . on ( 'click' , '.file:not(.active)' , showFileHandler ) ;
@ -253,16 +366,17 @@
if ( SOL _CACHE _FILE ) {
var active = fileTabFromKey ( SOL _CACHE _FILE ) ;
active . addClass ( 'active' ) ;
editor . setValue ( window . localStorage [ SOL _CACHE _FILE ] || '' , - 1 ) ;
editor . setSession ( sessions [ SOL _CACHE _FILE ] ) ;
editor . focus ( ) ;
}
$ ( '#input' ) . toggle ( ! ! SOL _CACHE _FILE ) ;
$ ( '#output' ) . toggle ( ! ! SOL _CACHE _FILE ) ;
reAdjust ( ) ;
}
function fileTabTemplate ( key ) {
var name = fileNameFromKey ( key ) ;
return $ ( '<span class="file"><span class="name">' + name + '</span><span class="remove"><i class="fa fa-close"></i></span></span >' ) ;
return $ ( '<li class="file"><span class="name">' + name + '</span><span class="remove"><i class="fa fa-close"></i></span></li >' ) ;
}
function fileKey ( name ) {
@ -278,16 +392,79 @@
for ( var f in localStorage ) {
if ( f . indexOf ( SOL _CACHE _FILE _PREFIX , 0 ) === 0 ) {
files . push ( f ) ;
if ( ! sessions [ f ] ) sessions [ f ] = newEditorSession ( f ) ;
}
}
return files ;
}
$filesWrapper = $ ( '.files-wrapper' ) ;
$scrollerRight = $ ( '.scroller-right' ) ;
$scrollerLeft = $ ( '.scroller-left' ) ;
function widthOfList ( ) {
var itemsWidth = 0 ;
$ ( '.file' ) . each ( function ( ) {
var itemWidth = $ ( this ) . outerWidth ( ) ;
itemsWidth += itemWidth ;
} ) ;
return itemsWidth ;
} ;
function widthOfHidden ( ) {
return ( ( $filesWrapper . outerWidth ( ) ) - widthOfList ( ) - getLeftPosi ( ) ) ;
} ;
function widthOfVisible ( ) {
return $filesWrapper . outerWidth ( ) ;
} ;
function getLeftPosi ( ) {
return $filesEl . position ( ) . left ;
} ;
function activeFilePos ( ) {
var el = $filesEl . find ( '.active' ) ;
var l = el . position ( ) . left ;
return l ;
}
function reAdjust ( ) {
if ( widthOfList ( ) + getLeftPosi ( ) > + widthOfVisible ( ) ) {
$scrollerRight . fadeIn ( 'fast' ) ;
} else {
$scrollerRight . fadeOut ( 'fast' ) ;
}
if ( getLeftPosi ( ) < 0 ) {
$scrollerLeft . fadeIn ( 'fast' ) ;
} else {
$scrollerLeft . fadeOut ( 'fast' ) ;
$filesEl . animate ( { left : getLeftPosi ( ) + "px" } , 'slow' ) ;
}
}
$scrollerRight . click ( function ( ) {
var delta = ( getLeftPosi ( ) - FILE _SCROLL _DELTA )
$filesEl . animate ( { left : delta + "px" } , 'slow' , function ( ) {
reAdjust ( ) ;
} ) ;
} ) ;
$scrollerLeft . click ( function ( ) {
var delta = Math . min ( ( getLeftPosi ( ) + FILE _SCROLL _DELTA ) , 0 )
$filesEl . animate ( { left : delta + "px" } , 'slow' , function ( ) {
reAdjust ( ) ;
} ) ;
} ) ;
updateFiles ( ) ;
// ----------------- version selector-------------
// var soljsonSources is provided by bin/list.js
$ ( 'option' , '#versionSelector' ) . remove ( ) ;
$ . each ( soljsonSources , function ( i , file ) {
if ( file ) {
@ -296,6 +473,7 @@
}
} ) ;
$ ( '#versionSelector' ) . change ( function ( ) {
updateQueryParams ( { version : $ ( '#versionSelector' ) . val ( ) } ) ;
loadVersion ( $ ( '#versionSelector' ) . val ( ) ) ;
} ) ;
@ -339,6 +517,7 @@
dragging = false ;
setEditorSize ( delta ) ;
window . localStorage . setItem ( EDITOR _SIZE _CACHE _KEY , delta ) ;
reAdjust ( ) ;
}
} ) ;
@ -352,10 +531,11 @@
var hidingRHP = false ;
$ ( '.toggleRHP' ) . click ( function ( ) {
hidingRHP = ! hidingRHP ;
setEditorSize ( hidingRHP ? 0 : window . localStorage [ EDITOR _SIZE _CACHE _KEY ] ) ;
$ ( '.toggleRHP' ) . toggleClass ( 'hiding' , hidingRHP ) ;
if ( ! hidingRHP ) compile ( ) ;
hidingRHP = ! hidingRHP ;
setEditorSize ( hidingRHP ? 0 : window . localStorage [ EDITOR _SIZE _CACHE _KEY ] ) ;
$ ( '.toggleRHP i' ) . toggleClass ( 'fa-angle-double-right' , ! hidingRHP ) ;
$ ( '.toggleRHP i' ) . toggleClass ( 'fa-angle-double-left' , hidingRHP ) ;
if ( ! hidingRHP ) compile ( ) ;
} ) ;
@ -363,6 +543,7 @@
function onResize ( ) {
editor . resize ( ) ;
var session = editor . getSession ( ) ;
session . setUseWrapMode ( document . querySelector ( '#editorWrap' ) . checked ) ;
if ( session . getUseWrapMode ( ) ) {
var characterWidth = editor . renderer . characterWidth ;
@ -372,6 +553,7 @@
session . setWrapLimit ( parseInt ( contentWidth / characterWidth , 10 ) ) ;
}
}
reAdjust ( ) ;
}
window . onresize = onResize ;
onResize ( ) ;
@ -401,7 +583,7 @@
if ( input === null ) {
renderError ( error ) ;
} else {
var optimize = document . querySelector ( '#optimize' ) . checked ;
var optimize = getQueryParams ( ) . optimize ;
compileJSON ( input , optimize ? 1 : 0 ) ;
}
} ) ;
@ -553,6 +735,7 @@
var worker = null ;
var loadVersion = function ( version ) {
$ ( '#version' ) . text ( "(loading)" ) ;
updateQueryParams ( { version : version } ) ;
var isFirefox = typeof InstallTrigger !== 'undefined' ;
if ( document . location . protocol != 'file:' && Worker !== undefined && isFirefox ) {
// Workers cannot load js on "file:"-URLs and we get a
@ -571,17 +754,24 @@
if ( ! Module ) return ;
window . clearInterval ( check ) ;
onCompilerLoaded ( ) ;
} , 200 ) ;
}
} ;
loadVersion ( 'soljson-latest.js' ) ;
editor . getSession ( ) . on ( 'change' , onChange ) ;
document . querySelector ( '#optimize' ) . addEventListener ( 'change' , compile ) ;
// ----------------- compiler output renderer ----------------------
var detailsOpen = { } ;
} , 200 ) ;
}
} ;
loadVersion ( getQueryParams ( ) . version || 'soljson-latest.js' ) ;
editor . getSession ( ) . on ( 'change' , onChange ) ;
editor . on ( 'changeSession' , function ( ) {
editor . getSession ( ) . on ( 'change' , onChange ) ;
} )
document . querySelector ( '#optimize' ) . addEventListener ( 'change' , function ( ) {
updateQueryParams ( { optimize : document . querySelector ( '#optimize' ) . checked } ) ;
compile ( ) ;
} ) ;
// ----------------- compiler output renderer ----------------------
var detailsOpen = { } ;
function errortype ( message ) {
return message . match ( /^.*:[0-9]*:[0-9]* Warning: / ) ? 'warning' : 'error' ;
@ -696,9 +886,9 @@
$txOrigin . empty ( ) ;
for ( var a in accounts ) { $txOrigin . append ( $ ( '<option />' ) . val ( accounts [ a ] ) . text ( accounts [ a ] ) ) ; }
$txOrigin . val ( accounts [ 0 ] ) ;
} else $txOrigin . val ( 'unknown' ) ;
} else $txOrigin . val ( 'unknown' ) ;
}
if ( executionContext === 'vm' ) {
dapp . getAccounts ( renderAccounts ) ;
} else {
@ -710,7 +900,7 @@
$ ( '.col2 input,textarea' ) . click ( function ( ) { this . select ( ) ; } ) ;
} ;
var tableRowItems = function ( first , second , cls ) {
return $ ( '<div class="row"/>' )
return $ ( '<div class="c row"/>' )
. addClass ( cls )
. append ( $ ( '<div class="col1">' ) . append ( first ) )
. append ( $ ( '<div class="col2">' ) . append ( second ) ) ;
@ -801,4 +991,6 @@
return funABI ;
} ;
syncStorage ( )
} ) ;