From ede956e1d654da3097e55361f5e4e83184a06b9b Mon Sep 17 00:00:00 2001 From: benmcmahon100 Date: Sun, 23 Aug 2015 21:59:29 +0100 Subject: [PATCH] Merge of the frameworks: an unexpected merge --- public/js/lib/coursewares/commonFrameWork.js | 469 ++++++++++++++++++ .../coursewaresHCJQFramework_0.1.9.js | 280 ----------- .../coursewaresJSFramework_0.0.6.js | 394 --------------- server/views/coursewares/showHTML.jade | 11 +- server/views/coursewares/showJS.jade | 4 +- 5 files changed, 479 insertions(+), 679 deletions(-) create mode 100644 public/js/lib/coursewares/commonFrameWork.js delete mode 100644 public/js/lib/coursewares/coursewaresHCJQFramework_0.1.9.js delete mode 100644 public/js/lib/coursewares/coursewaresJSFramework_0.0.6.js diff --git a/public/js/lib/coursewares/commonFrameWork.js b/public/js/lib/coursewares/commonFrameWork.js new file mode 100644 index 0000000000..a2717ca7e1 --- /dev/null +++ b/public/js/lib/coursewares/commonFrameWork.js @@ -0,0 +1,469 @@ +var editor; +var widgets = []; +editor = CodeMirror.fromTextArea(document.getElementById("codeEditor"), { + lineNumbers: true, + mode: "text", + theme: 'monokai', + runnable: true, + matchBrackets: true, + autoCloseBrackets: true, + scrollbarStyle: 'null', + lineWrapping: true, + gutters: ["CodeMirror-lint-markers"], + onKeyEvent: doLinting +}); + +var myCodeMirror = editor; + +var codeStorage = { + version: 0.01, + keyVersion:"saveVersion", + keyValue: null,//where the value of the editor is saved + updateWait: 2000,// 2 seconds + updateTimeoutId: null, + eventArray: []//for firing saves +}; +codeStorage.hasSaved = function(){ + return ( updateTimeoutId === null ); +}; +codeStorage.onSave = function(func){ + codeStorage.eventArray.push(func); +}; +codeStorage.setSaveKey = function(key){ + codeStorage.keyValue = key + 'Val'; +}; +codeStorage.getEditorValue = function(){ + return ('' + localStorage.getItem(codeStorage.keyValue)); +}; + +codeStorage.isAlive = function() { + var val = this.getEditorValue(); + return val !== 'null' && + val !== 'undefined' && + (val && val.length > 0); +}; +codeStorage.updateStorage = function(){ + if(typeof(Storage) !== undefined) { + var value = editor.getValue(); + localStorage.setItem(codeStorage.keyValue, value); + } else { + var debugging = false; + if( debugging ){ + console.log('no web storage'); + } + } + codeStorage.updateTimeoutId = null; + codeStorage.eventArray.forEach(function(func){ + func(); + }); +}; +(function(){ + var savedVersion = localStorage.getItem('saveVersion'); + if( savedVersion === null ){ + localStorage.setItem(codeStorage.keyVersion, codeStorage.version);//just write current version + }else{ + if( savedVersion !== codeStorage.version ){ + //Update version + } + } +})(); +codeStorage.setSaveKey(challenge_Name); +editor.on('keyup', function(){ + window.clearTimeout(codeStorage.updateTimeoutId); + codeStorage.updateTimeoutId = window.setTimeout(codeStorage.updateStorage, codeStorage.updateWait); +}); +var editorValue; +var challengeSeed = challengeSeed || null; +var tests = tests || []; +var allSeeds = ''; +(function() { + challengeSeed.forEach(function(elem) { + allSeeds += elem + '\n'; + }); +})(); + +function doLinting() { + editor.operation(function() { + for (var i = 0; i < widgets.length; ++i) + editor.removeLineWidget(widgets[i]); + widgets.length = 0; + JSHINT(editor.getValue()); + for (var i = 0; i < JSHINT.errors.length; ++i) { + var err = JSHINT.errors[i]; + if (!err) continue; + var msg = document.createElement("div"); + var icon = msg.appendChild(document.createElement("span")); + icon.innerHTML = "!!"; + icon.className = "lint-error-icon"; + msg.appendChild(document.createTextNode(err.reason)); + msg.className = "lint-error"; + widgets.push(editor.addLineWidget(err.line - 1, msg, { + coverGutter: false, + noHScroll: true + })); + } + }); +} + +/*var defaultKeymap = { + 'Cmd-E': 'emmet.expand_abbreviation', + 'Tab': 'emmet.expand_abbreviation_with_tab', + 'Enter': 'emmet.insert_formatted_line_break_only' + }; + + emmetCodeMirror(editor, defaultKeymap);*/ + +// Hijack tab key to insert two spaces instead +editor.setOption("extraKeys", { + Tab: function(cm) { + if (cm.somethingSelected()){ + cm.indentSelection("add"); + } else { + var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); + cm.replaceSelection(spaces); + } + }, + "Shift-Tab": function(cm) { + if (cm.somethingSelected()){ + cm.indentSelection("subtract"); + } else { + var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); + cm.replaceSelection(spaces); + } + }, + "Ctrl-Enter": function() { + bonfireExecute(); + return false; + } +}); + +editor.setSize("100%", "auto"); + +var libraryIncludes = "" + + "" + + "" + + "" + + "" + + "" + + "" + + "" + + ""; + + +var editorValueForIFrame; +var iFrameScript = ""; + +var delay; +// Initialize CodeMirror editor with a nice html5 canvas demo. +editor.on("keyup", function () { + clearTimeout(delay); + delay = setTimeout(updatePreview, 300); +}); + +if(typeof prodOrDev !== 'undefined') { + var nodeEnv = prodOrDev === 'production' ? 'http://www.freecodecamp.com' : 'http://localhost:3001'; + + function updatePreview() { + editorValueForIFrame = editor.getValue(); + var failedCommentTest = false; + if (editorValueForIFrame.match(/\<\!\-\-/gi) && editorValueForIFrame.match(/\-\-\>/gi) == null) { + failedCommentTest = true; + } + else if (editorValueForIFrame.match(/\<\!\-\-/gi) && editorValueForIFrame.match(/\<\!\-\-/gi).length > editorValueForIFrame.match(/\-\-\>/gi).length) { + failedCommentTest = true; + } + if (failedCommentTest) { + editor.setValue(editor.getValue() + "-->"); + editorValueForIFrame = editorValueForIFrame + "-->"; + } + goodTests = 0; + var previewFrame = document.getElementById('preview'); + var preview = previewFrame.contentDocument || previewFrame.contentWindow.document; + preview.open(); + preview.write(libraryIncludes + editor.getValue()); + codeStorage.updateStorage(); + preview.close(); + + } + + setTimeout(updatePreview, 300); +} +/** + * "post" methods + */ + +var testResults = []; +var postSuccess = function(data) { + var testDoc = document.createElement("div"); + $(testDoc) + .html("
" + JSON.parse(data) + "
"); + $('#testSuite').append(testDoc); + testSuccess(); +}; + +var postError = function(data) { + var testDoc = document.createElement("div"); + $(testDoc) + .html("
" + JSON.parse(data) + "
"); + $('#testSuite').append(testDoc); +}; +var goodTests = 0; +var testSuccess = function() { + goodTests++; + if (goodTests === tests.length) { + showCompletion(); + } +}; + +function showCompletion() { + var time = Math.floor(Date.now()) - started; + ga('send', 'event', 'Challenge', 'solved', challenge_Name + ', Time: ' + time + + ', Attempts: ' + attempts); + var bonfireSolution = myCodeMirror.getValue(); + var didCompleteWith = $('#completed-with').val() || null; + $.post( + '/completed-bonfire/', { + challengeInfo: { + challengeId: challenge_Id, + challengeName: challenge_Name, + completedWith: didCompleteWith, + challengeType: challengeType, + solution: bonfireSolution + } + }, + function(res) { + if (res) { + $('#complete-courseware-dialog').modal('show'); + $('#complete-courseware-dialog').keydown(function(e) { + if (e.ctrlKey && e.keyCode == 13) { + $('#next-courseware-button').click(); + } + }); + } + } + ); +} + +var resetEditor = function resetEditor() { + editor.setValue(allSeeds.replace((/fccss/gi), '')); + updatePreview(); + codeStorage.updateStorage(); +}; + +var attempts = 0; +if (attempts) { + attempts = 0; +} + +console.log(challengeType); +if(challengeType !== "0") { + var codeOutput = CodeMirror.fromTextArea(document.getElementById("codeOutput"), { + lineNumbers: false, + mode: "text", + theme: 'monokai', + readOnly: 'nocursor', + lineWrapping: true + }); + + codeOutput.setValue('/**\n' + + ' * Your output will go here.\n' + ' * Console.log() -type statements\n' + + ' * will appear in your browser\'s\n' + ' * DevTools JavaScript console.\n' + + ' */'); + codeOutput.setSize("100%", "100%"); +} +var info = editor.getScrollInfo(); +var after = editor.charCoords({ + line: editor.getCursor().line + 1, + ch: 0 +}, "local").top; +if (info.top + info.clientHeight < after) + editor.scrollTo(null, after - info.clientHeight + 3); + +var userTests; +var testSalt = Math.random(); + + +var scrapeTests = function(userJavaScript) { + + // insert tests from mongo + for (var i = 0; i < tests.length; i++) { + userJavaScript += '\n' + tests[i]; + } + + var counter = 0; + var regex = new RegExp( + /(expect(\s+)?\(.*\;)|(assert(\s+)?\(.*\;)|(assert\.\w.*\;)|(.*\.should\..*\;)/ + ); + var match = regex.exec(userJavaScript); + while (match != null) { + var replacement = '//' + counter + testSalt; + userJavaScript = userJavaScript.substring(0, match.index) + replacement + + userJavaScript.substring(match.index + match[0].length); + + if (!userTests) { + userTests = []; + } + userTests.push({ + "text": match[0], + "line": counter, + "err": null + }); + counter++; + match = regex.exec(userJavaScript); + } + + return userJavaScript; +}; + +function removeComments(userJavaScript) { + var regex = new RegExp(/(\/\*[^(\*\/)]*\*\/)|\/\/[^\n]*/g); + return userJavaScript.replace(regex, ''); +} + +function removeLogs(userJavaScript) { + return userJavaScript.replace(/(console\.[\w]+\s*\(.*\;)/g, ''); +} + +var pushed = false; +var createTestDisplay = function() { + if (pushed) { + userTests.pop(); + } + for (var i = 0; i < userTests.length; i++) { + var test = userTests[i]; + var testDoc = document.createElement("div"); + if (test.err != null) { + console.log('Should be displaying bad tests'); + $(testDoc) + .html( + "
" + + test.text + "
" + + test.err + "
") + .appendTo($('#testSuite')); + } else { + $(testDoc) + .html( + "
" + + test.text + "
") + .appendTo($('#testSuite')); + } + }; +}; + +var expect = chai.expect; +var assert = chai.assert; +var should = chai.should(); + + +var reassembleTest = function(test, data) { + var lineNum = test.line; + var regexp = new RegExp("\/\/" + lineNum + testSalt); + return data.input.replace(regexp, test.text); +}; + +var runTests = function(err, data) { + //userTests = userTests ? null : []; + var allTestsPassed = true; + pushed = false; + $('#testSuite').children().remove(); + if (err && userTests.length > 0) { + userTests = [{ + text: "Program Execution Failure", + err: "No user tests were run." + }]; + createTestDisplay(); + } + //Add blocks to test exploits here! + else if(editorValue.match(/if\s\(null\)\sconsole\.log\(1\);/gi)){ + allTestsPassed = false; + userTests = [{ + text: "Program Execution Failure", + err: "Invalid if (null) console.log(1); detected" + }]; + createTestDisplay(); + } + else if (userTests) { + userTests.push(false); + pushed = true; + userTests.forEach(function(chaiTestFromJSON, indexOfTestArray, + __testArray) { + try { + if (chaiTestFromJSON) { + var output = eval(reassembleTest(chaiTestFromJSON, data)); + } + } catch (error) { + allTestsPassed = false; + __testArray[indexOfTestArray].err = error.message; + } finally { + if (!chaiTestFromJSON) { + createTestDisplay(); + } + } + }); + + if (allTestsPassed) { + allTestsPassed = false; + showCompletion(); + } + + } +}; + +function bonfireExecute() { + attempts++; + ga('send', 'event', 'Challenge', 'ran-code', challenge_Name); + userTests = null; + if(challengeType === "0"){ + $('#testSuite').empty(); + + editorValueForIFrame = editor.getValue(); + goodTests = 0; + var previewFrame = document.getElementById('preview'); + var preview = previewFrame.contentDocument || previewFrame.contentWindow.document; + preview.open(); + preview.write(libraryIncludes + editor.getValue() + ""); + codeStorage.updateStorage(); + preview.close(); + } + else { + var userJavaScript = myCodeMirror.getValue(); + var failedCommentTest = false; + if (userJavaScript.match(/\/\*/gi) && userJavaScript.match(/\*\//gi) == null) { + failedCommentTest = true; + } + else if (!failedCommentTest && userJavaScript.match(/\/\*/gi) && userJavaScript.match(/\/\*/gi).length > userJavaScript.match(/\*\//gi).length) { + failedCommentTest = true; + } + userJavaScript = removeComments(userJavaScript); + userJavaScript = scrapeTests(userJavaScript); + // simple fix in case the user forgets to invoke their function + + submit(userJavaScript, function (cls, message) { + if (failedCommentTest) { + myCodeMirror.setValue(myCodeMirror.getValue() + "*/"); + console.log('Caught Unfinished Comment'); + codeOutput.setValue("Unfinished mulit-line comment"); + failedCommentTest = false; + } + else if (cls) { + codeOutput.setValue(message.error); + runTests('Error', null); + } else { + codeOutput.setValue(message.output); + codeOutput.setValue(codeOutput.getValue().replace(/\\\"/gi, '')); + message.input = removeLogs(message.input); + runTests(null, message); + } + }); + } +} + +$('#submitButton').on('click', function() { + bonfireExecute(); +}); + +$(document).ready(function(){ + editorValue = (codeStorage.isAlive())? codeStorage.getEditorValue() : allSeeds; + myCodeMirror.setValue(editorValue); + bonfireExecute(); +}); diff --git a/public/js/lib/coursewares/coursewaresHCJQFramework_0.1.9.js b/public/js/lib/coursewares/coursewaresHCJQFramework_0.1.9.js deleted file mode 100644 index 89dc0d9dd6..0000000000 --- a/public/js/lib/coursewares/coursewaresHCJQFramework_0.1.9.js +++ /dev/null @@ -1,280 +0,0 @@ -/** - * Created by nathanleniz on 2/2/15. - */ - -var widgets = []; -var editor = CodeMirror.fromTextArea(document.getElementById("codeEditor"), { - lineNumbers: true, - mode: "text/html", - theme: 'monokai', - runnable: true, - matchBrackets: true, - autoCloseBrackets: true, - scrollbarStyle: 'null', - lineWrapping: true, - gutters: ["CodeMirror-lint-markers"], - onKeyEvent: doLinting -}); - -var defaultKeymap = { - 'Cmd-E': 'emmet.expand_abbreviation', - 'Tab': 'emmet.expand_abbreviation_with_tab', - 'Enter': 'emmet.insert_formatted_line_break_only' -}; - -emmetCodeMirror(editor, defaultKeymap); - - -// Hijack tab key to insert two spaces instead -editor.setOption("extraKeys", { - Tab: function(cm) { - if (cm.somethingSelected()){ - cm.indentSelection("add"); - } else { - var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); - cm.replaceSelection(spaces); - } - }, - "Shift-Tab": function(cm) { - if (cm.somethingSelected()){ - cm.indentSelection("subtract"); - } else { - var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); - cm.replaceSelection(spaces); - } - } -}); - -editor.setSize("100%", "auto"); - -var libraryIncludes = "" + - "" + - "" + - "" + - "" + - "" + - "" + - "" + - ""; - - -var editorValueForIFrame; -var iFrameScript = ""; - -var delay; -// Initialize CodeMirror editor with a nice html5 canvas demo. -editor.on("keyup", function () { - clearTimeout(delay); - delay = setTimeout(updatePreview, 300); -}); - -var nodeEnv = prodOrDev === 'production' ? 'http://www.freecodecamp.com' : 'http://localhost:3001'; -function updatePreview() { - editorValueForIFrame = editor.getValue(); - var failedCommentTest = false; - if(editorValueForIFrame.match(/\<\!\-\-/gi) && editorValueForIFrame.match(/\-\-\>/gi) == null){ - failedCommentTest = true; - } - else if(editorValueForIFrame.match(/\<\!\-\-/gi) && editorValueForIFrame.match(/\<\!\-\-/gi).length > editorValueForIFrame.match(/\-\-\>/gi).length){ - failedCommentTest = true; - } - if(failedCommentTest){ - editor.setValue(editor.getValue()+ "-->"); - editorValueForIFrame = editorValueForIFrame + "-->"; - } - goodTests = 0; - var previewFrame = document.getElementById('preview'); - var preview = previewFrame.contentDocument || previewFrame.contentWindow.document; - preview.open(); - $('#testSuite').empty(); - preview.write(libraryIncludes + editor.getValue() + iFrameScript); - codeStorage.updateStorage(); - preview.close(); - -} -setTimeout(updatePreview, 300); - -/** - * "post" methods - */ - -var testResults = []; -var postSuccess = function(data) { - var testDoc = document.createElement("div"); - $(testDoc) - .html("
" + JSON.parse(data) + "
"); - $('#testSuite').append(testDoc); - testSuccess(); -}; - -var postError = function(data) { - var testDoc = document.createElement("div"); - $(testDoc) - .html("
" + JSON.parse(data) + "
"); - $('#testSuite').append(testDoc); -}; -var goodTests = 0; -var testSuccess = function() { - goodTests++; - if (goodTests === tests.length) { - showCompletion(); - } -}; - -function doLinting () { - editor.operation(function () { - for (var i = 0; i < widgets.length; ++i) - editor.removeLineWidget(widgets[i]); - widgets.length = 0; - JSHINT(editor.getValue()); - for (var i = 0; i < JSHINT.errors.length; ++i) { - var err = JSHINT.errors[i]; - if (!err) continue; - var msg = document.createElement("div"); - var icon = msg.appendChild(document.createElement("span")); - icon.innerHTML = "!!"; - icon.className = "lint-error-icon"; - msg.appendChild(document.createTextNode(err.reason)); - msg.className = "lint-error"; - widgets.push(editor.addLineWidget(err.line - 1, msg, { - coverGutter: false, - noHScroll: true - })); - } - }); -}; - -//$('#testSuite').empty(); -function showCompletion() { - var time = Math.floor(Date.now()) - started; - ga('send', 'event', 'Challenge', 'solved', challenge_Name + ', Time: ' + time); - $('#next-courseware-button').removeAttr('disabled'); - $('#next-courseware-button').addClass('animated tada'); - if (!userLoggedIn) { - $('#complete-courseware-dialog').modal('show'); - } - $('body').keydown(function(e) { - if (e.ctrlKey && e.keyCode == 13) { - $('#next-courseware-button').click(); - $('#next-courseware-button').unbind('click'); - } - }); -} - -/* - Local Storage Update System By Andrew Cay(Resto) - codeStorage: singleton object that contains properties and methods related to - dealing with the localStorage system. - The keys work off of the variable challenge_name to make unique identifiers per bonfire - - Two extra functionalities: - Added anonymous version checking system incase of future updates to the system - Added keyup listener to editor(myCodeMirror) so the last update has been saved to storage - */ -var codeStorage = { - version: 0.01, - keyVersion:"saveVersion", - keyValue: null,//where the value of the editor is saved - updateWait: 2000,// 2 seconds - updateTimeoutId: null, - eventArray: []//for firing saves -}; -// Returns true if the editor code was saved since last key press (use this if you want to make a "saved" notification somewhere") -codeStorage.hasSaved = function(){ - return ( updateTimeoutId === null ); -}; -codeStorage.onSave = function(func){ - codeStorage.eventArray.push(func); -}; -codeStorage.setSaveKey = function(key){ - codeStorage.keyValue = key + 'Val'; -}; -codeStorage.getEditorValue = function(){ - return ('' + localStorage.getItem(codeStorage.keyValue)); -}; - -codeStorage.isAlive = function() { - var val = this.getEditorValue() - return val !== 'null' && - val !== 'undefined' && - (val && val.length > 0); -}; -codeStorage.updateStorage = function(){ - if(typeof(Storage) !== undefined) { - var value = editor.getValue(); - localStorage.setItem(codeStorage.keyValue, value); - } else { - var debugging = false; - if( debugging ){ - console.log('no web storage'); - } - } - codeStorage.updateTimeoutId = null; - codeStorage.eventArray.forEach(function(func){ - func(); - }); -}; -//Update Version -(function(){ - var savedVersion = localStorage.getItem('saveVersion'); - if( savedVersion === null ){ - localStorage.setItem(codeStorage.keyVersion, codeStorage.version);//just write current version - }else{ - if( savedVersion !== codeStorage.version ){ - //Update version - } - } -})(); - - - -///Set everything up one page -/// Update local save when editor has changed -codeStorage.setSaveKey(challenge_Name); -editor.on('keyup', function(){ - window.clearTimeout(codeStorage.updateTimeoutId); - codeStorage.updateTimeoutId = window.setTimeout(codeStorage.updateStorage, codeStorage.updateWait); -}); - -var editorValue; - - -var challengeSeed = challengeSeed || null; -var tests = tests || []; - - -var allSeeds = ''; -(function() { - challengeSeed.forEach(function(elem) { - allSeeds += elem + '\n'; - }); -})(); - -editorValue = (codeStorage.isAlive())? codeStorage.getEditorValue() : allSeeds; - -editor.setValue(editorValue.replace((/fccss/gi), '')); -editor.refresh(); - -var resetEditor = function resetEditor() { - editor.setValue(allSeeds.replace((/fccss/gi), '')); - updatePreview(); - codeStorage.updateStorage(); -}; - - - -/* -var challengeSeed = challengeSeed || null; -var allSeeds = ''; -(function() { - challengeSeed.forEach(function(elem) { - allSeeds += elem.replace(/fccss/g, '') + '\n'; - }); - editor.setValue(allSeeds); - (function() { - setTimeout(function() { - editor.refresh(); - }, 200); - })(); -})(); -*/ diff --git a/public/js/lib/coursewares/coursewaresJSFramework_0.0.6.js b/public/js/lib/coursewares/coursewaresJSFramework_0.0.6.js deleted file mode 100644 index ddeb9519f4..0000000000 --- a/public/js/lib/coursewares/coursewaresJSFramework_0.0.6.js +++ /dev/null @@ -1,394 +0,0 @@ -var widgets = []; -var myCodeMirror = CodeMirror.fromTextArea(document.getElementById("codeEditor"), { - lineNumbers: true, - mode: "javascript", - theme: 'monokai', - runnable: true, - lint: true, - matchBrackets: true, - autoCloseBrackets: true, - scrollbarStyle: 'null', - lineWrapping: true, - gutters: ["CodeMirror-lint-markers"], - onKeyEvent: doLinting -}); -var editor = myCodeMirror; -editor.setSize("100%", "auto"); - -// Hijack tab key to enter two spaces intead -editor.setOption("extraKeys", { - Tab: function(cm) { - if (cm.somethingSelected()) { - cm.indentSelection("add"); - } else { - var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); - cm.replaceSelection(spaces); - } - }, - "Shift-Tab": function(cm) { - if (cm.somethingSelected()) { - cm.indentSelection("subtract"); - } else { - var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); - cm.replaceSelection(spaces); - } - }, - "Ctrl-Enter": function() { - bonfireExecute(); - return false; - } -}); - - -var attempts = 0; -if (attempts) { - attempts = 0; -} - - -var codeOutput = CodeMirror.fromTextArea(document.getElementById("codeOutput"), { - lineNumbers: false, - mode: "text", - theme: 'monokai', - readOnly: 'nocursor', - lineWrapping: true -}); - -codeOutput.setValue('/**\n' + - ' * Your output will go here.\n' + ' * Console.log() -type statements\n' + - ' * will appear in your browser\'s\n' + ' * DevTools JavaScript console.\n' + - ' */'); -codeOutput.setSize("100%", "100%"); -var info = editor.getScrollInfo(); -var after = editor.charCoords({ - line: editor.getCursor().line + 1, - ch: 0 -}, "local").top; -if (info.top + info.clientHeight < after) - editor.scrollTo(null, after - info.clientHeight + 3); - -function doLinting() { - editor.operation(function() { - for (var i = 0; i < widgets.length; ++i) - editor.removeLineWidget(widgets[i]); - widgets.length = 0; - JSHINT(editor.getValue()); - for (var i = 0; i < JSHINT.errors.length; ++i) { - var err = JSHINT.errors[i]; - if (!err) continue; - var msg = document.createElement("div"); - var icon = msg.appendChild(document.createElement("span")); - icon.innerHTML = "!!"; - icon.className = "lint-error-icon"; - msg.appendChild(document.createTextNode(err.reason)); - msg.className = "lint-error"; - widgets.push(editor.addLineWidget(err.line - 1, msg, { - coverGutter: false, - noHScroll: true - })); - } - }); -} - -$('#submitButton').on('click', function() { - bonfireExecute(); -}); - -function bonfireExecute() { - attempts++; - ga('send', 'event', 'Challenge', 'ran-code', challenge_Name); - userTests = null; - $('#codeOutput').empty(); - var userJavaScript = myCodeMirror.getValue(); - var failedCommentTest = false; - if(userJavaScript.match(/\/\*/gi) && userJavaScript.match(/\*\//gi) == null){ - failedCommentTest = true; - } - else if(!failedCommentTest && userJavaScript.match(/\/\*/gi) && userJavaScript.match(/\/\*/gi).length > userJavaScript.match(/\*\//gi).length){ - failedCommentTest = true; - } - userJavaScript = removeComments(userJavaScript); - userJavaScript = scrapeTests(userJavaScript); - // simple fix in case the user forgets to invoke their function - - submit(userJavaScript, function(cls, message) { - if(failedCommentTest){ - myCodeMirror.setValue(myCodeMirror.getValue() + "*/"); - console.log('Caught Unfinished Comment'); - codeOutput.setValue("Unfinished mulit-line comment"); - failedCommentTest = false; - } - else if (cls) { - codeOutput.setValue(message.error); - runTests('Error', null); - } else { - codeOutput.setValue(message.output); - codeOutput.setValue(codeOutput.getValue().replace(/\\\"/gi,'')); - message.input = removeLogs(message.input); - runTests(null, message); - } - }); -} - - -var userTests; -var testSalt = Math.random(); - - -var scrapeTests = function(userJavaScript) { - - // insert tests from mongo - for (var i = 0; i < tests.length; i++) { - userJavaScript += '\n' + tests[i]; - } - - var counter = 0; - var regex = new RegExp( - /(expect(\s+)?\(.*\;)|(assert(\s+)?\(.*\;)|(assert\.\w.*\;)|(.*\.should\..*\;)/ - ); - var match = regex.exec(userJavaScript); - while (match != null) { - var replacement = '//' + counter + testSalt; - userJavaScript = userJavaScript.substring(0, match.index) + replacement + - userJavaScript.substring(match.index + match[0].length); - - if (!userTests) { - userTests = []; - } - userTests.push({ - "text": match[0], - "line": counter, - "err": null - }); - counter++; - match = regex.exec(userJavaScript); - } - - return userJavaScript; -}; - -function removeComments(userJavaScript) { - var regex = new RegExp(/(\/\*[^(\*\/)]*\*\/)|\/\/[^\n]*/g); - return userJavaScript.replace(regex, ''); -} - -function removeLogs(userJavaScript) { - return userJavaScript.replace(/(console\.[\w]+\s*\(.*\;)/g, ''); -} - -var pushed = false; -var createTestDisplay = function() { - if (pushed) { - userTests.pop(); - } - for (var i = 0; i < userTests.length; i++) { - var test = userTests[i]; - var testDoc = document.createElement("div"); - if (test.err != null) { - console.log('Should be displaying bad tests'); - $(testDoc) - .html( - "
" + - test.text + "
" + - test.err + "
") - .appendTo($('#testSuite')); - } else { - $(testDoc) - .html( - "
" + - test.text + "
") - .appendTo($('#testSuite')); - } - }; -}; - -var expect = chai.expect; -var assert = chai.assert; -var should = chai.should(); - - -var reassembleTest = function(test, data) { - var lineNum = test.line; - var regexp = new RegExp("\/\/" + lineNum + testSalt); - return data.input.replace(regexp, test.text); -}; - -var runTests = function(err, data) { - var allTestsPassed = true; - pushed = false; - $('#testSuite').children().remove(); - if (err && userTests.length > 0) { - userTests = [{ - text: "Program Execution Failure", - err: "No user tests were run." - }]; - createTestDisplay(); - } - //Add blocks to test exploits here! - else if(editorValue.match(/if\s\(null\)\sconsole\.log\(1\);/gi)){ - allTestsPassed = false; - userTests = [{ - text: "Program Execution Failure", - err: "Invalid if (null) console.log(1); detected" - }]; - createTestDisplay(); - } - else if (userTests) { - userTests.push(false); - pushed = true; - userTests.forEach(function(chaiTestFromJSON, indexOfTestArray, - __testArray) { - try { - if (chaiTestFromJSON) { - var output = eval(reassembleTest(chaiTestFromJSON, data)); - } - } catch (error) { - allTestsPassed = false; - __testArray[indexOfTestArray].err = error.message; - } finally { - if (!chaiTestFromJSON) { - createTestDisplay(); - } - } - }); - - if (allTestsPassed) { - allTestsPassed = false; - showCompletion(); - } - - } -}; - -function showCompletion() { - var time = Math.floor(Date.now()) - started; - ga('send', 'event', 'Challenge', 'solved', challenge_Name + ', Time: ' + time + - ', Attempts: ' + attempts); - var bonfireSolution = myCodeMirror.getValue(); - var didCompleteWith = $('#completed-with').val() || null; - $.post( - '/completed-bonfire/', { - challengeInfo: { - challengeId: challenge_Id, - challengeName: challenge_Name, - completedWith: didCompleteWith, - challengeType: challengeType, - solution: bonfireSolution - } - }, - function(res) { - if (res) { - $('#complete-courseware-dialog').modal('show'); - $('#complete-courseware-dialog').keydown(function(e) { - if (e.ctrlKey && e.keyCode == 13) { - $('#next-courseware-button').click(); - } - }); - } - } - ); - -} - - -/* - Local Storage Update System By Andrew Cay(Resto) - codeStorage: singleton object that contains properties and methods related to - dealing with the localStorage system. - The keys work off of the variable challenge_name to make unique identifiers per bonfire - - Two extra functionalities: - Added anonymous version checking system incase of future updates to the system - Added keyup listener to editor(myCodeMirror) so the last update has been saved to storage - */ -var codeStorage = { - version: 0.01, - keyVersion:"saveVersion", - keyValue: null,//where the value of the editor is saved - updateWait: 2000,// 2 seconds - updateTimeoutId: null, - eventArray: []//for firing saves -}; -// Returns true if the editor code was saved since last key press (use this if you want to make a "saved" notification somewhere") -codeStorage.hasSaved = function(){ - return ( updateTimeoutId === null ); -}; -codeStorage.onSave = function(func){ - codeStorage.eventArray.push(func); -}; -codeStorage.setSaveKey = function(key){ - codeStorage.keyValue = key + 'Val'; -}; -codeStorage.getEditorValue = function(){ - return ('' + localStorage.getItem(codeStorage.keyValue)); -}; - -codeStorage.isAlive = function() { - var val = this.getEditorValue() - return val !== 'null' && - val !== 'undefined' && - (val && val.length > 0); -} -codeStorage.updateStorage = function(){ - if(typeof(Storage) !== undefined) { - var value = editor.getValue(); - localStorage.setItem(codeStorage.keyValue, value); - } else { - var debugging = false; - if( debugging ){ - console.log('no web storage'); - } - } - codeStorage.updateTimeoutId = null; - codeStorage.eventArray.forEach(function(func){ - func(); - }); -}; -//Update Version -(function(){ - var savedVersion = localStorage.getItem('saveVersion'); - if( savedVersion === null ){ - localStorage.setItem(codeStorage.keyVersion, codeStorage.version);//just write current version - }else{ - if( savedVersion !== codeStorage.version ){ - //Update version - } - } -})(); - - - -///Set everything up one page -/// Update local save when editor has changed -codeStorage.setSaveKey(challenge_Name); -editor.on('keyup', function(){ - window.clearTimeout(codeStorage.updateTimeoutId); - codeStorage.updateTimeoutId = window.setTimeout(codeStorage.updateStorage, codeStorage.updateWait); -}); - -var editorValue; - - -var challengeSeed = challengeSeed || null; -var tests = tests || []; - - -var allSeeds = ''; -(function() { - challengeSeed.forEach(function(elem) { - allSeeds += elem + '\n'; - }); -})(); - -editorValue = (codeStorage.isAlive())? codeStorage.getEditorValue() : allSeeds; - -myCodeMirror.setValue(editorValue); - -var resetEditor = function resetEditor() { - editor.setValue(allSeeds); - codeStorage.updateStorage(); -}; - -$(document).ready(function(){ - bonfireExecute(); -}); diff --git a/server/views/coursewares/showHTML.jade b/server/views/coursewares/showHTML.jade index 85970895f9..f22fbdfb76 100644 --- a/server/views/coursewares/showHTML.jade +++ b/server/views/coursewares/showHTML.jade @@ -31,10 +31,11 @@ block content for sentence in details p.wrappable.negative-10!= sentence .negative-bottom-margin-30 + label.negative-10.btn.btn-primary.btn-block#submitButton + i.fa.fa-play + |   Run code (ctrl + enter) + br if (user) - label.btn.btn-primary.btn-block.negative-10#next-courseware-button - .ion-checkmark-circled - |   Go to my next challenge (ctrl + enter) .button-spacer .btn-group.input-group.btn-group-justified label.btn.btn-success#trigger-reset-modal @@ -71,6 +72,9 @@ block content form.code .codeMirrorView textarea#codeEditor(autofocus=true, style='display: none;') + script(src = '/js/lib/coursewares/commonFrameWork.js') + script. + editor.setOption("mode", "text/html"); .col-md-4.col-lg-3 .hidden-xs.hidden-sm img.iphone-position.iframe-scroll(src="https://s3.amazonaws.com/freecodecamp/iphone6-frame.png", style = "z-index: -2;") @@ -88,4 +92,3 @@ block content span.completion-icon.ion-checkmark-circled.text-primary a.animated.fadeIn.btn.btn-lg.signup-btn.btn-block(href='/login') Sign in so you can save your progress include ../partials/challenge-modals - script(src="/js/lib/coursewares/coursewaresHCJQFramework_0.1.9.js") diff --git a/server/views/coursewares/showJS.jade b/server/views/coursewares/showJS.jade index 85ab33adaa..2d8acf85a3 100644 --- a/server/views/coursewares/showJS.jade +++ b/server/views/coursewares/showJS.jade @@ -72,7 +72,9 @@ block content form.code .codeMirrorView textarea#codeEditor(autofocus=true, style='display: none;') - script(src='/js/lib/coursewares/coursewaresJSFramework_0.0.6.js') + script(src = '/js/lib/coursewares/commonFrameWork.js') + script. + editor.setOption("mode", "javascript"); #complete-courseware-dialog.modal(tabindex='-1') .modal-dialog.animated.zoomIn.fast-animation .modal-content