@@ -54,6 +54,65 @@ $(document).ready(function() {
5454 $ ( "#testCodeInput" ) . tabby ( ) ; // recognize TAB and SHIFT-TAB
5555
5656
57+ // be friendly to the browser's forward and back buttons
58+ // thanks to http://benalman.com/projects/jquery-bbq-plugin/
59+ $ ( window ) . bind ( "hashchange" , function ( e ) {
60+ appMode = $ . bbq . getState ( "mode" ) ; // assign this to the GLOBAL appMode
61+
62+ if ( appMode == 'edit' ) {
63+ $ ( "#pyInputPane" ) . show ( ) ;
64+ $ ( "#pyOutputPane" ) . hide ( ) ;
65+ $ ( "#pyGradingPane" ) . hide ( ) ;
66+
67+ $ ( "#HintStatement" ) . show ( ) ;
68+ $ ( "#SolutionStatement" ) . show ( ) ;
69+ }
70+ else if ( appMode == 'visualize' ) {
71+ $ ( "#pyInputPane" ) . hide ( ) ;
72+ $ ( "#pyOutputPane" ) . show ( ) ;
73+ $ ( "#pyGradingPane" ) . hide ( ) ;
74+
75+ $ ( "#HintStatement" ) . show ( ) ;
76+ $ ( "#SolutionStatement" ) . show ( ) ;
77+
78+ $ ( '#submitBtn' ) . html ( "Submit answer" ) ;
79+ $ ( '#submitBtn' ) . attr ( 'disabled' , false ) ;
80+
81+ $ ( '#executeBtn' ) . html ( "Visualize execution" ) ;
82+ $ ( '#executeBtn' ) . attr ( 'disabled' , false ) ;
83+
84+
85+ // do this AFTER making #pyOutputPane visible, or else
86+ // jsPlumb connectors won't render properly
87+ processTrace ( curTrace /* kinda dumb and redundant */ , true ) ;
88+
89+ // don't let the user submit answer when there's an error
90+ var hasError = false ;
91+ for ( var i = 0 ; i < curTrace . length ; i ++ ) {
92+ var curEntry = curTrace [ i ] ;
93+ if ( curEntry . event == 'exception' ||
94+ curEntry . event == 'uncaught_exception' ) {
95+ hasError = true ;
96+ break ;
97+ }
98+ }
99+ $ ( '#submitBtn' ) . attr ( 'disabled' , hasError ) ;
100+ }
101+ else if ( appMode == 'grade' ) {
102+ $ ( "#gradeMatrix #gradeMatrixTbody" ) . empty ( ) ; // clear it!!!
103+
104+ $ ( "#pyInputPane" ) . hide ( ) ;
105+ $ ( "#pyOutputPane" ) . hide ( ) ;
106+ $ ( "#pyGradingPane" ) . show ( ) ;
107+
108+ $ ( "#HintStatement" ) . hide ( ) ;
109+ $ ( "#SolutionStatement" ) . hide ( ) ;
110+
111+ gradeSubmission ( ) ;
112+ }
113+ } ) ;
114+
115+
57116 // load the questions file specified by the query string
58117 var questionsFilename = location . search . substring ( 1 ) ;
59118
@@ -75,41 +134,17 @@ function concatSolnTestCode(solnCode, testCode) {
75134
76135
77136function enterEditMode ( ) {
78- appMode = 'edit' ;
79-
80- $ ( "#pyInputPane" ) . show ( ) ;
81- $ ( "#pyOutputPane" ) . hide ( ) ;
82- $ ( "#pyGradingPane" ) . hide ( ) ;
83-
84- $ ( "#HintStatement" ) . show ( ) ;
85- $ ( "#SolutionStatement" ) . show ( ) ;
137+ $ . bbq . pushState ( { mode : 'edit' } ) ;
86138}
87139
88- function enterVisualizeMode ( ) {
89- appMode = 'visualize' ;
90-
91- $ ( "#pyInputPane" ) . hide ( ) ;
92- $ ( "#pyOutputPane" ) . show ( ) ;
93- $ ( "#pyGradingPane" ) . hide ( ) ;
94-
95- $ ( "#HintStatement" ) . show ( ) ;
96- $ ( "#SolutionStatement" ) . show ( ) ;
97-
98- $ ( '#submitBtn' ) . html ( "Submit answer" ) ;
99- $ ( '#submitBtn' ) . attr ( 'disabled' , false ) ;
140+ function enterVisualizeMode ( traceData ) {
141+ curTrace = traceData ; // first assign it to the global curTrace, then
142+ // let jQuery BBQ take care of the rest
143+ $ . bbq . pushState ( { mode : 'visualize' } ) ;
100144}
101145
102146function enterGradingMode ( ) {
103- appMode = 'grade' ;
104-
105- $ ( "#gradeMatrix #gradeMatrixTbody" ) . empty ( ) ; // clear it!!!
106-
107- $ ( "#pyInputPane" ) . hide ( ) ;
108- $ ( "#pyOutputPane" ) . hide ( ) ;
109- $ ( "#pyGradingPane" ) . show ( ) ;
110-
111- $ ( "#HintStatement" ) . hide ( ) ;
112- $ ( "#SolutionStatement" ) . hide ( ) ;
147+ $ . bbq . pushState ( { mode : 'grade' } ) ;
113148}
114149
115150
@@ -119,16 +154,17 @@ function genTestResultHandler(idx) {
119154 assert ( testResults [ idx ] === null ) ;
120155 testResults [ idx ] = res ;
121156
122- // if ALL results have been delivered, then call
123- // readyToGradeSubmission() ... (remember that each result comes in
157+ // if ALL results have been successfully delivered, then call
158+ // enterGradingMode() (remember that each result comes in
124159 // asynchronously and probably out-of-order)
160+
125161 for ( var i = 0 ; i < testResults . length ; i ++ ) {
126162 if ( testResults [ i ] === null ) {
127163 return ;
128164 }
129165 }
130166
131- readyToGradeSubmission ( ) ;
167+ enterGradingMode ( ) ;
132168 }
133169
134170 return ret ;
@@ -194,34 +230,7 @@ function finishQuestionsInit(questionsDat) {
194230 { user_script : submittedCode } ,
195231 function ( traceData ) {
196232 renderPyCodeOutput ( submittedCode ) ;
197-
198- enterVisualizeMode ( ) ;
199-
200- $ ( '#executeBtn' ) . html ( "Visualize execution" ) ;
201- $ ( '#executeBtn' ) . attr ( 'disabled' , false ) ;
202-
203- // do this AFTER making #pyOutputPane visible, or else
204- // jsPlumb connectors won't render properly
205- processTrace ( traceData , true ) ;
206-
207- // don't let the user submit answer when there's an error
208- var hasError = false ;
209- for ( var i = 0 ; i < curTrace . length ; i ++ ) {
210- var curEntry = curTrace [ i ] ;
211- if ( curEntry . event == 'exception' ||
212- curEntry . event == 'uncaught_exception' ) {
213- hasError = true ;
214- break ;
215- }
216- }
217-
218- if ( hasError ) {
219- $ ( '#submitBtn' ) . attr ( 'disabled' , true ) ;
220- }
221- else {
222- $ ( '#submitBtn' ) . attr ( 'disabled' , false ) ;
223- }
224-
233+ enterVisualizeMode ( traceData ) ;
225234 } ,
226235 "json" ) ;
227236 } ) ;
@@ -248,17 +257,13 @@ function finishQuestionsInit(questionsDat) {
248257 "json" ) ;
249258 }
250259 } ) ;
251-
252260}
253261
254262
255263// should be called after ALL elements in testsTraces and expectsTraces
256264// have been populated by their respective AJAX POST calls
257- function readyToGradeSubmission ( ) {
258- enterGradingMode ( ) ;
259-
265+ function gradeSubmission ( ) {
260266 $ ( "#submittedCodePRE" ) . html ( htmlspecialchars ( $ ( "#actualCodeInput" ) . val ( ) ) ) ;
261- //$("#submittedCodeRO").val($("#actualCodeInput").val());
262267
263268 for ( var i = 0 ; i < tests . length ; i ++ ) {
264269 var res = testResults [ i ] ;
0 commit comments