@@ -31,173 +31,61 @@ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
3131
3232var backend_script = 'exec' ; // URL of backend script, which must eventually call pg_logger.py
3333
34- var appMode = 'edit' ; // 'edit' or 'visualize'
35-
36-
3734var myVisualizer = null ; // singleton ExecutionVisualizer instance
3835
39- function enterEditMode ( ) {
40- $ . bbq . pushState ( { mode : 'edit' } , 2 /* completely override other hash strings to keep URL clean */ ) ;
41- }
42-
43-
44- var pyInputCodeMirror ; // CodeMirror object that contains the input text
45-
46- function setCodeMirrorVal ( dat ) {
47- pyInputCodeMirror . setValue ( dat . rtrim ( ) /* kill trailing spaces */ ) ;
48- }
49-
50-
51- $ ( document ) . ready ( function ( ) {
52-
53- pyInputCodeMirror = CodeMirror ( document . getElementById ( 'codeInputPane' ) , {
54- mode : 'python' ,
55- lineNumbers : true ,
56- tabSize : 2 ,
57- // convert tab into two spaces:
58- extraKeys : { Tab : function ( cm ) { cm . replaceSelection ( " " , "end" ) ; } }
59- } ) ;
60-
61- pyInputCodeMirror . setSize ( null , '450px' ) ;
62-
63-
64-
65- // be friendly to the browser's forward and back buttons
66- // thanks to http://benalman.com/projects/jquery-bbq-plugin/
67- $ ( window ) . bind ( "hashchange" , function ( e ) {
68- appMode = $ . bbq . getState ( 'mode' ) ; // assign this to the GLOBAL appMode
69-
70- // default mode is 'edit'
71- if ( appMode == undefined ) {
72- appMode = 'edit' ;
73- }
74-
75- // if there's no myVisualizer, then default to edit mode since there's
76- // nothing to visualize:
77- if ( ! myVisualizer ) {
78- appMode = 'edit' ;
79- $ . bbq . pushState ( { mode : 'edit' } , 2 /* completely override other hash strings to keep URL clean */ ) ;
80- }
81-
82-
83- if ( appMode == 'edit' ) {
84- $ ( "#pyInputPane" ) . show ( ) ;
85- $ ( "#pyOutputPane" ) . hide ( ) ;
86- }
87- else if ( appMode == 'visualize' ) {
88- $ ( "#pyInputPane" ) . hide ( ) ;
89- $ ( "#pyOutputPane" ) . show ( ) ;
90-
91- $ ( '#executeBtn' ) . html ( "Visualize execution" ) ;
92- $ ( '#executeBtn' ) . attr ( 'disabled' , false ) ;
93-
94-
95- // do this AFTER making #pyOutputPane visible, or else
96- // jsPlumb connectors won't render properly
97- myVisualizer . updateOutput ( ) ;
98-
99- // grab focus so that keyboard events work
100- myVisualizer . grabKeyboardFocus ( ) ;
101-
102- // customize edit button click functionality AFTER rendering (TODO: awkward!)
103- $ ( '#pyOutputPane #editBtn' ) . click ( function ( ) {
104- enterEditMode ( ) ;
105- } ) ;
106-
107- }
108- else {
109- assert ( false ) ;
110- }
111- } ) ;
112-
113- // From: http://benalman.com/projects/jquery-bbq-plugin/
114- // Since the event is only triggered when the hash changes, we need
115- // to trigger the event now, to handle the hash the page may have
116- // loaded with.
117- $ ( window ) . trigger ( "hashchange" ) ;
118-
119-
120- $ ( "#executeBtn" ) . attr ( 'disabled' , false ) ;
121- $ ( "#executeBtn" ) . click ( function ( ) {
122- $ ( '#executeBtn' ) . html ( "Please wait ... processing your code" ) ;
123- $ ( '#executeBtn' ) . attr ( 'disabled' , true ) ;
124- $ ( "#pyOutputPane" ) . hide ( ) ;
125-
126-
127- $ . get ( backend_script ,
128- { user_script : pyInputCodeMirror . getValue ( ) ,
129- cumulative_mode : $ ( '#cumulativeMode' ) . prop ( 'checked' ) } ,
130- function ( dataFromBackend ) {
131- var trace = dataFromBackend . trace ;
132-
133- // don't enter visualize mode if there are killer errors:
134- if ( ! trace ||
135- ( trace . length == 0 ) ||
136- ( trace [ trace . length - 1 ] . event == 'uncaught_exception' ) ) {
137-
138- if ( trace . length == 1 ) {
139- var errorLineNo = trace [ 0 ] . line - 1 ; /* CodeMirror lines are zero-indexed */
140- if ( errorLineNo !== undefined ) {
141- // highlight the faulting line in pyInputCodeMirror
142- pyInputCodeMirror . focus ( ) ;
143- pyInputCodeMirror . setCursor ( errorLineNo , 0 ) ;
144- pyInputCodeMirror . setLineClass ( errorLineNo , null , 'errorLine' ) ;
145-
146- pyInputCodeMirror . setOption ( 'onChange' , function ( ) {
147- pyInputCodeMirror . setLineClass ( errorLineNo , null , null ) ; // reset line back to normal
148- pyInputCodeMirror . setOption ( 'onChange' , null ) ; // cancel
149- } ) ;
150- }
151-
152- alert ( trace [ 0 ] . exception_msg ) ;
153- }
154- else {
155- alert ( "Whoa, unknown error! Reload to try again, or report a bug to philip@pgbovine.net\n\n(Click the 'Generate URL' button to include a unique URL in your email bug report.)" ) ;
156- }
157-
158- $ ( '#executeBtn' ) . html ( "Visualize execution" ) ;
159- $ ( '#executeBtn' ) . attr ( 'disabled' , false ) ;
36+ function parseLessonFile ( dat ) {
37+ var toks = dat . split ( '======' ) ;
38+ var lessonScript = toks [ 0 ] . rtrim ( ) ;
39+ var metadataJSON = $ . parseJSON ( toks [ 1 ] ) ;
40+ console . log ( lessonScript ) ;
41+ console . log ( metadataJSON ) ;
42+
43+ $ . get ( backend_script ,
44+ { user_script : lessonScript } ,
45+ function ( dataFromBackend ) {
46+ var trace = dataFromBackend . trace ;
47+
48+ // don't enter visualize mode if there are killer errors:
49+ if ( ! trace ||
50+ ( trace . length == 0 ) ||
51+ ( trace [ trace . length - 1 ] . event == 'uncaught_exception' ) ) {
52+
53+ if ( trace . length == 1 ) {
54+ alert ( trace [ 0 ] . exception_msg ) ;
16055 }
16156 else {
162- myVisualizer = new ExecutionVisualizer ( 'pyOutputPane' ,
163- dataFromBackend ,
164- { embeddedMode : true } ) ;
165-
166- $ . bbq . pushState ( { mode : 'visualize' } , 2 /* completely override other hash strings to keep URL clean */ ) ;
57+ alert ( "Whoa, unknown error! Reload to try again, or report a bug to philip@pgbovine.net\n\n(Click the 'Generate URL' button to include a unique URL in your email bug report.)" ) ;
16758 }
168- } ,
169- "json" ) ;
170- } ) ;
59+ }
60+ else {
61+ myVisualizer = new ExecutionVisualizer ( 'pyOutputPane' ,
62+ dataFromBackend ,
63+ { embeddedMode : true } ) ;
64+
65+ myVisualizer . updateOutput ( ) ;
66+
67+ // grab focus so that keyboard events work
68+ myVisualizer . grabKeyboardFocus ( ) ;
69+ }
70+ } ,
71+ "json" ) ;
72+ }
73+
74+ $ ( document ) . ready ( function ( ) {
17175
76+ $ . get ( "lessons/aliasing.txt" , parseLessonFile ) ;
17277
17378 // log a generic AJAX error handler
17479 $ ( document ) . ajaxError ( function ( ) {
17580 alert ( "Server error (possibly due to memory/resource overload)." ) ;
176-
177- $ ( '#executeBtn' ) . html ( "Visualize execution" ) ;
178- $ ( '#executeBtn' ) . attr ( 'disabled' , false ) ;
17981 } ) ;
18082
18183
18284 // redraw connector arrows on window resize
18385 $ ( window ) . resize ( function ( ) {
184- if ( appMode == 'visualize' ) {
86+ if ( myVisualizer ) {
18587 myVisualizer . redrawConnectors ( ) ;
18688 }
18789 } ) ;
18890
189- $ ( '#genUrlBtn' ) . bind ( 'click' , function ( ) {
190- var urlStr = $ . param . fragment ( window . location . href ,
191- { code : pyInputCodeMirror . getValue ( ) ,
192- curInstr : ( appMode == 'visualize' ) ? myVisualizer . curInstr : 0 ,
193- mode : appMode ,
194- cumulative_mode : $ ( '#cumulativeMode' ) . prop ( 'checked' )
195- } ,
196- 2 ) ;
197- $ ( '#urlOutput' ) . val ( urlStr ) ;
198- } ) ;
199-
200-
201- $ . get ( "example-code/aliasing.txt" , setCodeMirrorVal ) ;
20291} ) ;
203-
0 commit comments