var IDE = new function() { var QBCompiler = null; // if code has been passed on the query string load it into the editor var qbcode = ""; var url = location.href; var sizeMode = "normal"; var appMode = "ide"; var consoleVisible = false; var currTab = "js"; var editor; var selectedError = null; var currPath = "/"; var mainProg = null; var theme = "qbjs"; var splitWidth = 600; var splitHeight = 327; var sliding = false; var vsliding = false; var _e = { ideTheme: _el("ide-theme"), loadScreen: _el("gx-load-screen"), jsCode: _el("js-code"), warningContainer: _el("warning-container"), gxContainer: _el("gx-container"), shareMode: _el("share-mode"), shareCode: _el("share-code"), shareDialog: _el("share-dialog"), exportButton: _el("export-button"), fileInput: _el("file-input"), progSelSources: _el("prog-sel-sources"), progSelDialog: _el("prog-sel-dialog"), optionsDialog: _el("options-dialog"), aboutDialog: _el("about-dialog"), toolbar: _el("toolbar"), tbConsoleShow: _el("toolbar-button-console-show"), tbConsoleHide: _el("toolbar-button-console-hide"), tbSlideRight: _el("toolbar-button-slide-right"), tbSlideLeft: _el("toolbar-button-slide-left"), tbRun: _el("toolbar-button-run"), tbStop: _el("toolbar-button-stop"), outputContainer: _el("output-container"), outputContent: _el("output-content"), codeContainer: _el("code-container"), rightPanel: _el("game-container"), slider: _el("slider"), vslider: _el("vslider"), fsBrowser: _el("fs-browser"), fsContents: _el("fs-contents"), fsUrl: _el("fs-url"), code: _el("code"), themePicker: _el("theme-picker"), help: _el("help"), helpSidebar: _el("help-sidebar"), helpPage: _el("help-page"), helpContainer: _el("help-container") }; function _el(id) { return document.getElementById(id); } async function _init() { document.body.style.display = "initial"; if (window.innerWidth < 1200) { sizeMode = "max"; } var srcUrl = null; if (url && (url.indexOf("?") || url.indexOf("#"))) { var pindex = url.indexOf("?"); if (pindex == -1) { pindex = url.indexOf("#"); } var queryString = url.substring(pindex + 1); var nvpairs = queryString.split("&"); for (var i = 0; i < nvpairs.length; i++) { var pname = ""; var pvalue = ""; var nvidx = nvpairs[i].indexOf("="); if (nvidx > -1) { pname = nvpairs[i].substring(0, nvidx); pvalue = nvpairs[i].substring(nvidx + 1); if (pname == "qbcode") { var zin = new Shorty(); qbcode = zin.inflate(atob(pvalue)); break; } else if (pname == "code") { qbcode = LZUTF8.decompress(pvalue, { inputEncoding: "Base64" }); } else if (pname == "gzcode") { var strData = atob(pvalue); var charData = strData.split("").map(function(x){return x.charCodeAt(0);}); var binData = new Uint8Array(charData); var data = pako.inflate(binData); qbcode = String.fromCharCode.apply(null, new Uint16Array(data)); } else if (pname == "mode") { appMode = pvalue; } else if (pname == "src") { srcUrl = decodeURIComponent(pvalue); } else if (pname == "main") { mainProg = pvalue; } } } } if (appMode == "play") { _e.loadScreen.style.display = "block"; } else if (appMode == "ide") { var stheme = localStorage.getItem("@@_theme"); if (stheme && stheme != "") { theme = stheme; } _e.ideTheme.href = "codemirror/themes/" + theme + ".css"; GitHelp.navhome(); } // initialize the code editor editor = CodeMirror(document.querySelector("#code"), { lineNumbers: true, tabSize: 4, indentUnit: 4, value: qbcode, module: "qbjs", theme: theme, height: "auto", styleActiveLine: true, smartIndent: false, extraKeys: { "Tab": function(cm) { cm.replaceSelection(" ", "end"); } } }); editor.setSize(600, 600); editor.on("beforeChange", (cm, change) => { if (change.origin === "paste") { const newText = change.text.map(line => line.replace(/\t/g, " ")); change.update(null, null, newText); } }); // if IDE mode, capture the F5 event if (appMode != "play" && appMode != "auto") { window.addEventListener("keydown", function(event) { // run if (event.code == 'F5') { if (event.shiftKey) { QB.halt(); GX.sceneStop(); } else if (!QB.running() && !GX.sceneActive()) { event.preventDefault(); _runProgram(); } } // compile else if (event.code == 'F11') { event.preventDefault(); shareProgram(); } }); } if (appMode == "ide" && !inIframe()) { editor.focus(); } if (srcUrl) { var res = await fetch(srcUrl); var contentType = res.headers.get("Content-Type"); if (contentType == "application/zip" || contentType == "application/zip-compressed" || contentType == "application/x-zip-compressed") { // load a project await loadProject(await res.arrayBuffer(), mainProg, function() { if (appMode == "auto") { _runProgram(); } }); } else { // otherwise, assume a single source file var decoder = new TextDecoder("iso-8859-1"); qbcode = decoder.decode(await res.arrayBuffer()); editor.setValue(qbcode); } } var warnCount = 0; _changeTab("console"); window.onresize(); if (appMode == "auto") { _runProgram(); } } function _getErrorLine(error, stackDepth) { if (!stackDepth) { stackDepth = 0; } else if (error._stackDepth) { stackDepth = error._stackDepth; } var cdepth = 0; var srcLine = ""; if (error.line) { // safari srcLine = error.line - 1; } if (!error.stack) { return 0; } var stack = error.stack.split("\n"); for (var i=0; i < stack.length; i++) { // chrome if (stack[i].trim().indexOf("(eval at _runProgram") > -1) { if (cdepth == stackDepth) { var idx = stack[i].indexOf(":"); var pos = stack[i].substring(idx + 12); pos = pos.substring(0, pos.length - 1); pos = pos.split(":"); srcLine = pos[0] - 2; } cdepth++; } // firefox else if (stack[i].trim().indexOf("> AsyncFunction:") > -1) { if (cdepth == stackDepth) { var idx = stack[i].indexOf("> AsyncFunction:"); var pos = stack[i].substring(idx + 16); pos = pos.split(":"); srcLine = pos[0] - 2; } cdepth++; } } if (!isNaN(srcLine)) { srcLine = QBCompiler.getSourceLine(srcLine); } return srcLine; } async function _runProgram() { _e.loadScreen.style.display = "none"; if (sizeMode == "max") { _slideLeft(); } GX.reset(); QB.start(); var qbCode = editor.getValue(); if (!QBCompiler) { QBCompiler = await _QBCompiler(); } var jsCode = await QBCompiler.compile(qbCode); await displayWarnings(); if (_hasError()) { consoleVisible = true; window.onresize(); QB.halt(); GX.sceneStop(); return false; } _e.jsCode.innerHTML = jsCode; window.onresize(); try { const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor; var codeFn = new AsyncFunction(jsCode); await codeFn(); } catch (error) { console.error(error); // find the source line, if possible var srcLine = await _getErrorLine(error); var table = _el("warning-table"); if (table) { tr = document.createElement("tr"); _addWarningCell(tr, "ERROR"); _addWarningCell(tr, ":"); _addWarningCell(tr, srcLine); _addWarningCell(tr, ":"); _addWarningCell(tr, "
" + error.message + "\n
" + error.stack + "
", "99%"); tr.codeLine = srcLine - 1; tr.onclick = _gotoWarning; table.append(tr); } consoleVisible = true; window.onresize(); QB.halt(); GX.sceneStop(); } _e.gxContainer.focus(); return false; } function _hasError() { var warnings = QBCompiler.getWarnings(); for (var i=0; i < warnings.length; i++) { if (warnings[i].mtype == 1) { return true; } } return false; } function _stopProgram() { QB.halt(); GX.sceneStop(); } function _shareProgram() { var zout = new Shorty(); var b64 = LZUTF8.compress(editor.getValue(), { outputEncoding: "Base64" }); var baseUrl = location.href.split('?')[0]; var mode = _e.shareMode.value; var codeShare = _e.shareCode; var url = baseUrl + "?"; if (mode) { url += "mode=" + mode + "&"; } url += "code=" + b64; codeShare.value = url; if (!_e.shareDialog.open) { _e.shareDialog.showModal(); } codeShare.focus(); codeShare.select(); var exportVisible = (mode == "play" || mode == "auto"); _e.exportButton.title = (exportVisible) ? "" : "Select Play or Auto mode to enable Export"; if (exportVisible) { _e.exportButton.classList.remove("disabled"); } else { _e.exportButton.classList.add("disabled"); } } function _changeTheme(newTheme) { theme = newTheme; _e.ideTheme.href = "codemirror/themes/" + theme + ".css"; editor.setOption("theme", theme); localStorage.setItem("@@_theme", theme); } function _showOptionDialog() { _e.themePicker.value = theme; _showDialog(_e.optionsDialog); } function _showDialog(dlg) { if (typeof dlg == "string") { dlg = _el(dlg); } if (!dlg.open) { dlg.showModal(); } } async function _exportProgram() { var mode = _e.shareMode.value; if (mode == "") { return; } var zip = new JSZip(); var qbCode = editor.getValue(); if (!QBCompiler) { QBCompiler = await _QBCompiler(); } var jsCode = "async function __qbjs_run() {\n" + await QBCompiler.compile(qbCode) + "\n}"; var mode = _e.shareMode.value; zip.file("index.html", await getFile("export/" + mode + ".html", "text")); zip.file("program.js", jsCode); zip.file("fullscreen.svg", await getFile("export/fullscreen.svg", "blob")); zip.file("fullscreen-hover.svg", await getFile("export/fullscreen-hover.svg", "blob")); zip.file("logo.png", await getFile("export/logo.png", "blob")); zip.file("qbjs.woff2", await getFile("qbjs.woff2", "blob")); zip.file("play.png", await getFile("play.png", "blob")); zip.file("qbjs.css", await getFile("export/qbjs.css", "text")); zip.file("qb.js", await getFile("qb.js", "text")); zip.file("vfs.js", await getFile("vfs.js", "text")); zip.file("pako.2.1.0.min.js", await getFile("util/pako.2.1.0.min.js", "text")); zip.file("gx/gx.js", await getFile("gx/gx.js", "text")); zip.file("gx/__gx_font_default.png", await getFile("gx/__gx_font_default.png", "blob")); zip.file("gx/__gx_font_default_black.png", await getFile("gx/__gx_font_default_black.png", "blob")); // include vfs content var vfs = QB.vfs(); var node = vfs.getNode("/"); addVFSFiles(vfs, zip, node); zip.generateAsync({type:"blob", compression:"DEFLATE"}).then(function(content) { const link = document.createElement("a"); link.href = URL.createObjectURL(content); link.download = "program.zip"; link.click(); link.remove(); }); } function addVFSFiles(vfs, zip, parent) { var files = vfs.getChildren(parent, vfs.FILE); for (var i=0; i < files.length; i++) { var f = files[i]; var path = vfs.fullPath(f).substring(1); zip.file(path, f.data); } var dirs = vfs.getChildren(parent, vfs.DIRECTORY); for (var i=0; i < dirs.length; i++) { addVFSFiles(vfs, zip, dirs[i]); } } async function _saveProject() { var vfs = QB.vfs(); var node = vfs.getNode("/"); var count = vfs.getChildren(node, vfs.FILE).length; if (count < 1) { count = vfs.getChildren(node, vfs.DIRECTORY).length; } // save a single .bas file if (count == 0) { var progFile = new Blob([ editor.getValue() ]); QB.downloadFile(progFile, "program.bas"); } // save a project .zip file else { var zip = new JSZip(); zip.file("main.bas", editor.getValue()); var vfs = QB.vfs(); var node = vfs.getNode("/"); addVFSFiles(vfs, zip, node); zip.generateAsync({type:"blob",compression:"DEFLATE"}).then(function(content) { QB.downloadFile(content, "project.zip"); }); } } async function _openProject() { _e.fileInput.click(); } async function onOpenProject(event) { var f = event.target.files[0]; // load a single BASIC source file if (f.name.toLowerCase().endsWith(".bas") || f.type.startsWith("text/")) { var fr = new FileReader(); fr.onload = function() { editor.setValue(fr.result); } fr.readAsText(f); } // load a project from a zip file else if (f.name.endsWith(".zip") || f.type == "application/x-zip-compressed") { await loadProject(f); } } _e.fileInput.onchange = onOpenProject; async function loadProject(zipData, mainFilename, fnCallback) { if (!mainFilename) { mainFilename = "main.bas"; } else { mainFilename = mainFilename.toLowerCase(); } var vfs = GX.vfs(); vfs.reset(); JSZip.loadAsync(zipData).then(async function(zip) { var basFiles = []; var fnames = ""; var mainFound = false; for (let [filename, file] of Object.entries(zip.files)) { fnames += filename + " - " + zip.files[filename].name + "\n"; var parentDir = dirFromPath(vfs.getParentPath(filename)); if (filename.toLowerCase() == mainFilename) { var text = await zip.file(filename).async("text"); editor.setValue(text); mainFound = true; } else { if (zip.file(filename)) { var fdata = await zip.file(filename).async("arraybuffer"); var f = vfs.createFile(vfs.getFileName(filename), parentDir); vfs.writeData(f, fdata); if (filename.toLowerCase().endsWith(".bas")) { basFiles.push(filename); } } } } if (!mainFound) { var fileList = _e.progSelSources; fileList.innerHTML = ""; for (var i=0; i < basFiles.length; i++) { var opt = new Option(basFiles[i], basFiles[i]); fileList.append(opt); } _showDialog(_e.progSelDialog); } _refreshFS(); if (fnCallback) { fnCallback(); } }); function dirFromPath(path) { var vfs = GX.vfs(); if (path == "") { return vfs.rootDirectory(); } var dirnames = path.split("/"); var dirpath = "" var parent = vfs.rootDirectory(); for (var i=0; i < dirnames.length; i++) { dirpath += "/" + dirnames[i]; var dir = vfs.getNode(dirpath); if (!dir) { dir = vfs.createDirectory(dirnames[i], parent); } parent = dir; } return parent; } } function _onSelMainProg() { var fileList = _e.progSelSources; if (fileList.value == "") { alert("No file selected."); } else { var vfs = GX.vfs(); var file = vfs.getNode("/" + fileList.value); editor.setValue(vfs.readText(file)); vfs.removeFile(file); closeProgSelDlg(); } } async function getFile(path, type) { var file = await fetch(path); if (type == "text") { return await file.text(); } else if (type == "blob") { return await file.blob(); } } function _testShare() { open(_e.shareCode.value, "_blank"); } function _closeDialog() { _e.shareDialog.close(); _e.progSelDialog.close(); _e.optionsDialog.close(); _e.aboutDialog.close(); } async function displayWarnings() { var wstr = ""; var w = await QBCompiler.getWarnings(); warnCount = w.length; var wdiv = _e.warningContainer; wdiv.innerHTML = ""; var table = document.createElement("table"); table.style.width = "100%"; table.id = "warning-table"; table.cellPadding = 2; table.cellSpacing = 0; table.style.cursor = "default"; wdiv.appendChild(table); selectedError = null; if (warnCount > 0) { for (var i=0; i < w.length; i++) { var tr = document.createElement("tr"); var td1 = document.createElement("td"); var td2 = document.createElement("td"); var td3 = document.createElement("td"); var mtype = (w[i].mtype == 1) ? "ERROR": "WARN"; _addWarningCell(tr, mtype); _addWarningCell(tr, ":"); _addWarningCell(tr, w[i].line); _addWarningCell(tr, ":"); _addWarningCell(tr, w[i].text, "99%"); table.append(tr); tr.codeLine = w[i].line - 1; tr.onclick = _gotoWarning; } } if (!consoleVisible && w.length > 0) { consoleVisible = true; } } function _gotoWarning() { if (selectedError ) { selectedError.classList.remove("selected"); } editor.setCursor({ line: this.codeLine}); this.classList.add("selected"); selectedError = this; } function _addWarningCell(tr, text, width) { var td = document.createElement("td"); td.innerHTML = text; td.vAlign = "top"; if (width != undefined) { td.width = width; } tr.append(td); } function _showConsole(force) { consoleVisible = !consoleVisible; if (force != undefined) { consoleVisible = force; } if (!consoleVisible) { _e.tbConsoleShow.style.display = "inline-block"; _e.tbConsoleHide.style.display = "none"; } else { _e.tbConsoleHide.style.display = "inline-block"; _e.tbConsoleShow.style.display = "none"; } window.dispatchEvent(new Event('resize')); } function _changeTab(tabName) { if (tabName == currTab) { return; } _el("tab-" + currTab).classList.remove("active"); _el("tab-" + tabName).classList.add("active"); currTab = tabName; if (currTab == "console") { _e.warningContainer.style.display = "block"; _e.jsCode.style.display = "none"; _e.fsBrowser.style.display = "none"; _e.help.style.display = "none"; } else if (currTab == "js") { _e.warningContainer.style.display = "none"; _e.fsBrowser.style.display = "none"; _e.jsCode.style.display = "block"; _e.help.style.display = "none"; } else if (currTab == "fs") { _e.fsBrowser.style.display = "block"; _e.warningContainer.style.display = "none"; _e.jsCode.style.display = "none"; _e.help.style.display = "none"; _refreshFS(); } else if (currTab == "help") { _e.warningContainer.style.display = "none"; _e.jsCode.style.display = "none"; _e.fsBrowser.style.display = "none"; _e.help.style.display = "block"; } } function _showHelp(page) { _changeTab("help"); var helpUrl = ""; if (page == "language") { GitHelp.wikinav("https://raw.githubusercontent.com/wiki/boxgaming/qbjs/QBasic-Language-Support.md"); } else if (page == "keywords") { GitHelp.wikinav("https://raw.githubusercontent.com/wiki/boxgaming/qbjs/Supported-Keywords.md"); } else if (page == "samples") { GitHelp.wikinav("https://raw.githubusercontent.com/wiki/boxgaming/qbjs/Samples.md"); } else { GitHelp.navhome(); } consoleVisible = false; _showConsole(); } function displayTypes() { var tstr = ""; var t = QBCompiler.getTypes(); for (var i=0; i < t.length; i++) { tstr += t[i].name } var wdiv = _e.warningContainer; wdiv.innerHTML = tstr; } function _slideLeft() { _e.tbSlideRight.style.display = "inline-block"; if (sizeMode == "max" && window.innerWidth >= 1200) { sizeMode = "normal" } else { sizeMode = "min" _e.tbSlideLeft.style.display = "none"; } window.dispatchEvent(new Event('resize')); } function _slideRight() { _e.tbSlideLeft.style.display = "inline-block"; if (sizeMode == "min" && window.innerWidth >= 1200) { sizeMode = "normal" } else { sizeMode = "max" _e.tbSlideRight.style.display = "none"; } window.dispatchEvent(new Event('resize')); } window.onresize = function() { if (!editor) { return; } var f = _e.gxContainer; var jsDiv = _e.outputContainer; if (appMode == "play" || appMode == "auto") { f.style.left = "0px"; f.style.top = "0px"; f.style.width = window.innerWidth + "px"; f.style.height = window.innerHeight + "px"; f.style.border = "0px"; _e.codeContainer.style.display = "none"; _e.slider.style.display = "none"; _e.rightPanel.style.left = "0px"; _e.rightPanel.style.top = "0px"; _e.rightPanel.style.right = "0px"; _e.rightPanel.style.bottom = "0px"; _e.rightPanel.style.backgroundColor = "#000"; _e.toolbar.style.display = "none"; jsDiv.style.display = "none"; _e.vslider.style.display = "none"; splitHeight = 0; } else { var cmwidth = splitWidth; if (sizeMode == "min") { cmwidth = -10; editor.getWrapperElement().style.display = "none"; _e.rightPanel.style.display = "block"; _e.slider.style.display = "none"; } else if (sizeMode == "max") { cmwidth = window.innerWidth - 12; _e.rightPanel.style.display = "none"; _e.slider.style.display = "none"; editor.getWrapperElement().style.display = "block"; } else { editor.getWrapperElement().style.display = "block"; _e.rightPanel.style.display = "block"; _e.slider.style.display = "block"; } _e.rightPanel.style.left = (cmwidth + 15) + "px"; f.style.width = (window.innerWidth - (cmwidth + 22)) + "px"; jsDiv.style.width = f.style.width; _e.slider.style.left = (cmwidth + 7) + "px"; if (consoleVisible) { _e.vslider.style.display = "block"; f.style.height = (window.innerHeight - splitHeight) + "px"; jsDiv.style.display = "block"; jsDiv.style.top = (window.innerHeight - splitHeight + 10) + "px"; _e.outputContent.style.height = (splitHeight - 77) + "px"; _e.helpContainer.style.height = (splitHeight - 110) + "px"; } else { _e.vslider.style.display = "none"; f.style.height = (window.innerHeight - 40) + "px"; jsDiv.style.display = "none"; } editor.setSize(cmwidth, window.innerHeight - 40); _e.code.style.height = (window.innerHeight - 40) + "px"; _e.slider.style.height = (window.innerHeight - 40) + "px"; } QB.resize(f.clientWidth, f.clientHeight); } window.onresize(); function checkButtonState() { var stopButton = _e.tbStop; var runButton = _e.tbRun; if (GX.sceneActive() || QB.running()) { stopButton.style.display = "inline-block"; runButton.style.display = "none"; } else { stopButton.style.display = "none"; runButton.style.display = "inline-block"; } setTimeout(checkButtonState, 100); } checkButtonState(); _init(); // Virtual File System Viewer function _refreshFS() { var vfs = QB.vfs(); var node = vfs.getNode(currPath); if (!node) { currPath = "/"; node = vfs.getNode(currPath); } var contents = _e.fsContents; while (contents.firstChild) { contents.removeChild(contents.firstChild); } if (!node) { // TODO: better error reporting return; } currPath = vfs.fullPath(node) _e.fsUrl.innerHTML = currPath; if (currPath != "/") { var a = document.createElement("a"); a.className = "fs-dir"; a.innerHTML = ".."; a.fullpath = currPath + "/.."; a.onclick = function() { chdir(this.fullpath); }; contents.appendChild(a); contents.appendChild(document.createElement("span")); } var folders = vfs.getChildren(node, vfs.DIRECTORY); for (var i=0; i < folders.length; i++) { var a = document.createElement("a"); a.className = "fs-dir"; a.innerHTML = folders[i].name; a.fullpath = vfs.fullPath(folders[i]); a.onclick = function() { chdir(this.fullpath); }; contents.appendChild(a); a = document.createElement("a"); a.className = "fs-delete"; a.vfsnode = folders[i]; a.onclick = function() { deleteDir(this.vfsnode); }; contents.appendChild(a); } var files = vfs.getChildren(node, vfs.FILE); for (var i=0; i < files.length; i++) { var a = document.createElement("a"); a.className = "fs-file"; a.innerHTML = files[i].name; a.fullpath = vfs.fullPath(files[i]); a.onclick = function() { saveFile(this.fullpath); }; contents.appendChild(a); a = document.createElement("a"); a.className = "fs-delete"; a.vfsnode = files[i]; a.onclick = function() { deleteFile(this.vfsnode); }; contents.appendChild(a); } function deleteFile(node) { if (confirm("This will permanently delete file '" + node.name + "'.\nAre you sure you wish to continue?")) { vfs.removeFile(node); _refreshFS(); } } function deleteDir(node) { if (vfs.getChildren(node).length > 0) { alert("Directory is not empty."); return; } if (confirm("This will permanently delete directory '" + node.name + "'.\nAre you sure you wish to continue?")) { vfs.removeDirectory(node); _refreshFS(); } } } function _onNewDirectory() { var vfs = QB.vfs(); var parent = vfs.getNode(currPath); var dirname = prompt("Enter new directory name"); if (dirname && dirname != "") { vfs.createDirectory(dirname, parent); _refreshFS(); } } function chdir(path) { currPath = path; _refreshFS(); } function saveFile(path) { var vfs = QB.vfs(); var fileNode = vfs.getNode(path); var fileBlob = new Blob([fileNode.data]); var url = URL.createObjectURL(fileBlob); var link = document.createElement("a"); link.href = url; link.download = fileNode.name; link.click(); } async function fileDrop(e) { if (currTab != "fs") { return; } e.stopPropagation(); e.preventDefault(); dropArea.style.backgroundColor = "transparent"; var dt = e.dataTransfer; var files = dt.files; var vfs = QB.vfs(); var parentDir = vfs.getNode(currPath); var fr = new FileReader(); for (var i=0; i < files.length; i++) { var f = files[i]; if (!f.type && f.size%4096 == 0) { // this is a folder, skip continue; } var file = vfs.createFile(f.name, parentDir); var data = await f.arrayBuffer(); vfs.writeData(file, data); } _refreshFS(); } function _onUploadFile() { _uploadFile(_e.fsUrl.innerHTML, null, function() { _refreshFS(); }); } function _uploadFile(destpath, filter, fnCallback) { var vfs = QB.vfs(); var parentDir = null; if (destpath == undefined || destpath == "" || destpath == "/") { parentDir = vfs.rootDirectory(); //QB.vfsCwd(); } else { parentDir = vfs.getNode(destpath, vfs.rootDirectory()); //QB.vfsCwd()); if (!parentDir) { throw Object.assign(new Error("Path not found: [" + destpath + "]"), { _stackDepth: 1 }); } else if (parentDir && parentDir.type != vfs.DIRECTORY) { throw Object.assign(new Error("Path is not a directory: [" + destpath + "]"), { _stackDepth: 1 }); } } var fileInput = document.getElementById("upload-file-input"); if (fileInput == null) { fileInput = document.createElement("input"); fileInput.id = "upload-file-input"; fileInput.type = "file"; } fileInput.value = null; if (filter != undefined) { fileInput.accept = filter; } fileInput.onchange = function(event) { if (event.target.files.length > 0) { var f = event.target.files[0]; var fr = new FileReader(); fr.onload = function() { var file = vfs.createFile(f.name, parentDir); vfs.writeData(file, fr.result); if (fnCallback) { fnCallback(vfs.fullPath(file)); } } fr.readAsArrayBuffer(f); } }; fileInput.click(); } _e.slider.addEventListener("mousedown", function(event) { sliding = true; }); _e.vslider.addEventListener("mousedown", function(event) { vsliding = true; }); window.addEventListener("mousemove", function(event) { if (!sliding && !vsliding) { return; } if (sliding) { splitWidth = event.pageX - 10; window.onresize(); } else { splitHeight = window.innerHeight - event.pageY + 35; window.onresize(); } }); window.addEventListener("mouseup", function() { sliding = false; vsliding = false; }); function fileDragEnter(e) { if (currTab != "fs") { return; } e.stopPropagation(); e.preventDefault(); dropArea.style.backgroundColor = "rgb(255,255,255,.1)"; } function fileDragLeave(e) { if (currTab != "fs") { return; } e.stopPropagation(); e.preventDefault(); dropArea.style.backgroundColor = "transparent"; } function fileDragOver(e) { if (currTab != "fs") { return; } e.stopPropagation(); e.preventDefault(); } var dropArea = _e.outputContent; dropArea.addEventListener("drop", fileDrop, false); dropArea.addEventListener("dragover", fileDragOver, false); dropArea.addEventListener("dragenter", fileDragEnter, false); dropArea.addEventListener("dragleave", fileDragLeave, false); if (!inIframe() && appMode == "ide") { addEventListener("beforeunload", function(e) { e.preventDefault(); return e.returnValue = "stop"; }); } function inIframe () { try { return window.self !== window.top; } catch (e) { return true; } } this.mode = function() { return appMode; } this.getErrorLine = _getErrorLine; this.runProgram = _runProgram; this.stopProgram = _stopProgram; this.shareProgram = _shareProgram; this.changeTheme = _changeTheme; this.showOptionDialog = _showOptionDialog; this.showDialog = _showDialog; this.exportProgram = _exportProgram; this.saveProject = _saveProject; this.openProject = _openProject; this.onSelMainProg = _onSelMainProg; this.testShare = _testShare; this.closeDialog = _closeDialog; this.gotoWarning = _gotoWarning; this.addWarningCell = _addWarningCell; this.showConsole = _showConsole; this.changeTab = _changeTab; this.showHelp = _showHelp; this.slideLeft = _slideLeft; this.slideRight = _slideRight; this.refreshFS = _refreshFS; this.onNewDirectory = _onNewDirectory; this.onUploadFile = _onUploadFile; this.uploadFile = _uploadFile; };