@@ -84,12 +84,16 @@ Code.getPage = function () {
8484Code . getDemoPage = function ( ) {
8585 var area = document . querySelector ( '#demo-area.show' ) ;
8686 if ( area ) {
87- var demo = area . querySelector ( '.da.show' ) ;
88- if ( demo ) {
89- return demo . id ;
87+ var select = document . querySelector ( '#demo-select' ) ;
88+ var link ;
89+ if ( ( select . value ) * 1 < 10 ) {
90+ link = '0' + select . value ;
91+ } else {
92+ link = select . value ;
9093 }
94+ return 'demo-area-' + link ;
9195 }
92- return '' ;
96+ return 'default ' ;
9397} ;
9498
9599/**
@@ -314,98 +318,81 @@ Code.copyCode = function (copy) {
314318}
315319
316320Code . loadDemoArea = function ( ) {
317- var btn , area , select , close , da , option , contentHeight , resizeBar , array = [ ] ;
318- area = document . getElementById ( 'demo-area' ) ;
319- function content ( p ) {
320- var i ;
321- array . forEach ( function ( e , i ) {
322- da [ i ] . className = da [ i ] . className . replace ( "show" , "" ) ;
323- } ) ;
324- option [ p - 1 ] . selected = true ;
325- document . getElementById ( 'demo-area-0' + p ) . className = document . getElementById ( 'demo-area-0' + p ) . className + " show" ;
326- localStorage . demoAreaSelect = p ;
321+ var area = document . getElementById ( 'demo-area' ) ;
322+ var btn = document . getElementById ( 'demoButton' ) ;
323+ var select = document . getElementById ( 'demo-select' ) ;
324+ var close = document . querySelector ( '.close-btn' ) ;
325+ var contentHeight = document . getElementById ( 'content_blocks' ) . offsetHeight ;
326+ var resizeBar = document . getElementById ( 'demo-resize-bar' ) ;
327+
328+ area . style . height = ( contentHeight - 130 ) + 'px' ;
329+ area . className = area . className . replace ( "show" , "" ) ;
330+
331+ if ( localStorage . demoAreaWidth ) {
332+ area . style . width = localStorage . demoAreaWidth ;
327333 }
328- if ( area ) {
329- btn = document . getElementById ( 'demoButton' ) ;
330- select = document . getElementById ( 'demo-select' ) ;
331- close = document . querySelector ( '.close-btn' ) ;
332- da = document . querySelectorAll ( '.da' ) ;
333- option = document . querySelectorAll ( '#demo-select option' ) ;
334- contentHeight = document . getElementById ( 'content_blocks' ) . offsetHeight ;
335- resizeBar = document . getElementById ( 'demo-resize-bar' ) ;
336-
337- array = Array . from ( da ) ;
338- area . style . height = ( contentHeight - 130 ) + 'px' ;
339- area . className = area . className . replace ( "show" , "" ) ;
340334
341- if ( localStorage . demoAreaWidth ) {
342- area . style . width = localStorage . demoAreaWidth ;
343- }
335+ if ( localStorage . demoArea == 'open' ) {
336+ area . className = area . className + "show" ;
337+ }
344338
345- if ( localStorage . demoArea == 'open' ) {
346- area . className = area . className + "show" ;
347- //btn.style.color = '#f80';
348- btn . style . opacity = 1 ;
349- }
339+ if ( ! localStorage . demoAreaSelect ) {
340+ localStorage . demoAreaSelect = 1 ;
341+ }
350342
351- content ( localStorage . demoAreaSelect || 1 ) ;
343+ select . value = localStorage . demoAreaSelect ;
344+ Code . reloadSandbox ( ) ;
352345
353- window . addEventListener ( 'resize' , function ( ) {
354- contentHeight = document . getElementById ( 'content_blocks' ) . offsetHeight ;
355- area . style . height = ( contentHeight - 130 ) + 'px' ;
356- } ) ;
346+ window . addEventListener ( 'resize' , function ( ) {
347+ contentHeight = document . getElementById ( 'content_blocks' ) . offsetHeight ;
348+ area . style . height = ( contentHeight - 130 ) + 'px' ;
349+ } ) ;
357350
358- resizeBar . onmousedown = function ( e ) {
359- area . style . opacity = '0.4' ;
360- var ox = e . pageX ;
361- var dw = area . offsetWidth ;
362- area . className = area . className + " resize" ;
363- document . onmousemove = function ( event ) {
364- var rx = event . pageX ;
365- area . style . width = dw - rx + ox - 20 + 'px' ;
366- localStorage . demoAreaWidth = area . style . width ;
367- }
368- }
351+ resizeBar . onmousedown = function ( e ) {
352+ area . style . opacity = '0.4' ;
353+ var frame = document . getElementById ( 'demo-frame' ) ;
354+ frame . style . pointerEvents = 'none' ;
355+ var ox = e . pageX ;
356+ var dw = area . offsetWidth ;
357+ area . className += " resize" ;
358+
359+ document . onmousemove = function ( event ) {
360+ var rx = event . pageX ;
361+ area . style . width = dw - rx + ox - 20 + 'px' ;
362+ localStorage . demoAreaWidth = area . style . width ;
363+ } ;
364+ } ;
369365
370- document . onmouseup = function ( ) {
371- area . style . opacity = '1' ;
372- area . className = area . className . replace ( " resize" , "" ) ;
373- document . onmousemove = null ;
374- }
366+ document . onmouseup = function ( ) {
367+ area . style . opacity = '1' ;
368+ var frame = document . getElementById ( 'demo-frame' ) ;
369+ frame . style . pointerEvents = 'auto' ;
370+ area . className = area . className . replace ( "resize" , "" ) ;
371+ document . onmousemove = null ;
372+ } ;
375373
376- btn . onclick = function ( ) {
377- area . className = area . className . replace ( "show" , "" ) ;
378- if ( localStorage . demoArea == 'open' ) {
379- localStorage . demoArea = 'close' ;
380- btn . style . color = '#000' ;
381- btn . style . opacity = 0.8 ;
382- } else {
383- area . className = area . className + "show" ;
384- localStorage . demoArea = 'open' ;
385- //btn.style.color = '#f80';
386- btn . style . opacity = 1 ;
387- }
388- } ;
389- close . onclick = function ( ) {
374+ btn . onclick = function ( ) {
375+ if ( localStorage . demoArea == 'open' ) {
390376 area . className = area . className . replace ( "show" , "" ) ;
391377 localStorage . demoArea = 'close' ;
392- btn . style . color = '#000' ;
393- btn . style . opacity = 0.8 ;
394- } ;
378+ } else {
379+ area . className += " show" ;
380+ localStorage . demoArea = 'open' ;
381+ }
382+ Code . reloadSandbox ( ) ;
383+ } ;
395384
396- select . addEventListener ( 'change' , function ( ) {
397- var i ;
398- var selectValue = this . value ;
399- var selectId = 'demo-area-0' + selectValue ;
400- ga ( 'send' , 'event' , 'Webduino-blockly' , 'demo select' , selectValue ) ;
401- localStorage . demoAreaSelect = selectValue ;
402- array . forEach ( function ( e , i ) {
403- da [ i ] . className = da [ i ] . className . replace ( "show" , "" ) ;
404- } ) ;
405- document . getElementById ( selectId ) . className = document . getElementById ( selectId ) . className + " show"
406- } ) ;
407- }
408- }
385+ close . onclick = function ( ) {
386+ area . className = area . className . replace ( "show" , "" ) ;
387+ localStorage . demoArea = 'close' ;
388+ } ;
389+
390+ select . onchange = function ( ) {
391+ ga ( 'send' , 'event' , 'Webduino-blockly' , 'demo select' , this . value ) ;
392+ localStorage . demoAreaSelect = this . value ;
393+ Code . reloadSandbox ( ) ;
394+ } ;
395+ } ;
409396
410397Code . loadSample = function ( ) {
411398 var sampleBtn = document . getElementById ( 'sampleButton' ) ,
@@ -487,6 +474,10 @@ Code.LANG = Code.getLang();
487474
488475Code . PAGE = Code . getPage ( ) ;
489476
477+ Code . running = false ;
478+
479+ Code . lastRun = 0 ;
480+
490481/**
491482 * List of tab names.
492483 * @private
@@ -649,22 +640,10 @@ Code.init = function() {
649640 Code . tabClick ( Code . selected ) ;
650641
651642 Code . bindClick ( 'linkToBin' , function ( ) {
652- var urls = ( location . protocol + '//' + location . host + location . pathname ) . split ( '/' ) ,
653- code = Blockly . JavaScript . workspaceToCode ( Code . workspace ) ,
654- babelize = code . indexOf ( 'async function' ) !== - 1 ,
655- page = Code . getPage ( ) ,
656- config = {
657- tpl : page === 'index' ? Code . getDemoPage ( ) : page ,
658- modes : 'html,css,js,output' ,
659- data : {
660- js : babelize ?
661- '(async function () {\n\n' + code + '\n}());' : code
662- } ,
663- jsPreprocessor : babelize ? 'babel' : ''
664- } ;
665-
643+ var urls = ( location . protocol + '//' + location . host + location . pathname ) . split ( '/' ) ;
644+ var ctx = Code . getContext ( ) ;
666645 urls . pop ( ) ;
667- localStorage . setItem ( urls . join ( '/' ) + '/launcher.html' , JSON . stringify ( config ) ) ;
646+ localStorage . setItem ( urls . join ( '/' ) + '/launcher.html' , JSON . stringify ( ctx ) ) ;
668647 } ) ;
669648
670649 Code . bindClick ( 'trashButton' ,
@@ -698,6 +677,20 @@ Code.init = function() {
698677 window . setTimeout ( Code . copyCode , 1 ) ;
699678 window . setTimeout ( Code . ga , 1 ) ;
700679
680+ var eventDelegater = function ( e ) {
681+ var frame = document . getElementById ( 'demo-frame' ) ,
682+ doc = frame . contentWindow . document ;
683+
684+ if ( Code . running ) {
685+ var event = doc . createEvent ( 'Event' ) ;
686+ event . initEvent ( e . type , true , true ) ;
687+ event . key = e . key ;
688+ event . keyCode = e . keyCode ;
689+ doc . body . dispatchEvent ( event ) ;
690+ }
691+ } ;
692+ window . addEventListener ( 'keydown' , eventDelegater ) ;
693+ window . addEventListener ( 'keyup' , eventDelegater ) ;
701694} ;
702695
703696Code . renderPage = function ( callback ) {
@@ -779,27 +772,90 @@ Code.initLanguage = function() {
779772 * Execute the user's code.
780773 * Just a quick and dirty eval. Catch infinite loops.
781774 */
782- Code . runJS = function ( ) {
783- Blockly . JavaScript . INFINITE_LOOP_TRAP = ' checkTimeout();\n' ;
784- var timeouts = 0 ;
785- var checkTimeout = function ( ) {
786- if ( timeouts ++ > 1000000 ) {
787- throw MSG [ 'timeout' ] ;
788- }
789- } ;
790- var code = Blockly . JavaScript . workspaceToCode ( Code . workspace ) ;
791- if ( code . indexOf ( 'async function' ) === - 1 ) {
792- code = 'disconnectBoards(function () {' + code + '})' ;
793- } else {
794- code = Code . transform ( 'disconnectBoards(async function () {' + code + '})' ) ;
775+ Code . runJS = function ( ) {
776+ var now = Date . now ( ) ;
777+
778+ if ( now - Code . lastRun < 500 ) {
779+ return ;
795780 }
781+ Code . lastRun = now ;
796782
797- Blockly . JavaScript . INFINITE_LOOP_TRAP = null ;
798- try {
799- eval ( code ) ;
800- } catch ( e ) {
801- alert ( MSG [ 'badCode' ] . replace ( '%1' , e ) ) ;
783+ Code . toggleRunning ( ) ;
784+ Code . reloadSandbox ( ) ;
785+ } ;
786+
787+ Code . toggleRunning = function ( ) {
788+ var runBtn = document . getElementById ( 'runButton' ) ;
789+ var select = document . getElementById ( 'demo-select' ) ;
790+ var demoBtn = document . getElementById ( 'demoButton' ) ;
791+ var demoStopBtn = document . querySelector ( '.close-btn' ) ;
792+
793+ if ( ! Code . running ) {
794+ runBtn . style . backgroundColor = "#0a5" ;
795+ runBtn . style . borderColor = "#0a5" ;
796+ document . querySelector ( '#runButton i' ) . setAttribute ( 'class' , 'icon-stop2' ) ;
797+ document . querySelector ( '#runButton div' ) . innerHTML = "停止執行" ;
798+ select . disabled = true ;
799+ demoBtn . disabled = true ;
800+ demoBtn . style . opacity = 0.5 ;
801+ demoStopBtn . style . pointerEvents = 'none' ;
802+ demoStopBtn . style . opacity = 0.2 ;
803+ } else {
804+ runBtn . style . backgroundColor = "#dd4b39" ;
805+ runBtn . style . borderColor = "#dd4b39" ;
806+ document . querySelector ( '#runButton i' ) . setAttribute ( 'class' , 'icon-play3' ) ;
807+ document . querySelector ( '#runButton div' ) . innerHTML = "執行程式" ;
808+ select . disabled = false ;
809+ demoBtn . disabled = false ;
810+ demoBtn . style . opacity = 0.9 ;
811+ demoStopBtn . style . pointerEvents = 'auto' ;
812+ demoStopBtn . style . opacity = 0.5 ;
802813 }
814+
815+ Code . running = ! Code . running ;
816+ } ;
817+
818+ Code . reloadSandbox = function ( ) {
819+ var container = document . querySelector ( '.demo-area-content' ) ;
820+ var ctx = Code . getContext ( ) ;
821+
822+ launcher . loadTemplate ( './templates/' + ctx . tpl + '.html' , function ( data ) {
823+ if ( Code . running ) {
824+ if ( ctx . jsPreprocessor === 'babel' ) {
825+ data . js = Code . transform ( ctx . data . js ) ;
826+ } else {
827+ data . js = ctx . data . js ;
828+ }
829+ }
830+
831+ var frame = container . querySelector ( '#demo-frame' ) ;
832+ if ( frame ) {
833+ container . removeChild ( frame ) ;
834+ frame = null ;
835+ }
836+
837+ frame = document . createElement ( 'iframe' ) ;
838+ frame . id = 'demo-frame' ;
839+ frame . style . display = 'block' ;
840+ container . appendChild ( frame ) ;
841+
842+ launcher . sandbox ( frame , data ) ;
843+ } ) ;
844+ } ;
845+
846+ Code . getContext = function ( ) {
847+ var code = Blockly . JavaScript . workspaceToCode ( Code . workspace ) ,
848+ babelize = code . indexOf ( 'async function' ) !== - 1 ,
849+ page = Code . getPage ( ) ;
850+
851+ return {
852+ tpl : page === 'index' ? Code . getDemoPage ( ) : page ,
853+ modes : 'html,css,js,output' ,
854+ data : {
855+ js : code
856+ } ,
857+ jsPreprocessor : babelize ? 'babel' : ''
858+ } ;
803859} ;
804860
805861Code . transform = function ( code ) {
@@ -811,7 +867,7 @@ Code.transform = function (code) {
811867 } catch ( e ) {
812868 alert ( e ) ;
813869 }
814- }
870+ } ;
815871
816872/**
817873 * Discard all blocks from the workspace.
@@ -908,6 +964,8 @@ Blockly.JavaScript['workspaceToCode'] = function (workspace) {
908964 var code = Blockly . JavaScript [ '_workspaceToCode' ] . call ( Blockly . JavaScript , workspace ) ;
909965 if ( code . indexOf ( 'await ' ) === - 1 ) {
910966 code = code . replace ( new RegExp ( 'async function' , 'g' ) , 'function' ) ;
967+ } else {
968+ code = '(async function () {\n\n' + code + '\n}());' ;
911969 }
912970 return code ;
913971} ;
0 commit comments