@@ -367,6 +367,34 @@ function initTogetherJS() {
367367 } ) ;
368368}
369369
370+ function TogetherjsReadyHandler ( ) {
371+ alert ( "ERROR: need to override TogetherjsReadyHandler()" ) ;
372+ }
373+
374+ function TogetherjsCloseHandler ( ) {
375+ alert ( "ERROR: need to override TogetherjsCloseHandler()" ) ;
376+ }
377+
378+ function startSharedSession ( ) {
379+ $ ( "#sharedSessionBtn" ) . hide ( ) ; // hide ASAP!
380+ $ ( "#togetherjsStatus" ) . html ( "Please wait ... loading" ) ;
381+ TogetherJS ( ) ;
382+ }
383+
384+ function populateTogetherJsShareUrl ( ) {
385+ // without anything after the '#' in the hash
386+ var cleanUrl = $ . param . fragment ( location . href , { } , 2 /* override */ ) ;
387+ var urlToShare = cleanUrl + 'togetherjs=' + TogetherJS . shareId ( ) ;
388+ $ ( "#togetherjsStatus" ) . html ( '<div>\
389+ Copy and send this URL to let others join your session:\
390+ </div>\
391+ <input type="text" style="font-size: 11pt; \
392+ font-weight: bold; padding: 5px;\
393+ margin-bottom: 6pt;" \
394+ id="togetherjsURL" size="80" readonly="readonly"/>' ) ;
395+ $ ( "#togetherjsURL" ) . val ( urlToShare ) . attr ( 'size' , urlToShare . length + 25 ) ;
396+ }
397+
370398// END - shared session stuff
371399
372400
@@ -423,6 +451,25 @@ function supports_html5_storage() {
423451
424452// run at the END so that everything else can be initialized first
425453function genericOptFrontendReady ( ) {
454+ initTogetherJS ( ) ; // initialize early
455+
456+
457+ // be friendly to the browser's forward and back buttons
458+ // thanks to http://benalman.com/projects/jquery-bbq-plugin/
459+ $ ( window ) . bind ( "hashchange" , function ( e ) {
460+ var newMode = $ . bbq . getState ( 'mode' ) ;
461+ console . log ( 'hashchange:' , newMode ) ;
462+ updateAppDisplay ( newMode ) ;
463+
464+ if ( TogetherJS . running && ! isExecutingCode ) {
465+ TogetherJS . send ( { type : "hashchange" ,
466+ appMode : appMode ,
467+ codeInputScrollTop : $ ( codeMirrorScroller ) . scrollTop ( ) ,
468+ myAppState : getAppState ( ) } ) ;
469+ }
470+ } ) ;
471+
472+
426473 pyInputCodeMirror = CodeMirror ( document . getElementById ( 'codeInputPane' ) , {
427474 mode : 'python' ,
428475 lineNumbers : true ,
@@ -434,6 +481,33 @@ function genericOptFrontendReady() {
434481
435482 pyInputCodeMirror . setSize ( null , '420px' ) ;
436483
484+
485+ // for shared sessions
486+ pyInputCodeMirror . on ( "change" , function ( cm , change ) {
487+ // only trigger when the user explicitly typed something
488+ if ( change . origin != 'setValue' ) {
489+ if ( TogetherJS . running ) {
490+ TogetherJS . send ( { type : "codemirror-edit" } ) ;
491+ }
492+ }
493+ } ) ;
494+
495+ $ ( '#codeInputPane .CodeMirror-scroll' ) . scroll ( function ( e ) {
496+ if ( TogetherJS . running ) {
497+ var elt = $ ( this ) ;
498+ // debounce
499+ $ . doTimeout ( 'codeInputScroll' , 100 , function ( ) {
500+ // note that this will send a signal back and forth both ways
501+ // (there's no easy way to prevent this), but it shouldn't keep
502+ // bouncing back and forth indefinitely since no the second signal
503+ // causes no additional scrolling
504+ TogetherJS . send ( { type : "codeInputScroll" ,
505+ scrollTop : elt . scrollTop ( ) } ) ;
506+ } ) ;
507+ }
508+ } ) ;
509+
510+
437511 // first initialize options from HTML LocalStorage. very important
438512 // that this code runs first so that options get overridden by query
439513 // string options and anything else the user wants to override with.
@@ -662,8 +736,7 @@ function updateAppDisplay(newAppMode) {
662736 $ ( "#pyOutputPane" ) . show ( ) ;
663737 $ ( "#embedLinkDiv" ) . show ( ) ;
664738
665- // XXX: ugly dependency on TogetherJS
666- if ( ! ( typeof TogetherJS !== 'undefined' && TogetherJS . running ) ) {
739+ if ( ! TogetherJS . running ) {
667740 $ ( "#surveyHeader" ) . show ( ) ;
668741 }
669742
@@ -681,6 +754,31 @@ function updateAppDisplay(newAppMode) {
681754
682755 $ ( document ) . scrollTop ( 0 ) ; // scroll to top to make UX better on small monitors
683756
757+
758+ // NASTY global :(
759+ if ( pendingCodeOutputScrollTop ) {
760+ myVisualizer . domRoot . find ( '#pyCodeOutputDiv' ) . scrollTop ( pendingCodeOutputScrollTop ) ;
761+ pendingCodeOutputScrollTop = null ;
762+ }
763+
764+ $ . doTimeout ( 'pyCodeOutputDivScroll' ) ; // cancel any prior scheduled calls
765+
766+ myVisualizer . domRoot . find ( '#pyCodeOutputDiv' ) . scroll ( function ( e ) {
767+ var elt = $ ( this ) ;
768+ // debounce
769+ $ . doTimeout ( 'pyCodeOutputDivScroll' , 100 , function ( ) {
770+ // note that this will send a signal back and forth both ways
771+ if ( TogetherJS . running ) {
772+ // (there's no easy way to prevent this), but it shouldn't keep
773+ // bouncing back and forth indefinitely since no the second signal
774+ // causes no additional scrolling
775+ TogetherJS . send ( { type : "pyCodeOutputDivScroll" ,
776+ scrollTop : elt . scrollTop ( ) } ) ;
777+ }
778+ } ) ;
779+ } ) ;
780+
781+
684782 $ . bbq . pushState ( { mode : 'display' } , 2 /* completely override other hash strings to keep URL clean */ ) ;
685783 }
686784 else {
@@ -762,6 +860,13 @@ function executePythonCode(pythonSourceCode,
762860 return ;
763861 }
764862
863+ if ( TogetherJS . running && ! executeCodeSignalFromRemote ) {
864+ TogetherJS . send ( { type : "executeCode" ,
865+ myAppState : getAppState ( ) ,
866+ forceStartingInstr : frontendOptionsObj . startingInstruction ,
867+ rawInputLst : rawInputLst } ) ;
868+ }
869+
765870 // if you're in display mode, kick back into edit mode before
766871 // executing or else the display might not refresh properly ... ugh
767872 // krufty FIXME
@@ -817,8 +922,7 @@ function executePythonCode(pythonSourceCode,
817922
818923 // VERY SUBTLE -- reinitialize TogetherJS so that it can detect
819924 // and sync any new elements that are now inside myVisualizer
820- // XXX: ugly dependency on TogetherJS
821- if ( typeof TogetherJS !== 'undefined' && TogetherJS . running ) {
925+ if ( TogetherJS . running ) {
822926 TogetherJS . reinitialize ( ) ;
823927 }
824928 }
0 commit comments