/* Copyright (C) 2013 AoPS Incorporated aops@aops.com Copyright (C) 2011 Brad Miller bonelake@gmail.com This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program. If not, see . */ // Every time you update things, check that these still work. Sk.onAfterImport = function(library) { switch(library) { case 'turtle': Sk.TurtleGraphics.module.Screen.title = new Sk.builtin.func(function () {}); // Sk.TurtleGraphics.raw.Screen.prototype.setUpWorld = function() { // console.log('setting up world'); // $('#' + Sk.TurtleGraphics.target).show(); // oldScreenSetUpWorld(); // }; // // make turtle draw instantly // Sk.tg.defaults.animate = false; // Sk.tg.Turtle.prototype.speed = function() {} // Sk.tg.Turtle.prototype.delay = function() {} break; } }; Sk.onBeforeImport = function(library) { switch (library) { case 'document': case 'webgl': case 'urllib': return false; } }; var pythonTool = { defaultValues : {}, lineNumberFlags : {}, readOnlyFlags : {}, myCodeMirror : {}, errorText : {}, defaultOutputHeights : {}, uploadedFiles : {}, originalFiles : {}, bookLocation : (window.location.origin ? window.location.origin : '//artofproblemsolving.com') + '/assets/pythonbook/', // This is called each time the user clicks "Run". An alert pops up in the test fails. compatibleBrowserTest : function () { try { var testObj = Object.create({}, { p: { value: 42 } }); } catch (e) { return false; } return true; }, addCodeSource : function (oldDivId, line_number_suppression, read_only_bool) { // Old code passed in an element instead of an id as the first argument. // This catches that issue. if (typeof oldDivId !== 'string') { oldDivId = oldDivId.id.slice(0,-5); } // Find the pywindow element. var $codesource = $('#'+oldDivId); if ($codesource.length === 0) { return; } // If the same pywindow with the same id is inserted on a page multiple times, // which often happens in the classroom with stickies and popup windows, skulpt // gets confused. You have to munge the id when it is added. var newDate = new Date(); var divId = oldDivId; var divIdPrefix = 'updated-pywindow-'; if (divId.slice(0, divIdPrefix.length) !== divIdPrefix || $('.' + divId).length > 1) { divId = divIdPrefix + newDate.getTime(); } // The naming conventions here are not great. This is to deal with that. var idsToChange = [ '_pre', '_error', '_canvas', '_code', '_files', '_runb', '_popb', '_resetb', ]; // This is the part that actually deals with multiple copies. if ($('.' + oldDivId).length > 1) { $('.' + oldDivId).each(function (index, elem) { var newId = divId + 'copy' + index; $(elem).attr('id', newId); $(elem).removeClass(oldDivId); $(elem).addClass(newId); for (var i in idsToChange) { $(elem).find("#" + oldDivId + idsToChange[i]).attr('id', newId + idsToChange[i]); } pythonTool.addCodeSource(newId, line_number_suppression, read_only_bool); }); return; } // The canvas functionality has changed as of 7/28/2015, and this code makes // it so that we don't have to clean out old versions in the database. var $oldCanvas = $("canvas#" + oldDivId + "_canvas"); if ($oldCanvas && $oldCanvas.length) { var canvasWidth = parseInt($oldCanvas.attr('width')); var canvasHeight = parseInt($oldCanvas.attr('height')); $oldCanvas.parent('div').attr('id', divId + "_canvas").addClass('ac-canvas') .css('width', canvasWidth).css('height', canvasHeight).hide(); } // Update the id's for (var i in idsToChange) { $("#" + oldDivId + idsToChange[i]).attr('id', divId + idsToChange[i]); } $codesource.attr('id', divId); $codesource.removeClass(oldDivId); $codesource.addClass(divId); var codesource = $codesource.find('.active-code')[0]; // console.log(codesource); if (!codesource) { $codesource.find('.active_code').addClass('active-code'); $codesource.find('.active_out').addClass('active-out'); codesource = $codesource.find('.active-code')[0]; if (!codesource) { return false; } } var $pywindowTextArea = $("#" + divId + " .active-code"); var codeText = $pywindowTextArea.text(); codeText = codeText.replace(/newlineEscape/gi, '\n'); var spaceRegExp = new RegExp(String.fromCharCode(160),"g"); codeText = codeText.replace(spaceRegExp, ' '); $pywindowTextArea.text(codeText); // find things like [uploadedFile="sherlock.txt"][/uploadedFile] and // [pyfile="hello.txt"]hello there![/pyfile]. // // Add any [uploadedFile]s to uploadedFilesArray, and add any [pyfile]s // to the dom. uploadedFilesArray = []; var retvalFromFileParsing = pythonTool.parseFilesFromText($pywindowTextArea.text()); $pywindowTextArea.text(retvalFromFileParsing[0]); uploadedFilesArray = uploadedFilesArray.concat(retvalFromFileParsing[1]); $('#' + divId + '_files').append(retvalFromFileParsing[2]); // Actually set these based on something. pythonTool.readOnlyFlags[divId] = !!read_only_bool; if (pythonTool.lineNumberFlags[divId] === void 0) { pythonTool.lineNumberFlags[divId] = true; } if (line_number_suppression) { pythonTool.lineNumberFlags[divId] = false; } if (pythonTool.defaultValues[divId] === 'temporary') { return; } else if ($('#'+divId+'.pywindow div.CodeMirror').length > 0) { $('#'+divId+'.pywindow div.CodeMirror').remove(); } pythonTool.defaultValues[divId] = 'temporary'; $("#" + divId + " .pywindow-temp-preview-code").hide(); pythonTool.myCodeMirror[divId] = CodeMirror.fromTextArea(codesource, { mode : { name : 'python', version: 3, singleLineStringErrors: false }, theme : 'default', indentUnit : 4, matchBrackets : true, lineNumbers : pythonTool.lineNumberFlags[divId], // lineNumbers : true, // readOnly: pythonTool.readOnlyFlags[divId] ? 'nocursor' : false, readOnly: pythonTool.readOnlyFlags[divId] ? true : false, styleActiveLine : !pythonTool.readOnlyFlags[divId] }); pythonTool.myCodeMirror[divId].addKeyMap({ Tab: function(cm) { var spaces = Array(cm.getOption("indentUnit") + 1).join(" "); cm.replaceSelection(spaces); } }); pythonTool.myCodeMirror[divId].setValue(retvalFromFileParsing[0]); pythonTool.constructCurrentFilesObject(divId, uploadedFilesArray, oldDivId); var thisRunButton = $('#' + divId + '_runb'); if (thisRunButton.length == 0) { thisRunButton = $('#' + divId + ' .btn-run'); } var thisPopButton = $('#' + divId + '_popb'); if (thisPopButton.length == 0) { thisPopButton = $('#' + divId + ' .btn-pop'); } var thisResetButton = $('#' + divId + '_resetb'); if (thisResetButton.length == 0) { thisResetButton = $('#' + divId + ' .btn-reset'); } thisLineNumbersButton = $('#' + divId + ' .btn-linenumbers'); thisViewFilesButton = $('#' + divId + ' .btn-viewfiles'); thisViewFilesButton.hide(); if (thisRunButton.length > 0) { thisRunButton[0].onclick = function () {}; } if (thisPopButton.length > 0) { thisPopButton[0].onclick = function () {}; } if (thisResetButton.length > 0) { thisResetButton[0].onclick = function () {}; } if (thisRunButton.off) { thisRunButton.off('click').click(function () { pythonTool.runit(divId); }); thisPopButton.off('click').click(function () { pythonTool.popOut(divId); }); thisResetButton.off('click').click(function () { pythonTool.resetit(divId); }); thisLineNumbersButton.off('click').click(function () { pythonTool.addLineNumbers(divId); }); } else { thisRunButton.unbind('click').click(function () { pythonTool.runit(divId); }); thisPopButton.unbind('click').click(function () { pythonTool.popOut(divId); }); thisResetButton.unbind('click').click(function () { pythonTool.resetit(divId); }); thisLineNumbersButton.unbind('click').click(function () { pythonTool.addLineNumbers(divId); }); } // pythonTool.myCodeMirror[divId].getValue(); pythonTool.defaultValues[divId] = pythonTool.getTextWithFiles(divId); var $pywindow = $('#'+divId+'.pywindow'); if ( $pywindow.parent('.preview').length > 0 ) { $pywindow.find('button').click(function( event ) { event.stopPropagation(); }); } else { $pywindow.click(function( event ) { event.stopPropagation(); }); } pythonTool.myCodeMirror[divId].on('focus', function () { $pywindow.trigger('pywindow_focus'); }); var $outPreElement = $('#'+divId+'.pywindow .active-out'); $outPreElement.hide(); if (pythonTool.myCodeMirror[divId].display.measure.children.length) { var refreshCount = 50; pythonTool.revealCodeMirrorCode(divId, refreshCount); } // pythonTool.myCodeMirror[divId].refresh(); return divId; }, addCodeSourceAndClick : function (event, read_only_bool) { $pywindow = $(event.target).parents('.pywindow'); var divId = $pywindow.attr('id'); if (divId) { divId = pythonTool.addCodeSource(divId, false, read_only_bool); var this_code_mirror = pythonTool.myCodeMirror[divId]; var old_scroll_top = $(document).scrollTop(); this_code_mirror.focus(); var current_coords = this_code_mirror.cursorCoords(true); var e = $.event.fix(event); var x_diff = e.pageX - current_coords.left; var y_diff = e.pageY - (current_coords.top + current_coords.bottom)/2; this_code_mirror.setCursor(Math.round(y_diff/15), Math.round(x_diff/9)); $(document).scrollTop(old_scroll_top); } }, addCodeSourceAndRun : function (divId, line_number_suppression, read_only_bool) { divId = pythonTool.addCodeSource(divId, line_number_suppression, read_only_bool); pythonTool.runit(divId); }, addCodeSourceAndPop : function (divId, line_number_suppression, read_only_bool) { divId = pythonTool.addCodeSource(divId, line_number_suppression, read_only_bool); pythonTool.popOut(divId); }, addLineNumbers : function (divId) { pythonTool.myCodeMirror[divId].save(); $('#'+divId).find('.CodeMirror').remove(); codesource = $('#'+divId).find('.active-code')[0]; pythonTool.myCodeMirror[divId] = CodeMirror.fromTextArea(codesource, { mode : { name : 'python', version: 3, singleLineStringErrors: false }, theme : 'default', indentUnit : 4, matchBrackets : true, // lineNumbers : pythonTool.lineNumberFlags[divId], lineNumbers : true, readOnly: pythonTool.readOnlyFlags[divId] ? true : false, styleActiveLine : !pythonTool.readOnlyFlags[divId] }); $('#' + divId + ' .btn-linenumbers').hide(); }, revealCodeMirrorCode : function (divId, refreshCount) { pythonTool.myCodeMirror[divId].refresh(); if (pythonTool.myCodeMirror[divId].display.measure.children.length && refreshCount > 0) { refreshCount -= 1; setTimeout(function () { pythonTool.revealCodeMirrorCode(divId, refreshCount); }, 250); } }, // Here's everything you need to run a python program in skulpt // grab the code from your textarea // get a reference to your pre element for output // configure the output function // call Sk.importMainWithBody() runit : function (divId, insource,outpre,outerror,outcanvas) { if (!pythonTool.compatibleBrowserTest()) { alert('You cannot run the Python code in your current web browser. You can run it if you update to Internet Explorer 9 or higher or a recent version of Chrome, Firefox, or Safari.'); return; } if (Sk && Sk.builtin.file && !Sk.builtin.file.aopsmods) { pythonTool.modifySkulptIO(); } // If the function is run with one argument, calculate the ids of the input and output elements. if (!insource) { outpre = divId + '_pre'; outerror = divId + '_error'; outcanvas = divId + '_canvas'; insource = divId + '_code'; } if (!divId) { divId = insource.slice(0, -5); } Sk.builtin.file.prototype.pywindowId = divId; // Transfer the user's code from the CodeMirror to the textarea pythonTool.myCodeMirror[divId].save(); console.log(Sk); console.log(Sk.TurtleGraphics); // If there is a program already running, stop it by clearing the interval. if (Sk && Sk.TurtleGraphics && Sk.TurtleGraphics.reset) { // Sk.TurtleGraphics.module.Screen.reset(); // Sk.TurtleGraphics.reset(); Sk.TurtleGraphics.stop(); // cancelAnimationFrame(); // for (var oneCanvas in Sk.TurtleGraphics.module) { // if (Sk.TurtleGraphics.canvasLib[oneCanvas].intervalId) { // clearInterval(Sk.TurtleGraphics.canvasLib[oneCanvas].intervalId); // } // } } // Clear all of the outputs var outCanvasElement = document.getElementById(outcanvas); if (outCanvasElement) { $(outCanvasElement).empty(); // Sk.canvas = outcanvas; // outCanvasElement.width = outCanvasElement.width; // outCanvasElement.style.backgroundColor = ''; // outCanvasElement.style.display = 'none'; } // Tell Skulpt what the output element ids are. // Skulpt doesn't know about the error output element, so we add that manually later. if (!Sk.TurtleGraphics) { Sk.TurtleGraphics = {}; } Sk.TurtleGraphics.width = $(outCanvasElement).width(); Sk.TurtleGraphics.height = $(outCanvasElement).height(); Sk.TurtleGraphics.target = outcanvas; Sk.pre = outpre; Sk.codeId = insource; var outErrorElement = document.getElementById(outerror); outErrorElement.innerHTML = ''; outErrorElement.style.display = 'none'; $mypre = $('#'+outpre); var oldOutText = $mypre.text(); Sk.myOldHeight = $mypre.height(); $mypre.height('auto'); if (!oldOutText || oldOutText[0] !== '>') { Sk.myOldHeight = 'auto'; // Overwrite anything that was in the empty shell $mypre.text('>>> =================== OUTPUT ===================\n'); Sk.myOldScrollHeight = 0; } else { Sk.myOldScrollHeight = $mypre.height(); $mypre.height(Sk.myOldHeight); Sk.builtins.print3('\n>>> =================== OUTPUT ==================='); } $mypre.show(); // Deal with issues arising with Python 2 vs Python 3: / vs // // It turns out that skulpt has an option for this in Sk.configure, // so I took out the regexs below. var prog = document.getElementById(insource).value; // prog = prog.replace(/\//g, "*1.0/"); // prog = prog.replace(/\*1.0\/\*1.0\//g, "//"); // prog = prog.replace(/\*1.0\/=/g, "/=1.0*"); prog = prog.replace(/\t/gi, " "); prog = prog.replace(/\n.+\.mainloop\(\)/gi, ""); prog = prog.replace(/\n.+\.colormode\s*\([\s0-9.]*\)/gi, ""); prog = prog.replace(/^(\s*print(?=\s*\())/igm, "$1" + "3"); prog = prog.replace(/^(\s*print3\s*\(.*?)(,\s*end\s*=)\s*(.*\)\s*(#.*)?)$/igm, '$1,"endfix="$3'); prog = prog.replace(/^(\s*print3\s*\(.*?)(,\s*end\s*=)\s*(.*\)\s*(#.*)?)$/igm, '$1,"endfix="$3'); prog = prog.replace(/^(\s*print3\s*\(.*?)(,\s*sep\s*=)\s*(.*\)\s*(#.*)?)$/igm, '$1,"sepfix="$3'); prog = prog.replace(/^(\s*print3\s*\(.*?)(,\s*sep\s*=)\s*(.*\)\s*(#.*)?)$/igm, '$1,"sepfix="$3'); prog = prog.replace(/=\s*input\s*\(\s*\)\s*(#.*)?$/igm, "= input('')"); if (prog.indexOf("import turtle") > -1) { $('#' + Sk.TurtleGraphics.target).show(); } if (outCanvasElement && prog.indexOf("turtle.setup") > -1) { prog = prog.replace(/\n\s*turtle\.setup\s*\(\s*(\d*)\s*\,\s*(\d*)\s*\)/gi, function (match, w, h) { Sk.TurtleGraphics.width = w; Sk.TurtleGraphics.height = h; $(outCanvasElement).width(w).height(h); return ""; }); } if (outCanvasElement && prog.indexOf(".setup") > -1) { var screenName = 'wn'; prog.replace(/\n\s*([A-Za-z0-9_])\s*=\s*turtle.Screen\s*\(\s*\)/gi, function (match, matchedScreenName) { screenName = match; }); console.log(screenName); prog = prog.replace(/\n\s*([A-Za-z0-9_]*)\.setup\s*\(\s*(\d*)\s*\,\s*(\d*)\s*\)/gi, function (match, potentialScreenName, w, h) { console.log(potentialScreenName); if (potentialScreenName == screenName) { $(outCanvasElement).width(w).height(h); } return match; }); } // Set execLimit in milliseconds -- for student projects set this to // 25 seconds -- just less than Chrome's own timer. if (prog.indexOf("#widgetIncreaseTimeout") > -1) { Sk.execLimit = 120000; } else { Sk.execLimit = 25000; } Sk.configure({ output: function(text) { $mypre.text($mypre.text() + text); }, read: function(x) { if (Sk.builtinFiles === undefined || Sk.builtinFiles["files"][x] === undefined) { throw "File not found: '" + x + "'"; } return Sk.builtinFiles["files"][x]; }, python3: true }); var myPromise = Sk.misceval.asyncToPromise(function() { return Sk.importMainWithBody("", false, prog, true); }); myPromise.then( function(mod) { console.log('success'); }, function(e) { pythonTool.addErrorMessage(e,outerror); outErrorElement.style.display = 'block'; } ); }, resetit : function (divId, insource,outpre,outerror,outcanvas) { var response = confirm("Do you really want to reset the Python code? Any changes that you have made will be lost." ); if (response) { pythonTool.resetitCallback(divId, insource,outpre,outerror,outcanvas); } }, popOut : function (pywindowId) { var textToSend = pythonTool.getTextWithFiles(pywindowId); var poppedWindow = window.open(pythonTool.bookLocation + 'popoutPythonTool.html' + '?v=' + Date.now() + '#' + pythonTool.encodeExtraCharacters(encodeURIComponent(textToSend)), '_blank', 'width=600,height=700,toolbar=yes, scrollbars=yes, resizable=yes, location=yes, status=yes, titlebar=yes', false ); // console.log(poppedWindow); // poppedWindow.location = {'http://artofproblemsolving.com/School/MyClasses/Grid/popoutPythonTool.html#' + encodeURIComponent($('#'+insource)[0].value)); // poppedWindow.document.write('testing: ' + $('#'+insource)[0].value); }, getTextWithFiles : function (pywindowId) { pythonTool.myCodeMirror[pywindowId].save(); var insource = pywindowId+'_code'; var textWithFiles = $('#'+insource)[0].value; $.each(pythonTool.currentFiles.files[pywindowId], function (index, fileObject) { if (fileObject.isOriginal && fileObject.global) { textWithFiles += '[uploadedFile="' + fileObject.fileName + '"][/uploadedFile]'; } else if (fileObject.isOriginal) { if (!fileObject.defaultText) { fileObject.defaultText = ''; } textWithFiles += '[pyfile="' + fileObject.fileName + '"]' + fileObject.defaultText + '[/pyfile]'; } }); return textWithFiles; }, // This will give you the [pyStudentResponse] and will save the current state so that // the widget will now return to this text when it is reset. getPyStudentResponse : function ($surrounding_element, skip_save) { var $pywindow = $surrounding_element.find('.pywindow'); var div_id = $pywindow.attr('id'); if (div_id) { if (!pythonTool.myCodeMirror[div_id]) { return $("#" + div_id + " .active-code").text(); } else { var text_with_files; if (skip_save) { var codesource = $("#" + div_id + " .active-code")[0]; if (codesource) { var old_saved_value = codesource.value; text_with_files = pythonTool.getTextWithFiles(div_id); codesource.value = old_saved_value; } if (!text_with_files) text_with_files = ''; } else { text_with_files = pythonTool.getTextWithFiles(div_id); if (!text_with_files) text_with_files = ''; pythonTool.defaultValues[div_id] = text_with_files; } return text_with_files; } } else { return ''; } }, // This will reset all of the pywindows within an element. externalReset : function ($surrounding_element) { var $pywindows = $surrounding_element.find('.pywindow'); var pywindow_length = $pywindows.length; // console.log(pywindow_length); for (var i = 0; i < pywindow_length; i++) { var div_id = $pywindows[i].id; // console.log(div_id); if (div_id && pythonTool.myCodeMirror[div_id]) { pythonTool.resetitCallback(div_id); } } }, encodeExtraCharacters : function (text) { text = text.replace(/\(/g, '\%28'); text = text.replace(/\)/g, '\%29'); return text; }, decodeExtraCharacters : function (text) { text = text.replace(/%28/g, '('); text = text.replace(/%29/g, ')'); return text; }, parseFilesFromText : function (textWithFiles) { // console.log(textWithFiles); var uploadedFilesArray = []; var textareaElements = $('
'); // do a regex to find [pyfile]s and [uploadedFile]s // turn each [pyfile] into a hidden textarea var pyfileRegex = /\[\s*pyfile\s*=\s*[\'"](.+?)['"]\s*\]([\s\S]*?)\[\s*\/pyfile\s*\]/ig; textWithFiles = textWithFiles.replace(pyfileRegex, function (m, fileName, fileText) { fileName = fileName.replace(/[^A-Za-z0-9_.]/g, ''); var textareaElement = $('') .css('border', '0px').css('resize', 'none'); var $pop_button = $(''); var $preview_modal = $('
').append($textarea) .css('overflow-x', 'auto'); var linecount = 0; var oldLineCount = 0; var arrayOfLines = textToPreview.split('\n'); var reducedTextToPreview = ''; for (var i in arrayOfLines) { oldLineCount = linecount; linecount += Math.ceil(arrayOfLines[i].length / (cols - 10)); if (linecount <= 10000) { reducedTextToPreview += arrayOfLines[i] + '\n'; } else { reducedTextToPreview += '\n[File was cut off because it was too large for this preview.]\n'; linecount = oldLineCount+2; break; } } linecount += 2; $textarea[0].rows = linecount; $textarea.text(reducedTextToPreview); $pop_button.click(function () { var poppedWindow = window.open('', '_blank', 'width=620, height=500, scrollbars=yes, resizable=yes', true ); $textarea_to_send = $(''); $textarea_to_send.text($textarea.text()); poppedWindow.document.write($textarea_to_send.prop('outerHTML')); poppedWindow.document.title = fileName; AoPS.Ui.Modal.closeTopModal(); }); if (!AoPS || !AoPS.Ui || !AoPS.Ui.Modal) { $pop_button.trigger('click'); } else { $preview_modal.showModal({ 'draggable' : true, // 'footer' : $pop_button, 'title' : fileName, 'scrollable' : true, 'frame_class' : 'pyfile-preview-modal-holder', 'onShow' : function () { $('.aops-modal-title').append($pop_button); } }); } }; }; pythonTool.filesHolder.prototype.initializeHiddenIFrame = function () { var hiddenIFrameID = 'hiddenDownloader', iframe = document.getElementById(hiddenIFrameID); if (iframe === null) { iframe = document.createElement('iframe'); iframe.name = hiddenIFrameID; iframe.id = hiddenIFrameID; iframe.style.display = 'none'; iframe.src = window.location.origin; document.body.appendChild(iframe); } }; pythonTool.filesHolder.prototype.deleteAllFilesWithFileName = function (fileObject) { var currentFilesForThisDiv = this.files[fileObject.divId]; if (!currentFilesForThisDiv) { currentFilesForThisDiv = []; this.files[fileObject.divId] = currentFilesForThisDiv; } for (var fileKey in currentFilesForThisDiv) { if (currentFilesForThisDiv[fileKey].fileName == fileObject.fileName && !currentFilesForThisDiv[fileKey].deleted) { currentFilesForThisDiv[fileKey].deleted = true; if (currentFilesForThisDiv[fileKey].$elem) { currentFilesForThisDiv[fileKey].currentText = currentFilesForThisDiv[fileKey].$elem.text(); currentFilesForThisDiv[fileKey].$elem.remove(); } } } // this.displayFileBrowserView(divId); }; pythonTool.filesHolder.prototype.addFile = function (fileObject, index) { var currentFilesForThisDiv = this.files[fileObject.divId]; this.deleteAllFilesWithFileName(fileObject); if (index === void 0 || index == -1) { currentFilesForThisDiv.push(fileObject); } else { currentFilesForThisDiv.splice(index, 0, fileObject); } }; pythonTool.filesHolder.prototype.addNewHiddenFileElement = function (divId, hiddenFileElement, isOriginal) { var fileObjectGenerator = $.extend({}, this.defaultFileObject); var fileObject = new pythonTool.fileObject(divId, fileObjectGenerator); $hiddenFileElement = $(hiddenFileElement); // console.log(fileObject); var classList = $hiddenFileElement.attr('class').split(/\s+/); $.each(classList, function(index, elementClass){ if (elementClass.length < 7 || elementClass.substr(0,7) !== 'ac-file') { fileObject.fileName = elementClass; } }); fileObject.setFileTimeStamp(); fileObject.text = null; fileObject.defaultText = $hiddenFileElement.text(); var escapedFileName = fileObject.fileName.replace(/\./, '\\.'); fileObject.$elem = $('#' + divId + '_files textarea.' + escapedFileName).first(); if (isOriginal) { fileObject.isOriginal = true; } fileObject.getText = function () { return fileObject.$elem.text(); }; var oldIndex = -1; $.each(pythonTool.currentFiles.files[divId], function (index, fileObjectFromList) { if (fileObject.fileName == fileObjectFromList.fileName) { oldIndex = index; } }); if (oldIndex == -1) { fileObject.addFile(); } else { fileObject.addFile(oldIndex+1); } }; pythonTool.filesHolder.prototype.addTempGlobalFileElement = function (divId, fileName, isOriginal) { var fileObjectGenerator = $.extend({}, this.defaultFileObject); var fileObject = new pythonTool.fileObject(divId, fileObjectGenerator); fileObject.fileName = fileName; fileObject.text = null; fileObject.global = 'temp'; if (isOriginal) { fileObject.isOriginal = true; } fileObject.getText = function () { return pythonTool.uploadedFiles[fileName]; }; fileObject.addFile(); }; pythonTool.filesHolder.prototype.addRealGlobalFileElement = function (divId, fileName, isOriginal) { $.each(pythonTool.currentFiles.files, function (divId, currentFilesForThisDiv) { // var currentFilesForThisDiv = pythonTool.currentFiles.files[divId]; var indexToRemove = -1; $.each(currentFilesForThisDiv, function (index, fileObject) { if (fileObject.fileName == fileName && fileObject.global == 'temp') { indexToRemove = index; } }); if (indexToRemove > -1) { var tempFileObject = currentFilesForThisDiv.splice(indexToRemove, 1); var fileObjectGenerator = $.extend({}, this.defaultFileObject); var fileObject = new pythonTool.fileObject(divId, fileObjectGenerator); fileObject.fileName = fileName; fileObject.text = null; fileObject.global = true; if (isOriginal) { fileObject.isOriginal = true; } fileObject.getText = function () { return pythonTool.uploadedFiles[fileName]; }; fileObject.addFile(indexToRemove); } }); }; pythonTool.filesHolder.prototype.ajaxLoadError = function (fileName) { $.each(pythonTool.currentFiles.files, function (divId, currentFilesForThisDiv) { var indexToEdit = -1; $.each(currentFilesForThisDiv, function (index, fileObject) { if (fileObject.fileName == fileName && fileObject.global == 'temp') { indexToEdit = index; } }); if (indexToEdit > -1) { var tempFileObject = currentFilesForThisDiv[indexToEdit]; tempFileObject.editedAt = '(Load Failed)'; pythonTool.currentFiles.displayFileBrowserView(divId); } }); }; pythonTool.filesHolder.prototype.displayFileBrowserView = function (divId, showDeleted) { // divId is required. if (showDeleted === void 0) { showDeleted = this.showDeleted[divId]; } this.initializeHiddenIFrame(); $('#' + divId).find('.pywindow-file-table-holder').remove(); var showHideDeletedButton = ''; if (showDeleted) { showHideDeletedButton = ''; } var $fileBrowserElement = $( '
' + '' + '' + '' + '' + // '' + '
Files ' + showHideDeletedButton + '
' ); $.each(this.files[divId], function (fileKey, fileObject) { if (fileObject.deleted && !showDeleted) { return; } else { var deleteResetRestoreButton = ''; var fileRowStyle = ''; var fileNameSupplement = ''; var downloadDisabled = ''; var previewDisabled = ''; var previewAvailable = ' class="pyfile_preview"'; if (fileObject.deleted == true) { fileRowStyle = ' style="background-color:#e99"'; // deleteResetRestoreButton = ''; // deleteResetRestoreButton = ''; deleteResetRestoreButton = '
r
'; if (fileObject.global == 'temp') { // fileNameSupplement = ' (Loading...)'; downloadDisabled = ' style="display:none;"'; previewDisabled = ' style="display:none;"'; previewAvailable = ' '; } } else if (fileObject.global == false) { // deleteResetRestoreButton = ''; // deleteResetRestoreButton = ''; deleteResetRestoreButton = '
J
'; } else { if (fileObject.edited == true) { deleteResetRestoreButton = ''; } if (fileObject.global == 'temp') { fileRowStyle = ' style="background-color:#FFFACD"'; // fileNameSupplement = ' (Loading...)'; downloadDisabled = ' style="display:none;"'; previewDisabled = ' style="display:none;"'; previewAvailable = ' '; } } if (fileObject.downloadDisabled) { downloadDisabled = ' style="display:none;"'; } $fileRow = $('' + '' + '' + fileObject.fileName + fileNameSupplement + '' + '' + fileObject.editedAt + '' + // '' + deleteResetRestoreButton + '' + '
' + deleteResetRestoreButton + // '
' + '" target="_blank" download="' + fileObject.fileName + '">Download' + '" target="_blank" download="' + fileObject.fileName + '">Download' + '" target="hiddenDownloader">Download' + '" target="hiddenDownloader">Download' + '" target="_blank" download="' + fileObject.fileName + '">Download' + 'Preview' + ''); $fileBrowserElement.find('table').append($fileRow); } $fileRow.find('.pyfile_delete').click(function () { // console.log('calling deleteFile'); fileObject.deleteFile(); }); $fileRow.find('.pyfile_reset').click(function () { fileObject.resetFile(); }); $fileRow.find('.pyfile_restore').click(function () { fileObject.restoreFile(); }); $fileRow.find('.pyfile_download').click(function (eventObject) { eventObject.stopPropagation(); // eventObject.preventDefault(); // fileObject.downloadFile(); }); $fileRow.find('.pyfile_download').submit(function (eventObject) { eventObject.stopPropagation(); return false; }); $fileRow.find('a').click(function (eventObject) { eventObject.stopPropagation(); }); $fileRow.find('a').submit(function (eventObject) { eventObject.stopPropagation(); return false; }); // $fileRow.find('.pyfile_preview').click(function (eventObject) { $fileRow.click(function (eventObject) { // eventObject.preventDefault(); fileObject.previewFile(); }); }); $fileBrowserElement.find('.pyfile_show_deleted').click(function (eventObject) { eventObject.preventDefault(); pythonTool.currentFiles.toggleDeleted(divId, true); }); $fileBrowserElement.find('.pyfile_hide_deleted').click(function (eventObject) { eventObject.preventDefault(); pythonTool.currentFiles.toggleDeleted(divId, false); }); $fileBrowserElement.click(function (eventObject) { eventObject.stopPropagation(); }); $fileBrowserElement.submit(function (eventObject) { eventObject.stopPropagation(); return false; }); $('#' + divId).append($fileBrowserElement); }; pythonTool.filesHolder.prototype.toggleDeleted = function (divId, showDeleted) { // Set a variable somewhere this.showDeleted[divId] = showDeleted; this.displayFileBrowserView(divId); }; pythonTool.currentFiles = new pythonTool.filesHolder(); pythonTool.fileObject = function (divId, fileProperties) { this.divId = divId; for (var filePropertyKey in fileProperties) { this[filePropertyKey] = fileProperties[filePropertyKey]; } }; pythonTool.fileObject.prototype.deleteFile = function () { // Delete this file if (!this.deleted) { this.deleted = true; if (this.$elem) { this.currentText = this.$elem.text(); // this.$elem.text(''); this.$elem.remove(); } this.displayFileBrowserView(); } }; pythonTool.fileObject.prototype.restoreFile = function () { // console.log('restoring file'); // restore the file pythonTool.currentFiles.deleteAllFilesWithFileName(this); this.deleted = false; this.escapedId = this.fileName.replace(/\./, '\\.'); this.$elem = $('#' + this.divId + '_files textarea.'+this.escapedId).first(); if ((this.$elem == null || this.$elem.length == 0) && !this.global) { this.$elem = $('