Skip to content
This repository was archived by the owner on Jun 7, 2023. It is now read-only.

Commit f5466e7

Browse files
committed
restore scratch activecode functionality
1 parent fc4f90f commit f5466e7

File tree

2 files changed

+120
-65
lines changed

2 files changed

+120
-65
lines changed

runestone/activecode/js/activecode.js

Lines changed: 119 additions & 64 deletions
Original file line numberDiff line numberDiff line change
@@ -17,9 +17,8 @@ function ActiveCode(opts) {
1717

1818
ActiveCode.prototype.init = function(opts) {
1919
RunestoneBase.apply( this, arguments ); // call parent constructor
20-
var _this = this;
2120
var suffStart = -1;
22-
var orig = opts.orig
21+
var orig = opts.orig;
2322
this.useRunestoneServices = opts.useRunestoneServices;
2423
this.python3 = opts.python3;
2524
this.origElem = orig;
@@ -56,7 +55,7 @@ ActiveCode.prototype.init = function(opts) {
5655
} else {
5756
this.caption = ""
5857
}
59-
this.addCaption()
58+
this.addCaption();
6059

6160
if ($(orig).data('autorun')) {
6261
$(document).ready(this.runProg.bind(this));
@@ -373,14 +372,14 @@ ActiveCode.prototype.createGradeSummary = function () {
373372

374373
el = $(html);
375374
el.modal();
376-
}
377-
var data = {'div_id': this.divid}
375+
};
376+
var data = {'div_id': this.divid};
378377
jQuery.get(eBookConfig.ajaxURL + 'getassignmentgrade', data, showGradeSummary);
379-
}
378+
};
380379

381380
ActiveCode.prototype.hideCodelens = function (button, div_id) {
382381
this.codelens.style.display = 'none'
383-
}
382+
};
384383

385384
ActiveCode.prototype.showCodelens = function () {
386385

@@ -393,35 +392,35 @@ ActiveCode.prototype.showCodelens = function () {
393392
return;
394393
}
395394

396-
var cl = this.codelens.firstChild
395+
var cl = this.codelens.firstChild;
397396
if (cl) {
398397
div.removeChild(cl)
399398
}
400-
var code = this.editor.getValue()
401-
var myVars = {}
402-
myVars.code = code
403-
myVars.origin = "opt-frontend.js"
404-
myVars.cumulative = false
405-
myVars.heapPrimitives = false
406-
myVars.drawParentPointers = false
407-
myVars.textReferences = false
408-
myVars.showOnlyOutputs = false
409-
myVars.rawInputLstJSON = JSON.stringify([])
410-
myVars.py = 2
411-
myVars.curInstr = 0
412-
myVars.codeDivWidth = 350
413-
myVars.codeDivHeight = 400
414-
var srcURL = '//pythontutor.com/iframe-embed.html'
415-
var embedUrlStr = $.param.fragment(srcURL, myVars, 2 /* clobber all */)
416-
var myIframe = document.createElement('iframe')
417-
myIframe.setAttribute("id", this.divid + '_codelens')
418-
myIframe.setAttribute("width", "800")
419-
myIframe.setAttribute("height", "500")
420-
myIframe.setAttribute("style", "display:block")
421-
myIframe.style.background = '#fff'
399+
var code = this.editor.getValue();
400+
var myVars = {};
401+
myVars.code = code;
402+
myVars.origin = "opt-frontend.js";
403+
myVars.cumulative = false;
404+
myVars.heapPrimitives = false;
405+
myVars.drawParentPointers = false;
406+
myVars.textReferences = false;
407+
myVars.showOnlyOutputs = false;
408+
myVars.rawInputLstJSON = JSON.stringify([]);
409+
myVars.py = 2;
410+
myVars.curInstr = 0;
411+
myVars.codeDivWidth = 350;
412+
myVars.codeDivHeight = 400;
413+
var srcURL = '//pythontutor.com/iframe-embed.html';
414+
var embedUrlStr = $.param.fragment(srcURL, myVars, 2 /* clobber all */);
415+
var myIframe = document.createElement('iframe');
416+
myIframe.setAttribute("id", this.divid + '_codelens');
417+
myIframe.setAttribute("width", "800");
418+
myIframe.setAttribute("height", "500");
419+
myIframe.setAttribute("style", "display:block");
420+
myIframe.style.background = '#fff';
422421
//myIframe.setAttribute("src",srcURL)
423-
myIframe.src = embedUrlStr
424-
this.codelens.appendChild(myIframe)
422+
myIframe.src = embedUrlStr;
423+
this.codelens.appendChild(myIframe);
425424
this.logBookEvent({
426425
'event': 'codelens',
427426
'act': 'view',
@@ -455,7 +454,7 @@ ActiveCode.prototype.showCodeCoach = function (div_id) {
455454
myIframe.setAttribute("height", "500px");
456455
myIframe.setAttribute("style", "display:block");
457456
myIframe.style.background = '#fff';
458-
myIframe.style.width = "100%"
457+
myIframe.style.width = "100%";
459458
myIframe.src = srcURL;
460459
this.codecoach.appendChild(myIframe);
461460
logBookEvent({
@@ -472,14 +471,14 @@ ActiveCode.prototype.toggleEditorVisibility = function () {
472471

473472
ActiveCode.prototype.addErrorMessage = function (err) {
474473
//logRunEvent({'div_id': this.divid, 'code': this.prog, 'errinfo': err.toString()}); // Log the run event
475-
var errHead = $('<h3>').html('Error')
476-
this.eContainer = this.outerDiv.appendChild(document.createElement('div'))
474+
var errHead = $('<h3>').html('Error');
475+
this.eContainer = this.outerDiv.appendChild(document.createElement('div'));
477476
this.eContainer.className = 'error alert alert-danger';
478477
this.eContainer.id = this.divid + '_errinfo';
479478
this.eContainer.appendChild(errHead[0]);
480-
var errText = this.eContainer.appendChild(document.createElement('pre'))
481-
var errString = err.toString()
482-
var to = errString.indexOf(":")
479+
var errText = this.eContainer.appendChild(document.createElement('pre'));
480+
var errString = err.toString();
481+
var to = errString.indexOf(":");
483482
var errName = errString.substring(0, to);
484483
errText.innerHTML = errString;
485484
$(this.eContainer).append('<h3>Description</h3>');
@@ -605,7 +604,7 @@ ActiveCode.prototype.buildProg = function() {
605604
};
606605

607606
ActiveCode.prototype.runProg = function() {
608-
var prog = this.buildProg()
607+
var prog = this.buildProg();
609608

610609
$(this.output).text('');
611610

@@ -643,6 +642,61 @@ ActiveCode.prototype.runProg = function() {
643642

644643
};
645644

645+
646+
ActiveCode.createScratchActivecode = function() {
647+
/* set up the scratch Activecode editor in the search menu */
648+
// use the URL to assign a divid - each page should have a unique Activecode block id.
649+
// Remove everything from the URL but the course and page name
650+
// todo: this could probably be eliminated and simply moved to the template file
651+
var divid = document.URL.split('#')[0];
652+
divid = divid.split('static')[1];
653+
divid = divid.split('?')[0]; // remove any query string (e.g ?lastPosition)
654+
divid = divid.replaceAll('/', '').replace('.html', '');
655+
656+
// generate the HTML
657+
var html = '<div id="ac_modal_' + divid + '" class="modal fade">' +
658+
' <div class="modal-dialog scratch-ac-modal">' +
659+
' <div class="modal-content">' +
660+
' <div class="modal-header">' +
661+
' <button type="button" class="close" data-dismiss="modal" aria-hidden="true">&times;</button>' +
662+
' <h4 class="modal-title">Scratch ActiveCode</h4>' +
663+
' </div> ' +
664+
' <div class="modal-body">' +
665+
' <pre data-component="activecode" id="' + divid + '">' +
666+
'<br /> ' +
667+
'<br /> ' +
668+
'<br /> ' +
669+
' </pre>' +
670+
' </div>' +
671+
' </div>' +
672+
' </div>' +
673+
'</div>';
674+
el = $(html);
675+
$('body').append(el);
676+
677+
el.on('shown.bs.modal show.bs.modal', function () {
678+
el.find('.CodeMirror').each(function (i, e) {
679+
e.CodeMirror.refresh();
680+
e.CodeMirror.focus();
681+
});
682+
});
683+
684+
$(document).bind('keypress', '\\', function(evt) {
685+
toggleScratchActivecode();
686+
return false;
687+
});
688+
};
689+
690+
691+
ActiveCode.toggleScratchActivecode = function () {
692+
var divid = "ac_modal_" + document.URL.split('#')[0].split('static')[1].split('?')[0].replaceAll('/', '').replace('.html', '');
693+
var div = $("#" + divid);
694+
695+
div.modal('toggle');
696+
697+
};
698+
699+
646700
JSActiveCode.prototype = new ActiveCode();
647701

648702
function JSActiveCode(opts) {
@@ -656,11 +710,11 @@ JSActiveCode.prototype.init = function(opts) {
656710
}
657711

658712
JSActiveCode.prototype.outputfun = function (a) {
659-
var str = "["
713+
var str = "[";
660714
if (typeof(a) == "object" && a.length) {
661715
for (var i = 0; i < a.length; i++)
662716
if (typeof(a[i]) == "object" && a[i].length) {
663-
str += (i == 0 ? "" : " ") + "["
717+
str += (i == 0 ? "" : " ") + "[";
664718
for (var j = 0; j < a[i].length; j++)
665719
str += a[i][j] + (j == a[i].length - 1 ?
666720
"]" + (i == a.length - 1 ? "]" : ",") + "\n" : ", ");
@@ -673,7 +727,7 @@ JSActiveCode.prototype.outputfun = function (a) {
673727
}
674728
}
675729
return str;
676-
}
730+
};
677731

678732
JSActiveCode.prototype.runProg = function() {
679733
var _this = this;
@@ -688,7 +742,7 @@ JSActiveCode.prototype.runProg = function() {
688742
_this.output.innerHTML += _this.outputfun(str)+"<br />";
689743
};
690744

691-
$(this.output).text('')
745+
$(this.output).text('');
692746
$(this.codeDiv).switchClass("col-md-12","col-md-6",{duration:500,queue:false});
693747
$(this.outDiv).show({duration:700,queue:false});
694748

@@ -723,7 +777,7 @@ HTMLActiveCode.prototype.runProg = function () {
723777
};
724778

725779
HTMLActiveCode.prototype.init = function(opts) {
726-
ActiveCode.prototype.init.apply(this,arguments)
780+
ActiveCode.prototype.init.apply(this,arguments);
727781
this.code = $('<textarea />').html(this.origElem.innerHTML).text();
728782
this.editor.setValue(this.code);
729783
};
@@ -797,7 +851,7 @@ function AudioTour (divid, code, bnum, audio_text) {
797851
first = first + "<div id='" + divid + "_l" + (i + 1) + "'>" + (i + 1) + ". " + codeArray[i] + "</div>";
798852
}
799853
}
800-
first = first + "</pre>"
854+
first = first + "</pre>";
801855

802856
//laying out the HTML content
803857

@@ -829,7 +883,7 @@ function AudioTour (divid, code, bnum, audio_text) {
829883
// show window on the left so that you can see the output from the code still
830884
this.css("left", ($(window).scrollLeft() + "px"));
831885
return this;
832-
}
886+
};
833887

834888
$(".modal-profile").center();
835889
$('.modal-profile').fadeIn("slow");
@@ -899,7 +953,7 @@ function AudioTour (divid, code, bnum, audio_text) {
899953
$("#next_audio").css('opacity', 0.25);
900954
$("#last_audio").css('opacity', 0.25);
901955

902-
};
956+
}
903957

904958
AudioTour.prototype.tour = function (divid, audio_type, bcount) {
905959
// set globals
@@ -981,7 +1035,7 @@ AudioTour.prototype.handlePlaying = function() {
9811035
this.unhighlightLines(this.theDivid, this.ahash[this.aname[this.currIndex]]);
9821036
}
9831037

984-
}
1038+
};
9851039

9861040
AudioTour.prototype.firstAudio = function () {
9871041

@@ -1242,18 +1296,18 @@ function LiveCode(opts) {
12421296
}
12431297

12441298
LiveCode.prototype.init = function(opts) {
1245-
ActiveCode.prototype.init.apply(this,arguments)
1299+
ActiveCode.prototype.init.apply(this,arguments);
12461300

12471301
var orig = opts.orig;
12481302
this.stdin = $(orig).data('stdin');
12491303
this.datafile = $(orig).data('datafile');
12501304
this.sourcefile = $(orig).data('sourcefile');
12511305

1252-
this.API_KEY = "67033pV7eUUvqo07OJDIV8UZ049aLEK1"
1306+
this.API_KEY = "67033pV7eUUvqo07OJDIV8UZ049aLEK1";
12531307
this.USE_API_KEY = true;
12541308
this.JOBE_SERVER = 'http://jobe2.cosc.canterbury.ac.nz';
12551309
this.resource = '/jobe/index.php/restapi/runs/';
1256-
this.div2id = {}
1310+
this.div2id = {};
12571311
if (this.stdin) {
12581312
this.createInputElement();
12591313
}
@@ -1266,8 +1320,8 @@ LiveCode.prototype.createInputElement = function () {
12661320

12671321
var label = document.createElement('label');
12681322
label.for = this.divid + "_stdin";
1269-
$(label).text("Input for Program")
1270-
var input = document.createElement('input')
1323+
$(label).text("Input for Program");
1324+
var input = document.createElement('input');
12711325
input.id = this.divid + "_stdin";
12721326
input.type = "text";
12731327
input.size = "35";
@@ -1279,13 +1333,13 @@ LiveCode.prototype.createInputElement = function () {
12791333

12801334
LiveCode.prototype.createErrorOutput = function () {
12811335

1282-
}
1336+
};
12831337

12841338
LiveCode.prototype.runProg = function() {
12851339
var xhr, stdin;
12861340
var runspec = {};
12871341
var data, host, source, editor;
1288-
var sfilemap = {java: '', cpp: 'test.cpp', c: 'test.c', python3: 'test.py', python2: 'test.py'}
1342+
var sfilemap = {java: '', cpp: 'test.cpp', c: 'test.c', python3: 'test.py', python2: 'test.py'};
12891343

12901344
xhr = new XMLHttpRequest();
12911345
source = this.editor.getValue();
@@ -1313,7 +1367,7 @@ LiveCode.prototype.runProg = function() {
13131367
runspec['file_list'] = [[this.div2id[datafile],datafile]];
13141368
}
13151369
data = JSON.stringify({'run_spec': runspec});
1316-
host = this.JOBE_SERVER + this.resource
1370+
host = this.JOBE_SERVER + this.resource;
13171371

13181372
var odiv = this.output;
13191373
$(this.runButton).attr('disabled', 'disabled');
@@ -1372,7 +1426,7 @@ LiveCode.prototype.runProg = function() {
13721426
}).bind(this);
13731427

13741428
///$("#" + divid + "_errinfo").remove();
1375-
$(this.output).html("Compiling and Running your Code Now...")
1429+
$(this.output).html("Compiling and Running your Code Now...");
13761430

13771431
xhr.onerror = function () {
13781432
this.addJobeErrorMessage("Error communicating with the server.");
@@ -1388,7 +1442,7 @@ LiveCode.prototype.addJobeErrorMessage = function (err) {
13881442
eContainer.className = 'error alert alert-danger';
13891443
eContainer.id = this.divid + '_errinfo';
13901444
eContainer.appendChild(errHead[0]);
1391-
var errText = eContainer.appendChild(document.createElement('pre'))
1445+
var errText = eContainer.appendChild(document.createElement('pre'));
13921446
errText.innerHTML = err;
13931447
};
13941448

@@ -1399,8 +1453,8 @@ LiveCode.prototype.pushDataFile = function (datadiv) {
13991453
var contents = $(document.getElementById(datadiv)).text();
14001454
var contentsb64 = btoa(contents);
14011455
var data = JSON.stringify({ 'file_contents' : contentsb64 });
1402-
var resource = '/jobe/index.php/restapi/files/' + file_id
1403-
var host = JOBE_SERVER + resource
1456+
var resource = '/jobe/index.php/restapi/files/' + file_id;
1457+
var host = JOBE_SERVER + resource;
14041458
var xhr = new XMLHttpRequest();
14051459

14061460
if (this.div2id[datadiv] === undefined ) {
@@ -1413,11 +1467,11 @@ LiveCode.prototype.pushDataFile = function (datadiv) {
14131467

14141468
xhr.onload = function () {
14151469
console.log("successfully sent file " + xhr.responseText);
1416-
}
1470+
};
14171471

14181472
xhr.onerror = function () {
14191473
console.log("error sending file" + xhr.responseText);
1420-
}
1474+
};
14211475

14221476
xhr.send(data)
14231477
}
@@ -1426,8 +1480,9 @@ LiveCode.prototype.pushDataFile = function (datadiv) {
14261480
//
14271481

14281482
$(document).ready(function() {
1483+
ActiveCode.createScratchActivecode();
14291484
$('[data-component=activecode]').each( function(index ) {
1430-
var opts = {'orig' : this, 'useRunestoneServices': eBookConfig.useRunestoneServices, 'python3' : eBookConfig.python3 }
1485+
var opts = {'orig' : this, 'useRunestoneServices': eBookConfig.useRunestoneServices, 'python3' : eBookConfig.python3 };
14311486
if ($(this).data('lang') === "javascript") {
14321487
edList[this.id] = new JSActiveCode(opts);
14331488
} else if ($(this).data('lang') === 'htmlmixed') {
@@ -1450,7 +1505,7 @@ $(document).ready(function() {
14501505
// figure out the login/logout status of the user. Sometimes its immediate, and sometimes its
14511506
// long. So to be safe we'll do it both ways..
14521507
var loggedout;
1453-
$(document).bind("runestone:logout",function() { loggedout=true;})
1508+
$(document).bind("runestone:logout",function() { loggedout=true;});
14541509
$(document).bind("runestone:logout",function() {
14551510
for (k in edList) {
14561511
if (edList.hasOwnProperty(k)) {

0 commit comments

Comments
 (0)