diff --git a/.jshintrc b/.jshintrc index 87604cef9..5950318e8 100644 --- a/.jshintrc +++ b/.jshintrc @@ -9,10 +9,11 @@ ], "esversion": 6, "quotmark": true, - "strict": false, + "strict": "implied", "sub": true, "browser": true, "maxerr": 200, - "globalstrict": true + "globalstrict": true, + "devel": true } \ No newline at end of file diff --git a/runestone/activecode/js/acfactory.js b/runestone/activecode/js/acfactory.js index 5dfb5c504..08f7442bb 100644 --- a/runestone/activecode/js/acfactory.js +++ b/runestone/activecode/js/acfactory.js @@ -104,30 +104,24 @@ export default class ACFactory { ? eBookConfig.acDefaultLanguage : "python"; // generate the HTML - var html = - '"; + var html = `
+ +
`; var el = $(html); $("body").append(el); el.on("shown.bs.modal show.bs.modal", function() { @@ -136,10 +130,6 @@ export default class ACFactory { e.CodeMirror.focus(); }); }); - //$(document).bind('keypress', '\\', function(evt) { - // ACFactory.toggleScratchActivecode(); - // return false; - //}); } static toggleScratchActivecode() { var divid = "ac_modal_" + eBookConfig.scratchDiv; diff --git a/runestone/activecode/js/activecode.js b/runestone/activecode/js/activecode.js index f982e95fa..a23101c17 100755 --- a/runestone/activecode/js/activecode.js +++ b/runestone/activecode/js/activecode.js @@ -5,6 +5,7 @@ "use strict"; import RunestoneBase from "../../common/js/runestonebase.js"; +import AudioTour from "./audiotour"; import "./activecode-i18n.en"; import CodeMirror from "codemirror"; import "codemirror/mode/python/python.js"; @@ -77,7 +78,7 @@ export class ActiveCode extends RunestoneBase { socket = new WebSocket("wss://" + chatcodesServer); } if (!connection) { - connection = new sharedb.Connection(socket); + connection = new window.sharedb.Connection(socket); } if (!doc) { doc = connection.get("chatcodes", "channels"); @@ -209,10 +210,11 @@ export class ActiveCode extends RunestoneBase { } createControls() { var ctrlDiv = document.createElement("div"); + var butt; $(ctrlDiv).addClass("ac_actions"); $(ctrlDiv).addClass("col-md-12"); // Run - var butt = document.createElement("button"); + butt = document.createElement("button"); $(butt).text($.i18n("msg_activecode_run_code")); $(butt).addClass("btn btn-success run-button"); ctrlDiv.appendChild(butt); @@ -220,7 +222,7 @@ export class ActiveCode extends RunestoneBase { $(butt).click(this.runProg.bind(this)); $(butt).attr("type", "button"); if (this.enabledownload || eBookConfig.downloadsEnabled) { - var butt = document.createElement("button"); + butt = document.createElement("button"); $(butt).text("Download"); $(butt).addClass("btn save-button"); ctrlDiv.appendChild(butt); @@ -229,7 +231,7 @@ export class ActiveCode extends RunestoneBase { $(butt).attr("type", "button"); } if (!this.hidecode && !this.hidehistory) { - var butt = document.createElement("button"); + butt = document.createElement("button"); $(butt).text($.i18n("msg_activecode_load_history")); $(butt).addClass("btn btn-default"); $(butt).attr("type", "button"); @@ -625,7 +627,7 @@ export class ActiveCode extends RunestoneBase { $(coachDiv).css("display", "none"); this.codecoach = coachDiv; this.outerDiv.appendChild(coachDiv); - var clearDiv = document.createElement("div"); + clearDiv = document.createElement("div"); $(clearDiv).css("clear", "both"); // needed to make parent div resize properly this.outerDiv.appendChild(clearDiv); } @@ -728,11 +730,12 @@ export class ActiveCode extends RunestoneBase { // display grades in modal window var showGradeSummary = function(data, status, whatever) { var report = eval(data)[0]; + var body; // check for report['message'] if (report) { if (report["version"] == 2) { // new version; would be better to embed this in HTML for the activecode - var body = + body = "

Grade Report

" + "

This question: " + report["grade"] + @@ -743,7 +746,7 @@ export class ActiveCode extends RunestoneBase { report["comment"] + "

"; } else { - var body = + body = "

Grade Report

" + "

This assignment: " + report["grade"] + @@ -762,20 +765,19 @@ export class ActiveCode extends RunestoneBase { body = "

The server did not return any grade information

"; } - var html = - '"; + var html = ``; var el = $(html); el.modal(); }; @@ -885,7 +887,7 @@ export class ActiveCode extends RunestoneBase { var ifm = document.createElement("iframe"); $(ifm).addClass("tie-frame"); ifm.src = `https://tech-interview-exercises.appspot.com/client/question.html?qid=${this.tie}`; - setIframeDimensions = function() { + var setIframeDimensions = function() { $(".tie-container").css( "width", $(".tie-container") diff --git a/runestone/activecode/js/activecode_html.js b/runestone/activecode/js/activecode_html.js index f446a517c..9e4aa95a0 100644 --- a/runestone/activecode/js/activecode_html.js +++ b/runestone/activecode/js/activecode_html.js @@ -14,7 +14,7 @@ export default class HTMLActiveCode extends ActiveCode { runProg() { var prog = this.buildProg(true); var scrubber_dfd, history_dfd, saveCode; - var saveCode = "True"; + saveCode = "True"; var __ret = this.manage_scrubber(scrubber_dfd, history_dfd, saveCode); history_dfd = __ret.history_dfd; saveCode = __ret.saveCode; diff --git a/runestone/activecode/js/audiotour.js b/runestone/activecode/js/audiotour.js index 4e26c07b2..908974b48 100644 --- a/runestone/activecode/js/audiotour.js +++ b/runestone/activecode/js/audiotour.js @@ -1,550 +1,593 @@ -import RunestoneBase from "../common/runestonebase.js"; +import RunestoneBase from "../../common/js/runestonebase.js"; // function to display the audio tours export default class AudioTour extends RunestoneBase { - constructor(divid, code, bnum, audio_text) { - this.audio_tour = null; - this.audio_code = null; - this.windowcode = null; - this.first_audio = null; - this.prev_audio = null; - this.pause_audio = null; - this.next_audio = null; - this.last_audio = null; - this.status = null; - this.stop_button = null; - this.tourButtons = []; - this.elem = null; // current audio element playing - this.currIndex = null; // current index - this.len = null; // current length of audio files for tour - this.buttonCount = null; // number of audio tour buttons - this.aname = null; // the audio file name - this.ahash = null; // hash of the audio file name to the lines to highlight - this.theDivid = null; // div id - this.afile = null; // file name for audio - this.playing = false; // flag to say if playing or not - this.tourName = ""; - // Replacing has been done here to make sure special characters in the code are displayed correctly - code = code.replaceAll("*doubleq*", '"'); - code = code.replaceAll("*singleq*", "'"); - code = code.replaceAll("*open*", "("); - code = code.replaceAll("*close*", ")"); - code = code.replaceAll("*nline*", "
"); - var codeArray = code.split("\n"); - var audio_hash = []; - var bval = []; - var atype = audio_text.replaceAll("*doubleq*", '"'); - var audio_type = atype.split("*atype*"); - for (var i = 0; i < audio_type.length - 1; i++) { - audio_hash[i] = audio_type[i]; - var aword = audio_type[i].split(";"); - bval.push(aword[0]); + constructor(divid, code, bnum, audio_text) { + this.audio_tour = null; + this.audio_code = null; + this.windowcode = null; + this.first_audio = null; + this.prev_audio = null; + this.pause_audio = null; + this.next_audio = null; + this.last_audio = null; + this.status = null; + this.stop_button = null; + this.tourButtons = []; + this.elem = null; // current audio element playing + this.currIndex = null; // current index + this.len = null; // current length of audio files for tour + this.buttonCount = null; // number of audio tour buttons + this.aname = null; // the audio file name + this.ahash = null; // hash of the audio file name to the lines to highlight + this.theDivid = null; // div id + this.afile = null; // file name for audio + this.playing = false; // flag to say if playing or not + this.tourName = ""; + // Replacing has been done here to make sure special characters in the code are displayed correctly + code = code.replaceAll("*doubleq*", '"'); + code = code.replaceAll("*singleq*", "'"); + code = code.replaceAll("*open*", "("); + code = code.replaceAll("*close*", ")"); + code = code.replaceAll("*nline*", "
"); + var codeArray = code.split("\n"); + var audio_hash = []; + var bval = []; + var atype = audio_text.replaceAll("*doubleq*", '"'); + var audio_type = atype.split("*atype*"); + for (var i = 0; i < audio_type.length - 1; i++) { + audio_hash[i] = audio_type[i]; + var aword = audio_type[i].split(";"); + bval.push(aword[0]); + } + var first = + "
" + + "1. " + + codeArray[0] + + "
"; + var num_lines = codeArray.length; + for (var i = 1; i < num_lines; i++) { + if (i < 9) { + first = + first + + "
" + + (i + 1) + + ". " + + codeArray[i] + + "
"; + } else if (i < 99) { + first = + first + + "
" + + (i + 1) + + ". " + + codeArray[i] + + "
"; + } else { + first = + first + + "
" + + (i + 1) + + ". " + + codeArray[i] + + "
"; + } + } + first = first + "
"; + //laying out the HTML content + var bcount = 0; + for (var i = 0; i < audio_type.length - 1; i++) { + var newButton = document.createElement("button"); + newButton.className = "btn btn-success"; + newButton.innerHTML = bval[i].replace(/\"/g, ""); + this.tourButtons.push(newButton); + bcount++; + } + this.audio_tour = document.createElement("div"); + this.audio_tour.align = "center"; + this.audio_code = document.createElement("p"); + this.windowcode = document.createElement("div"); + this.windowcode.align = "left"; + $(this.windowcode).html(first); + this.first_audio = document.createElement("button"); + this.prev_audio = document.createElement("button"); + this.pause_audio = document.createElement("button"); + this.next_audio = document.createElement("button"); + this.last_audio = document.createElement("button"); + this.first_audio.className = + "btn-default glyphicon glyphicon-fast-backward"; + this.prev_audio.className = + "btn-default glyphicon glyphicon-step-backward"; + this.pause_audio.className = "btn-default glyphicon glyphicon-pause"; + this.next_audio.className = + "btn-default glyphicon glyphicon-step-forward"; + this.last_audio.className = + "btn-default glyphicon glyphicon-fast-forward"; + this.first_audio.setAttribute( + "style", + "height: 22px; width: 25px; border-radius: 4px; margin-right:2px;" + ); + this.prev_audio.setAttribute( + "style", + "height: 22px; width: 25px; border-radius: 4px; margin-right:2px;" + ); + this.pause_audio.setAttribute( + "style", + "height: 22px; width: 25px; border-radius: 4px; margin-right:2px;" + ); + this.next_audio.setAttribute( + "style", + "height: 22px; width: 25px; border-radius: 4px; margin-right:2px;" + ); + this.last_audio.setAttribute( + "style", + "height: 22px; width: 25px; border-radius: 4px; margin-right:2px;" + ); + this.first_audio.name = "first_audio"; + this.prev_audio.name = "prev_audio"; + this.pause_audio.name = "pause_audio"; + this.next_audio.name = "next_audio"; + this.last_audio.name = "last_audio"; + this.first_audio.title = "Play first audio in tour"; + this.prev_audio.title = "Play previous audio in tour"; + this.pause_audio.title = "Pause current audio"; + this.next_audio.title = "Play next audio in tour"; + this.last_audio.title = "Play last audio in tour"; + this.first_audio.setAttribute("aria-label", "Play first audio in tour"); + this.prev_audio.setAttribute( + "aria-label", + "Play previous audio in tour" + ); + this.pause_audio.setAttribute("aria-label", "Pause audio"); + this.next_audio.setAttribute("aria-label", "Play next audio in tour"); + this.last_audio.setAttribute("aria-label", "Play last audio in tour"); + this.first_audio.disabled = true; + this.prev_audio.disabled = true; + this.pause_audio.disabled = true; + this.next_audio.disabled = true; + this.last_audio.disabled = true; + this.status = document.createElement("div"); + this.status.className = "alert alert-info"; + this.status.setAttribute("style", "display: none;"); + this.stop_button = document.createElement("button"); + this.stop_button.className = "btn btn-default"; + this.stop_button.innerHTML = "Stop tour"; + $(this.audio_tour).append( + this.audio_code, + this.windowcode, + document.createElement("br"), + this.first_audio, + this.prev_audio, + this.pause_audio, + this.next_audio, + this.last_audio, + document.createElement("br"), + this.status, + document.createElement("br"), + this.tourButtons, + this.stop_button + ); + $("#" + divid + " .ac_code_div").append(this.audio_tour); + $("#" + divid + " .ac_code_div").css("width", "50%"); + $("#" + divid + " .CodeMirror.cm-s-default.ui-resizable").hide(); + $("#" + divid + " .ac_opt.btn.btn-default:last-child").hide(); + $(this.stop_button).click( + function() { + if (this.playing) { + this.elem.pause(); + } + //log change to db + this.logBookEvent({ + event: "Audio", + act: "closeWindow", + div_id: divid + }); + $(this.audio_tour).remove(); + $( + "#" + divid + " .CodeMirror.cm-s-default.ui-resizable" + ).show(); + $("#" + divid + " .ac_opt.btn.btn-default:last-child").show(); + $("#" + divid + " .ac_code_div").css("width", ""); + }.bind(this) + ); + $(this.tourButtons[0]).click( + function() { + this.tour(divid, audio_hash[0], bcount); + }.bind(this) + ); + $(this.tourButtons[1]).click( + function() { + this.tour(divid, audio_hash[1], bcount); + }.bind(this) + ); + $(this.tourButtons[2]).click( + function() { + this.tour(divid, audio_hash[2], bcount); + }.bind(this) + ); + $(this.tourButtons[3]).click( + function() { + this.tour(divid, audio_hash[3], bcount); + }.bind(this) + ); + $(this.tourButtons[4]).click( + function() { + this.tour(divid, audio_hash[4], bcount); + }.bind(this) + ); + // handle the click to go to the next audio + $(this.first_audio).click( + function() { + this.firstAudio(); + }.bind(this) + ); + // handle the click to go to the next audio + $(this.prev_audio).click( + function() { + this.prevAudio(); + }.bind(this) + ); + // handle the click to pause or play the audio + $(this.pause_audio).click( + function() { + this.pauseAndPlayAudio(divid); + }.bind(this) + ); + // handle the click to go to the next audio + $(this.next_audio).click( + function() { + this.nextAudio(); + }.bind(this) + ); + // handle the click to go to the next audio + $(this.last_audio).click( + function() { + this.lastAudio(); + }.bind(this) + ); + // make the image buttons look disabled + $(this.first_audio).css("opacity", 0.25); + $(this.prev_audio).css("opacity", 0.25); + $(this.pause_audio).css("opacity", 0.25); + $(this.next_audio).css("opacity", 0.25); + $(this.last_audio).css("opacity", 0.25); } - var first = - "
" + "1. " + codeArray[0] + "
"; - var num_lines = codeArray.length; - for (var i = 1; i < num_lines; i++) { - if (i < 9) { - first = - first + - "
" + - (i + 1) + - ". " + - codeArray[i] + - "
"; - } else if (i < 99) { - first = - first + - "
" + - (i + 1) + - ". " + - codeArray[i] + - "
"; - } else { - first = - first + - "
" + - (i + 1) + - ". " + - codeArray[i] + - "
"; - } + tour(divid, audio_type, bcount) { + // set globals + this.buttonCount = bcount; + this.theDivid = divid; + this.status.setAttribute( + "style", + "display: inline-block; margin-top: 7px; margin-bottom: 3px;" + ); + // enable prev, pause/play and next buttons and make visible + $(this.first_audio).removeAttr("disabled"); + $(this.prev_audio).removeAttr("disabled"); + $(this.pause_audio).removeAttr("disabled"); + $(this.next_audio).removeAttr("disabled"); + $(this.last_audio).removeAttr("disabled"); + $(this.first_audio).css("opacity", 1.0); + $(this.prev_audio).css("opacity", 1.0); + $(this.pause_audio).css("opacity", 1.0); + $(this.next_audio).css("opacity", 1.0); + $(this.last_audio).css("opacity", 1.0); + // disable tour buttons + for (var i = 0; i < bcount; i++) + $(this.tourButtons[i]).attr("disabled", "disabled"); + var atype = audio_type.split(";"); + var name = atype[0].replaceAll('"', " "); + this.tourName = name; + $(this.status).html($.i18n("msg_activecode_starting", name)); + //log tour type to db + this.logBookEvent({ event: "Audio", act: name, div_id: divid }); + var max = atype.length; + var str = ""; + this.ahash = []; + this.aname = []; + for (i = 1; i < max - 1; i++) { + var temp = atype[i].split(":"); + var temp_line = temp[0]; + var temp_aname = temp[1]; + var akey = temp_aname.substring(1, temp_aname.length); + var lnums = temp_line.substring(1, temp_line.length); + //alert("akey:"+akey+"lnum:"+lnums); + // str+=""; + var dir = + "http://media.interactivepython.org/" + + eBookConfig.basecourse.toLowerCase() + + "/audio/"; + //var dir = "../_static/audio/" + str += ""; + this.ahash[akey] = lnums; + this.aname.push(akey); + } + $(this.audio_code).html(str); + this.len = this.aname.length; // set the number of audio file in the tour + this.currIndex = 0; + this.playCurrIndexAudio(); } - first = first + "
"; - //laying out the HTML content - var bcount = 0; - for (var i = 0; i < audio_type.length - 1; i++) { - var newButton = document.createElement("button"); - newButton.className = "btn btn-success"; - newButton.innerHTML = bval[i].replace(/\"/g, ""); - this.tourButtons.push(newButton); - bcount++; + handlePlaying() { + this.elem.pause(); + // unbind current ended + $("#" + this.afile).unbind("ended"); + // unhighlight the prev lines + this.unhighlightLines( + this.theDivid, + this.ahash[this.aname[this.currIndex]] + ); } - this.audio_tour = document.createElement("div"); - this.audio_tour.align = "center"; - this.audio_code = document.createElement("p"); - this.windowcode = document.createElement("div"); - this.windowcode.align = "left"; - $(this.windowcode).html(first); - this.first_audio = document.createElement("button"); - this.prev_audio = document.createElement("button"); - this.pause_audio = document.createElement("button"); - this.next_audio = document.createElement("button"); - this.last_audio = document.createElement("button"); - this.first_audio.className = - "btn-default glyphicon glyphicon-fast-backward"; - this.prev_audio.className = "btn-default glyphicon glyphicon-step-backward"; - this.pause_audio.className = "btn-default glyphicon glyphicon-pause"; - this.next_audio.className = "btn-default glyphicon glyphicon-step-forward"; - this.last_audio.className = "btn-default glyphicon glyphicon-fast-forward"; - this.first_audio.setAttribute( - "style", - "height: 22px; width: 25px; border-radius: 4px; margin-right:2px;" - ); - this.prev_audio.setAttribute( - "style", - "height: 22px; width: 25px; border-radius: 4px; margin-right:2px;" - ); - this.pause_audio.setAttribute( - "style", - "height: 22px; width: 25px; border-radius: 4px; margin-right:2px;" - ); - this.next_audio.setAttribute( - "style", - "height: 22px; width: 25px; border-radius: 4px; margin-right:2px;" - ); - this.last_audio.setAttribute( - "style", - "height: 22px; width: 25px; border-radius: 4px; margin-right:2px;" - ); - this.first_audio.name = "first_audio"; - this.prev_audio.name = "prev_audio"; - this.pause_audio.name = "pause_audio"; - this.next_audio.name = "next_audio"; - this.last_audio.name = "last_audio"; - this.first_audio.title = "Play first audio in tour"; - this.prev_audio.title = "Play previous audio in tour"; - this.pause_audio.title = "Pause current audio"; - this.next_audio.title = "Play next audio in tour"; - this.last_audio.title = "Play last audio in tour"; - this.first_audio.setAttribute("aria-label", "Play first audio in tour"); - this.prev_audio.setAttribute("aria-label", "Play previous audio in tour"); - this.pause_audio.setAttribute("aria-label", "Pause audio"); - this.next_audio.setAttribute("aria-label", "Play next audio in tour"); - this.last_audio.setAttribute("aria-label", "Play last audio in tour"); - this.first_audio.disabled = true; - this.prev_audio.disabled = true; - this.pause_audio.disabled = true; - this.next_audio.disabled = true; - this.last_audio.disabled = true; - this.status = document.createElement("div"); - this.status.className = "alert alert-info"; - this.status.setAttribute("style", "display: none;"); - this.stop_button = document.createElement("button"); - this.stop_button.className = "btn btn-default"; - this.stop_button.innerHTML = "Stop tour"; - $(this.audio_tour).append( - this.audio_code, - this.windowcode, - document.createElement("br"), - this.first_audio, - this.prev_audio, - this.pause_audio, - this.next_audio, - this.last_audio, - document.createElement("br"), - this.status, - document.createElement("br"), - this.tourButtons, - this.stop_button - ); - $("#" + divid + " .ac_code_div").append(this.audio_tour); - $("#" + divid + " .ac_code_div").css("width", "50%"); - $("#" + divid + " .CodeMirror.cm-s-default.ui-resizable").hide(); - $("#" + divid + " .ac_opt.btn.btn-default:last-child").hide(); - $(this.stop_button).click( - function() { - if (this.playing) { - this.elem.pause(); + firstAudio() { + // if audio is this.playing handle it + this.handlePlaying(); + //log change to db + this.logBookEvent({ + event: "Audio", + act: "first", + div_id: this.theDivid + }); + // move to the first audio + this.currIndex = 0; + // start at the first audio + this.playCurrIndexAudio(); + } + prevAudio() { + // if there is a previous audio + if (this.currIndex > 0) { + // if audio is this.playing handle it + this.handlePlaying(); + //log change to db + this.logBookEvent({ + event: "Audio", + act: "prev", + div_id: this.theDivid + }); + // move to previous to the current (but the current index has moved to the next) + this.currIndex = this.currIndex - 1; + // start at the prev audio + this.playCurrIndexAudio(); } + } + nextAudio() { + // if audio is this.playing handle it + this.handlePlaying(); //log change to db this.logBookEvent({ - event: "Audio", - act: "closeWindow", - div_id: divid + event: "Audio", + act: "next", + div_id: this.theDivid }); - $(this.audio_tour).remove(); - $("#" + divid + " .CodeMirror.cm-s-default.ui-resizable").show(); - $("#" + divid + " .ac_opt.btn.btn-default:last-child").show(); - $("#" + divid + " .ac_code_div").css("width", ""); - }.bind(this) - ); - $(this.tourButtons[0]).click( - function() { - this.tour(divid, audio_hash[0], bcount); - }.bind(this) - ); - $(this.tourButtons[1]).click( - function() { - this.tour(divid, audio_hash[1], bcount); - }.bind(this) - ); - $(this.tourButtons[2]).click( - function() { - this.tour(divid, audio_hash[2], bcount); - }.bind(this) - ); - $(this.tourButtons[3]).click( - function() { - this.tour(divid, audio_hash[3], bcount); - }.bind(this) - ); - $(this.tourButtons[4]).click( - function() { - this.tour(divid, audio_hash[4], bcount); - }.bind(this) - ); - // handle the click to go to the next audio - $(this.first_audio).click( - function() { - this.firstAudio(); - }.bind(this) - ); - // handle the click to go to the next audio - $(this.prev_audio).click( - function() { - this.prevAudio(); - }.bind(this) - ); - // handle the click to pause or play the audio - $(this.pause_audio).click( - function() { - this.pauseAndPlayAudio(divid); - }.bind(this) - ); - // handle the click to go to the next audio - $(this.next_audio).click( - function() { - this.nextAudio(); - }.bind(this) - ); - // handle the click to go to the next audio - $(this.last_audio).click( - function() { - this.lastAudio(); - }.bind(this) - ); - // make the image buttons look disabled - $(this.first_audio).css("opacity", 0.25); - $(this.prev_audio).css("opacity", 0.25); - $(this.pause_audio).css("opacity", 0.25); - $(this.next_audio).css("opacity", 0.25); - $(this.last_audio).css("opacity", 0.25); - } - tour(divid, audio_type, bcount) { - // set globals - this.buttonCount = bcount; - this.theDivid = divid; - this.status.setAttribute( - "style", - "display: inline-block; margin-top: 7px; margin-bottom: 3px;" - ); - // enable prev, pause/play and next buttons and make visible - $(this.first_audio).removeAttr("disabled"); - $(this.prev_audio).removeAttr("disabled"); - $(this.pause_audio).removeAttr("disabled"); - $(this.next_audio).removeAttr("disabled"); - $(this.last_audio).removeAttr("disabled"); - $(this.first_audio).css("opacity", 1.0); - $(this.prev_audio).css("opacity", 1.0); - $(this.pause_audio).css("opacity", 1.0); - $(this.next_audio).css("opacity", 1.0); - $(this.last_audio).css("opacity", 1.0); - // disable tour buttons - for (var i = 0; i < bcount; i++) - $(this.tourButtons[i]).attr("disabled", "disabled"); - var atype = audio_type.split(";"); - var name = atype[0].replaceAll('"', " "); - this.tourName = name; - $(this.status).html($.i18n("msg_activecode_starting", name)); - //log tour type to db - this.logBookEvent({ event: "Audio", act: name, div_id: divid }); - var max = atype.length; - var str = ""; - this.ahash = []; - this.aname = []; - for (i = 1; i < max - 1; i++) { - var temp = atype[i].split(":"); - var temp_line = temp[0]; - var temp_aname = temp[1]; - var akey = temp_aname.substring(1, temp_aname.length); - var lnums = temp_line.substring(1, temp_line.length); - //alert("akey:"+akey+"lnum:"+lnums); - // str+=""; - var dir = - "http://media.interactivepython.org/" + - eBookConfig.basecourse.toLowerCase() + - "/audio/"; - //var dir = "../_static/audio/" - str += ""; - this.ahash[akey] = lnums; - this.aname.push(akey); + // if not at the end + if (this.currIndex < this.len - 1) { + // start at the next audio + this.currIndex = this.currIndex + 1; + this.playCurrIndexAudio(); + } else if (this.currIndex == this.len - 1) { + this.handleTourEnd(); + } } - $(this.audio_code).html(str); - this.len = this.aname.length; // set the number of audio file in the tour - this.currIndex = 0; - this.playCurrIndexAudio(); - } - handlePlaying() { - this.elem.pause(); - // unbind current ended - $("#" + this.afile).unbind("ended"); - // unhighlight the prev lines - this.unhighlightLines( - this.theDivid, - this.ahash[this.aname[this.currIndex]] - ); - } - firstAudio() { - // if audio is this.playing handle it - this.handlePlaying(); - //log change to db - this.logBookEvent({ event: "Audio", act: "first", div_id: this.theDivid }); - // move to the first audio - this.currIndex = 0; - // start at the first audio - this.playCurrIndexAudio(); - } - prevAudio() { - // if there is a previous audio - if (this.currIndex > 0) { - // if audio is this.playing handle it - this.handlePlaying(); - //log change to db - this.logBookEvent({ event: "Audio", act: "prev", div_id: this.theDivid }); - // move to previous to the current (but the current index has moved to the next) - this.currIndex = this.currIndex - 1; - // start at the prev audio - this.playCurrIndexAudio(); + lastAudio() { + // if audio is this.playing handle it + this.handlePlaying(); + //log change to db + this.logBookEvent({ + event: "Audio", + act: "last", + div_id: this.theDivid + }); + // move to the last audio + this.currIndex = this.len - 1; + // start at last + this.playCurrIndexAudio(); } - } - nextAudio() { - // if audio is this.playing handle it - this.handlePlaying(); - //log change to db - this.logBookEvent({ event: "Audio", act: "next", div_id: this.theDivid }); - // if not at the end - if (this.currIndex < this.len - 1) { - // start at the next audio - this.currIndex = this.currIndex + 1; - this.playCurrIndexAudio(); - } else if (this.currIndex == this.len - 1) { - this.handleTourEnd(); + // play the audio at the current index + playCurrIndexAudio() { + // set this.playing to false + this.playing = false; + // play the current audio and highlight the lines + this.playaudio(this.currIndex, this.aname, this.theDivid, this.ahash); } - } - lastAudio() { - // if audio is this.playing handle it - this.handlePlaying(); - //log change to db - this.logBookEvent({ event: "Audio", act: "last", div_id: this.theDivid }); - // move to the last audio - this.currIndex = this.len - 1; - // start at last - this.playCurrIndexAudio(); - } - // play the audio at the current index - playCurrIndexAudio() { - // set this.playing to false - this.playing = false; - // play the current audio and highlight the lines - this.playaudio(this.currIndex, this.aname, this.theDivid, this.ahash); - } - // handle the end of the tour - handleTourEnd() { - $(this.status).html("The " + this.tourName + " has ended."); - this.pause_audio.className = "btn-default glyphicon glyphicon-pause"; - this.pause_audio.title = "Pause audio"; - this.pause_audio.setAttribute("aria-label", "Pause audio"); - $(this.first_audio).attr("disabled", "disabled"); - $(this.prev_audio).attr("disabled", "disabled"); - $(this.pause_audio).attr("disabled", "disabled"); - $(this.next_audio).attr("disabled", "disabled"); - $(this.last_audio).attr("disabled", "disabled"); - $(this.first_audio).css("opacity", 0.25); - $(this.prev_audio).css("opacity", 0.25); - $(this.pause_audio).css("opacity", 0.25); - $(this.next_audio).css("opacity", 0.25); - $(this.last_audio).css("opacity", 0.25); - // enable the tour buttons - for (var j = 0; j < this.buttonCount; j++) - $(this.tourButtons[j]).removeAttr("disabled"); - } - // only call this one after the first time - outerAudio() { - // unbind ended - $("#" + this.afile).unbind("ended"); - // set this.playing to false - this.playing = false; - // unhighlight previous lines from the last audio - this.unhighlightLines( - this.theDivid, - this.ahash[this.aname[this.currIndex]] - ); - // increment the this.currIndex to point to the next one - this.currIndex++; - // if the end of the tour reset the buttons - if (this.currIndex == this.len) { - this.handleTourEnd(); + // handle the end of the tour + handleTourEnd() { + $(this.status).html("The " + this.tourName + " has ended."); + this.pause_audio.className = "btn-default glyphicon glyphicon-pause"; + this.pause_audio.title = "Pause audio"; + this.pause_audio.setAttribute("aria-label", "Pause audio"); + $(this.first_audio).attr("disabled", "disabled"); + $(this.prev_audio).attr("disabled", "disabled"); + $(this.pause_audio).attr("disabled", "disabled"); + $(this.next_audio).attr("disabled", "disabled"); + $(this.last_audio).attr("disabled", "disabled"); + $(this.first_audio).css("opacity", 0.25); + $(this.prev_audio).css("opacity", 0.25); + $(this.pause_audio).css("opacity", 0.25); + $(this.next_audio).css("opacity", 0.25); + $(this.last_audio).css("opacity", 0.25); + // enable the tour buttons + for (var j = 0; j < this.buttonCount; j++) + $(this.tourButtons[j]).removeAttr("disabled"); } - // else not done yet so play the next audio - else { - // play the audio at the current index - this.playCurrIndexAudio(); + // only call this one after the first time + outerAudio() { + // unbind ended + $("#" + this.afile).unbind("ended"); + // set this.playing to false + this.playing = false; + // unhighlight previous lines from the last audio + this.unhighlightLines( + this.theDivid, + this.ahash[this.aname[this.currIndex]] + ); + // increment the this.currIndex to point to the next one + this.currIndex++; + // if the end of the tour reset the buttons + if (this.currIndex == this.len) { + this.handleTourEnd(); + } + // else not done yet so play the next audio + else { + // play the audio at the current index + this.playCurrIndexAudio(); + } } - } - // play the audio now that it is ready - playWhenReady(afile, divid, ahash) { - // unbind current - $("#" + afile).unbind("canplaythrough"); - this.elem.currentTime = 0; - this.playing = true; - //console.log("in playWhenReady " + elem.duration); - this.highlightLines(divid, ahash[afile]); - if ( - this.pause_audio.className === "btn-default glyphicon glyphicon-pause" - ) { - $(this.status).html($.i18n("msg_activecode_playing", this.tourName)); - $("#" + afile).bind( - "ended", - function() { - this.outerAudio(); - }.bind(this) - ); - this.elem.play(); - } else { - $("#" + afile).bind( - "ended", - function() { - this.outerAudio(); - }.bind(this) - ); + // play the audio now that it is ready + playWhenReady(afile, divid, ahash) { + // unbind current + $("#" + afile).unbind("canplaythrough"); + this.elem.currentTime = 0; + this.playing = true; + //console.log("in playWhenReady " + elem.duration); + this.highlightLines(divid, ahash[afile]); + if ( + this.pause_audio.className === + "btn-default glyphicon glyphicon-pause" + ) { + $(this.status).html( + $.i18n("msg_activecode_playing", this.tourName) + ); + $("#" + afile).bind( + "ended", + function() { + this.outerAudio(); + }.bind(this) + ); + this.elem.play(); + } else { + $("#" + afile).bind( + "ended", + function() { + this.outerAudio(); + }.bind(this) + ); + } } - } - // play the audio at the specified index i and set the duration and highlight the lines - playaudio(i, aname, divid, ahash) { - this.afile = aname[i]; - this.elem = document.getElementById(this.afile); - // if this isn't ready to play yet - no duration yet then wait - //console.log("in playaudio " + elem.duration); - if (isNaN(this.elem.duration) || this.elem.duration == 0) { - // set the status - $(this.status).html($.i18n("msg_activecode_loading_audio")); - $("#" + this.afile).bind( - "canplaythrough", - function() { - this.playWhenReady(this.afile, divid, ahash); - }.bind(this) - ); + // play the audio at the specified index i and set the duration and highlight the lines + playaudio(i, aname, divid, ahash) { + this.afile = aname[i]; + this.elem = document.getElementById(this.afile); + // if this isn't ready to play yet - no duration yet then wait + //console.log("in playaudio " + elem.duration); + if (isNaN(this.elem.duration) || this.elem.duration == 0) { + // set the status + $(this.status).html($.i18n("msg_activecode_loading_audio")); + $("#" + this.afile).bind( + "canplaythrough", + function() { + this.playWhenReady(this.afile, divid, ahash); + }.bind(this) + ); + } + // otherwise it is ready so play it + else { + this.playWhenReady(this.afile, divid, ahash); + } } - // otherwise it is ready so play it - else { - this.playWhenReady(this.afile, divid, ahash); + // pause if this.playing and play if paused + pauseAndPlayAudio(divid) { + var btn = this.pause_audio; + // if paused and clicked then continue from current + if (this.elem.paused) { + // calcualte the time left to play in milliseconds + counter = (this.elem.duration - this.elem.currentTime) * 1000; + this.elem.play(); // start the audio from current spot + this.pause_audio.className = + "btn-default glyphicon glyphicon-pause"; + this.pause_audio.title = $.i18n( + "msg_activecode_pause_current_audio" + ); + this.pause_audio.setAttribute( + "aria-label", + $.i18n("msg_activecode_pause_audio") + ); + $(this.status).html( + $.i18n("msg_activecode_playing", this.tourName) + ); + //log change to db + this.logBookEvent({ + event: "Audio", + act: "play", + div_id: this.theDivid + }); + } + // if audio was this.playing pause it + else if (this.playing) { + this.elem.pause(); // pause the audio + this.pause_audio.className = "btn-default glyphicon glyphicon-play"; + this.pause_audio.title = $.i18n("msg_activecode_play_paused_audio"); + this.pause_audio.setAttribute( + "aria-label", + $.i18n("msg_activecode_play_paused_audio") + ); + $(this.status).html( + $.i18n("msg_activecode_audio_paused", this.tourName) + ); + //log change to db + this.logBookEvent({ + event: "Audio", + act: "pause", + div_id: this.theDivid + }); + } } - } - // pause if this.playing and play if paused - pauseAndPlayAudio(divid) { - var btn = this.pause_audio; - // if paused and clicked then continue from current - if (this.elem.paused) { - // calcualte the time left to play in milliseconds - counter = (this.elem.duration - this.elem.currentTime) * 1000; - this.elem.play(); // start the audio from current spot - this.pause_audio.className = "btn-default glyphicon glyphicon-pause"; - this.pause_audio.title = $.i18n("msg_activecode_pause_current_audio"); - this.pause_audio.setAttribute( - "aria-label", - $.i18n("msg_activecode_pause_audio") - ); - $(this.status).html($.i18n("msg_activecode_playing", this.tourName)); - //log change to db - this.logBookEvent({ event: "Audio", act: "play", div_id: this.theDivid }); + // process the lines + processLines(divid, lnum, color) { + var comma = lnum.split(","); + if (comma.length > 1) { + for (i = 0; i < comma.length; i++) { + this.setBackgroundForLines(divid, comma[i], color); + } + } else { + this.setBackgroundForLines(divid, lnum, color); + } } - // if audio was this.playing pause it - else if (this.playing) { - this.elem.pause(); // pause the audio - this.pause_audio.className = "btn-default glyphicon glyphicon-play"; - this.pause_audio.title = $.i18n("msg_activecode_play_paused_audio"); - this.pause_audio.setAttribute( - "aria-label", - $.i18n("msg_activecode_play_paused_audio") - ); - $(this.status).html($.i18n("msg_activecode_audio_paused", this.tourName)); - //log change to db - this.logBookEvent({ - event: "Audio", - act: "pause", - div_id: this.theDivid - }); + // unhighlight the lines - set the background back to transparent + unhighlightLines(divid, lnum) { + this.processLines(divid, lnum, "transparent"); } - } - // process the lines - processLines(divid, lnum, color) { - var comma = lnum.split(","); - if (comma.length > 1) { - for (i = 0; i < comma.length; i++) { - this.setBackgroundForLines(divid, comma[i], color); - } - } else { - this.setBackgroundForLines(divid, lnum, color); + // highlight the lines - set the background to a yellow color + highlightLines(divid, lnum) { + this.processLines(divid, lnum, "#ffff99"); } - } - // unhighlight the lines - set the background back to transparent - unhighlightLines(divid, lnum) { - this.processLines(divid, lnum, "transparent"); - } - // highlight the lines - set the background to a yellow color - highlightLines(divid, lnum) { - this.processLines(divid, lnum, "#ffff99"); - } - // set the background to the passed color - setBackgroundForLines(divid, lnum, color) { - var hyphen = lnum.split("-"); - // if a range of lines - if (hyphen.length > 1) { - var start = parseInt(hyphen[0]); - var end = parseInt(hyphen[1]) + 1; - for (var k = start; k < end; k++) { - //alert(k); - var str = "#" + divid + "_l" + k; - if ($(str).text() != "") { - $(str).css("background-color", color); + // set the background to the passed color + setBackgroundForLines(divid, lnum, color) { + var hyphen = lnum.split("-"); + // if a range of lines + if (hyphen.length > 1) { + var start = parseInt(hyphen[0]); + var end = parseInt(hyphen[1]) + 1; + for (var k = start; k < end; k++) { + //alert(k); + var str = "#" + divid + "_l" + k; + if ($(str).text() != "") { + $(str).css("background-color", color); + } + //$(str).effect("highlight",{},(dur*1000)+4500); + } + } else { + //alert(lnum); + var str = "#" + divid + "_l" + lnum; + $(str).css("background-color", color); + //$(str).effect("highlight",{},(dur*1000)+4500); } - //$(str).effect("highlight",{},(dur*1000)+4500); - } - } else { - //alert(lnum); - var str = "#" + divid + "_l" + lnum; - $(str).css("background-color", color); - //$(str).effect("highlight",{},(dur*1000)+4500); } - } } diff --git a/runestone/activecode/js/livecode.js b/runestone/activecode/js/livecode.js index 9c3473ae4..4b9482de4 100644 --- a/runestone/activecode/js/livecode.js +++ b/runestone/activecode/js/livecode.js @@ -85,7 +85,7 @@ export default class LiveCode extends ActiveCode { if (this.datafile != undefined) { var ids = this.datafile.split(","); for (var i = 0; i < ids.length; i++) { - file = document.getElementById(ids[i].trim()); + let file = document.getElementById(ids[i].trim()); if (file === null || file === undefined) { // console.log("No file with given id"); } else if (file.className === "javaFiles") { @@ -107,7 +107,7 @@ export default class LiveCode extends ActiveCode { } } } - runspec = { + let runspec = { language_id: this.language, sourcecode: source, parameters: paramobj, @@ -117,7 +117,7 @@ export default class LiveCode extends ActiveCode { runspec.input = stdin; } if (files.length === 0) { - data = JSON.stringify({ run_spec: runspec }); + let data = JSON.stringify({ run_spec: runspec }); this.runProg_callback(data); } else { runspec["file_list"] = []; @@ -142,7 +142,7 @@ export default class LiveCode extends ActiveCode { }) ); } - data = JSON.stringify({ run_spec: runspec }); + let data = JSON.stringify({ run_spec: runspec }); this.div2id = instance.div2id; Promise.all(promises) .then(function() { @@ -171,6 +171,7 @@ export default class LiveCode extends ActiveCode { }; source = this.editor.getValue(); xhr = new XMLHttpRequest(); + var result; host = this.JOBE_SERVER + this.resource; var odiv = this.output; $(this.runButton).attr("disabled", "disabled"); @@ -185,7 +186,7 @@ export default class LiveCode extends ActiveCode { var logresult; $(this.runButton).removeAttr("disabled"); try { - var result = JSON.parse(xhr.responseText); + result = JSON.parse(xhr.responseText); } catch (e) { result = {}; result.outcome = -1; @@ -422,7 +423,7 @@ export default class LiveCode extends ActiveCode { } } if (found && stack === 0) { - endIndex = i + 1; + let endIndex = i + 1; var words = text .substring(endOfLastCommentBeforeClassBegins, startIndex) .trim() diff --git a/runestone/activecode/js/timed_activecode.js b/runestone/activecode/js/timed_activecode.js index 44cf3f2b4..dd6a13c9a 100644 --- a/runestone/activecode/js/timed_activecode.js +++ b/runestone/activecode/js/timed_activecode.js @@ -16,7 +16,7 @@ var TimedActiveCodeMixin = { this.isTimed = true; this.needsReinitialization = true; // the run button click listener needs to be reinitialized this.containerDiv.classList.add("timedComponent"); - edList[this.divid] = this; + window.edList[this.divid] = this; }, hideButtons: function() { diff --git a/runestone/parsons/js/timedparsons.js b/runestone/parsons/js/timedparsons.js index f80c0f3a8..5c9549146 100644 --- a/runestone/parsons/js/timedparsons.js +++ b/runestone/parsons/js/timedparsons.js @@ -1,6 +1,6 @@ import Parsons from "./parsons"; -class TimedParsons extends Parsons { +export default class TimedParsons extends Parsons { constructor(opts) { super(opts); } diff --git a/runestone/timed/js/timed.js b/runestone/timed/js/timed.js index d0aaeaf81..c590aadaa 100644 --- a/runestone/timed/js/timed.js +++ b/runestone/timed/js/timed.js @@ -17,6 +17,7 @@ import TimedShortAnswer from "../../shortanswer/js/timed_shortanswer.js"; import ACFactory from "../../activecode/js/acfactory.js"; import TimedClickableArea from "../../clickableArea/js/timedclickable"; import TimedDragNDrop from "../../dragndrop/js/timeddnd.js"; +import TimedParsons from "../../parsons/js/timedparsons.js"; export var TimedList = {}; // Timed dictionary