1
1
Fork 0
mirror of https://github.com/boxgaming/qbjs.git synced 2024-05-12 08:00:12 +00:00

Refactored IDE code to be encapsulated by "IDE" function. Issues: #86, #87, #89, #90

This commit is contained in:
boxgaming 2024-01-08 12:06:04 -06:00
parent cb8b666256
commit 8c6aefc403
8 changed files with 1178 additions and 927 deletions

View file

@ -105,6 +105,8 @@ dialog a:hover { color: #fff !important; }
a:before { content: ""; }
a:after { content: ""; }
a:hover { text-decoration: underline; }
dialog a.disabled, dialog a.disabled:hover { color: #999 !important; }
dialog a.disabled:hover { text-decoration: none; }
#fs-contents a { font-variant: normal; font-family: Verdana, Geneva, Tahoma, sans-serif; font-size: 13px; }
#fs-contents a:hover { text-decoration: none; }

View file

@ -43,6 +43,7 @@ a:active { border: 2px inset;}
a:hover { color: #000; }
a:before { content: ""; }
a:after { content: ""; }
dialog a.disabled:active { border: 2px outset; }
li a, li a:link, li a:visited { border: 0; text-decoration: underline; }
li a:active { border: 0; }

73
img/upload-hover.svg Normal file
View file

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 256 256"
version="1.1"
id="svg1"
sodipodi:docname="upload-hover.svg"
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="3.6679688"
inkscape:cx="128"
inkscape:cy="128"
inkscape:window-width="1920"
inkscape:window-height="1177"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<defs
id="defs1" />
<rect
fill="none"
height="256"
width="256"
id="rect1" />
<path
d="M176,128h48a8,8,0,0,1,8,8v64a8,8,0,0,1-8,8H32a8,8,0,0,1-8-8V136a8,8,0,0,1,8-8H80"
fill="none"
stroke="#000"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="12"
id="path1"
style="fill:none;fill-opacity:1;stroke:#cccccc;stroke-opacity:1;stroke-width:16;stroke-dasharray:none" />
<line
fill="none"
stroke="#000"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="12"
x1="128"
x2="128"
y1="128"
y2="24"
id="line1"
style="fill:none;fill-opacity:1;stroke:#cccccc;stroke-opacity:1;stroke-width:16;stroke-dasharray:none" />
<polyline
fill="none"
points="80 72 128 24 176 72"
stroke="#000"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="12"
id="polyline1"
style="fill:none;fill-opacity:1;stroke:#cccccc;stroke-opacity:1;stroke-width:16;stroke-dasharray:none" />
<circle
cx="188"
cy="168"
r="10"
id="circle1"
style="fill:#cccccc;fill-opacity:1;stroke:#cccccc;stroke-opacity:1;stroke-width:5;stroke-dasharray:none" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

73
img/upload.svg Normal file
View file

@ -0,0 +1,73 @@
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<svg
viewBox="0 0 256 256"
version="1.1"
id="svg1"
sodipodi:docname="upload.svg"
inkscape:version="1.3 (0e150ed6c4, 2023-07-21)"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview1"
pagecolor="#ffffff"
bordercolor="#000000"
borderopacity="0.25"
inkscape:showpageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:deskcolor="#d1d1d1"
inkscape:zoom="3.6679688"
inkscape:cx="128"
inkscape:cy="128"
inkscape:window-width="1920"
inkscape:window-height="1177"
inkscape:window-x="1912"
inkscape:window-y="-8"
inkscape:window-maximized="1"
inkscape:current-layer="svg1" />
<defs
id="defs1" />
<rect
fill="none"
height="256"
width="256"
id="rect1" />
<path
d="M176,128h48a8,8,0,0,1,8,8v64a8,8,0,0,1-8,8H32a8,8,0,0,1-8-8V136a8,8,0,0,1,8-8H80"
fill="none"
stroke="#000"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="12"
id="path1"
style="fill:none;fill-opacity:1;stroke:#666666;stroke-opacity:1;stroke-width:16;stroke-dasharray:none" />
<line
fill="none"
stroke="#000"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="12"
x1="128"
x2="128"
y1="128"
y2="24"
id="line1"
style="fill:none;fill-opacity:1;stroke:#666666;stroke-opacity:1;stroke-width:16;stroke-dasharray:none" />
<polyline
fill="none"
points="80 72 128 24 176 72"
stroke="#000"
stroke-linecap="round"
stroke-linejoin="round"
stroke-width="12"
id="polyline1"
style="fill:none;fill-opacity:1;stroke:#666666;stroke-opacity:1;stroke-width:16;stroke-dasharray:none" />
<circle
cx="188"
cy="168"
r="10"
id="circle1"
style="fill:#666666;fill-opacity:1;stroke:#666666;stroke-opacity:1;stroke-width:5;stroke-dasharray:none" />
</svg>

After

Width:  |  Height:  |  Size: 2.1 KiB

View file

@ -27,21 +27,21 @@
</head>
<body style="display:none">
<div id="toolbar">
<a href="javascript:openProject()" class="toolbar-button" id="toolbar-button-open" title="Open"></a>
<a href="javascript:saveProject()" class="toolbar-button" id="toolbar-button-save" title="Save"></a>
<a href="javascript:IDE.openProject()" class="toolbar-button" id="toolbar-button-open" title="Open"></a>
<a href="javascript:IDE.saveProject()" class="toolbar-button" id="toolbar-button-save" title="Save"></a>
<div class="spacer"></div>
<a href="javascript:runProgram()" class="toolbar-button" id="toolbar-button-run" title="Run"></a>
<a href="javascript:stopProgram()" class="toolbar-button" id="toolbar-button-stop" title="Stop"></a>
<a href="javascript:shareProgram()" class="toolbar-button" id="toolbar-button-share" title="Share / Export"></a>
<a href="javascript:IDE.runProgram()" class="toolbar-button" id="toolbar-button-run" title="Run"></a>
<a href="javascript:IDE.stopProgram()" class="toolbar-button" id="toolbar-button-stop" title="Stop"></a>
<a href="javascript:IDE.shareProgram()" class="toolbar-button" id="toolbar-button-share" title="Share / Export"></a>
<div class="spacer"></div>
<a href="javascript:showOptionDialog()" class="toolbar-button" id="toolbar-button-settings" title="Settings"></a>
<a href="javascript:IDE.showOptionDialog()" class="toolbar-button" id="toolbar-button-settings" title="Settings"></a>
<a href="javascript:showDialog('about-dialog')" class="toolbar-button" id="toolbar-button-about" title="About QBJS"></a>
<a href="javascript:IDE.showDialog('about-dialog')" class="toolbar-button" id="toolbar-button-about" title="About QBJS"></a>
<div class="spacer" style="float:right"></div>
<a href="javascript:showConsole()" class="toolbar-button" id="toolbar-button-console-show" title="Show Console"></a>
<a href="javascript:showConsole()" class="toolbar-button" id="toolbar-button-console-hide" title="Hide Console" style="display:none"></a>
<a href="javascript:slideRight()" class="toolbar-button" id="toolbar-button-slide-right" title="Slide View Right"></a>
<a href="javascript:slideLeft()" class="toolbar-button" id="toolbar-button-slide-left" title="Slide View Left"></a>
<a href="javascript:IDE.showConsole()" class="toolbar-button" id="toolbar-button-console-show" title="Show Console"></a>
<a href="javascript:IDE.showConsole()" class="toolbar-button" id="toolbar-button-console-hide" title="Hide Console" style="display:none"></a>
<a href="javascript:IDE.slideRight()" class="toolbar-button" id="toolbar-button-slide-right" title="Slide View Right"></a>
<a href="javascript:IDE.slideLeft()" class="toolbar-button" id="toolbar-button-slide-left" title="Slide View Left"></a>
</div>
<div id="code-container">
<div id="code"></div>
@ -55,7 +55,7 @@
<div id="vslider"></div>
<div id="output-container">
<div id="tabs">
<div id="tab-console" class="tab active" onclick="changeTab('console')">Console</div><div id="tab-js" class="tab" onclick="changeTab('js')">Javascript</div><div id="tab-fs" class="tab" onclick="changeTab('fs')">Files</div><div id="tab-help" class="tab" onclick="changeTab('help')">Help</div>
<div id="tab-console" class="tab active" onclick="IDE.changeTab('console')">Console</div><div id="tab-js" class="tab" onclick="IDE.changeTab('js')">Javascript</div><div id="tab-fs" class="tab" onclick="IDE.changeTab('fs')">Files</div><div id="tab-help" class="tab" onclick="IDE.changeTab('help')">Help</div>
</div>
<div id="output-content">
<div id="warning-container"></div>
@ -63,8 +63,9 @@
<div id="fs-browser">
<div id="fs-path">
<span id="fs-url">/</span>
<div id="fs-refresh" title="Refresh" onclick="refreshFS()"></div>
<div id="fs-new-folder" title="New Directory" onclick="onNewDirectory()"></div>
<div id="fs-refresh" title="Refresh" onclick="IDE.refreshFS()"></div>
<div id="fs-new-folder" title="New Directory" onclick="IDE.onNewDirectory()"></div>
<div id="fs-upload" title="Upload" onclick="IDE.onUploadFile()"></div>
</div>
<div id="fs-contents">
</div>
@ -92,15 +93,15 @@
<div style="margin-bottom:5px">Copy the link below to share your code:</div>
<div><textarea id="share-code" rows="15" cols="60" readonly></textarea></div>
<div style="margin-top: 5px; float:left">Launch Mode:
<select id="share-mode" onchange="shareProgram()">
<select id="share-mode" onchange="IDE.shareProgram()">
<option value="">IDE (Default)</option>
<option value="play">Play</option>
<option value="auto">Auto</option>
</select>
</div>
<a id="export-button" href="javascript:exportProgram()" style="display: none; float:left; margin-top: 7px; margin-left: 10px">Export</a>
<a href="javascript:closeDialog()" style="display:block; float:right; margin-top: 7px">Close</a>
<a href="javascript:testShare()" style="display: block; float:right; margin-top: 7px; margin-right: 10px">Test</a>
<a id="export-button" href="javascript:IDE.exportProgram()" style="float:left; margin-top: 7px; margin-left: 10px">Export</a>
<a href="javascript:IDE.closeDialog()" style="display:block; float:right; margin-top: 7px">Close</a>
<a href="javascript:IDE.testShare()" style="display: block; float:right; margin-top: 7px; margin-right: 10px">Test</a>
</dialog>
<dialog id="prog-sel-dialog">
@ -110,14 +111,14 @@
</div>
<select id="prog-sel-sources" size="10" style="display:block; width:100%; margin-top:10px"></select>
<div style="text-align:center; margin-top:10px">
<a href="javascript:onSelMainProg()">Ok</a>
<a href="javascript:closeDialog()">Cancel</a>
<a href="javascript:IDE.onSelMainProg()">Ok</a>
<a href="javascript:IDE.closeDialog()">Cancel</a>
</div>
</dialog>
<dialog id="options-dialog">
<div>Select a theme:</div>
<select id="theme-picker" onchange="changeTheme(this.value)">
<select id="theme-picker" onchange="IDE.changeTheme(this.value)">
<option value="qbjs">Default</option>
<option value="qb45">QBasic</option>
<option value="qb64-vscode">QB64 VSCode</option>
@ -125,7 +126,7 @@
<option value="vscode-dark">VSCode Dark</option>
</select>
<div>
<a href="javascript:closeDialog()" style="display:block; float:right; margin-top: 7px">Close</a>
<a href="javascript:IDE.closeDialog()" style="display:block; float:right; margin-top: 7px">Close</a>
</div>
</dialog>
@ -139,14 +140,14 @@
QBJS brings the fun and accessibility of QBasic to the browser.<br/>
Learn more:<br/>
<ul>
<li><a href="javascript:showHelp('language')">QBasic Language Support</a></li>
<li><a href="javascript:showHelp('keywords')">Supported Keywords</a></li>
<li><a href="javascript:showHelp('samples')">Samples</a></li>
<li><a href="javascript:IDE.showHelp('language')">QBasic Language Support</a></li>
<li><a href="javascript:IDE.showHelp('keywords')">Supported Keywords</a></li>
<li><a href="javascript:IDE.showHelp('samples')">Samples</a></li>
</ul>
</p>
<p>Copyright (c) 2022-2023 boxgaming</p>
<div>
<a href="javascript:closeDialog()" style="display:block; float:right">Close</a>
<a href="javascript:IDE.closeDialog()" style="display:block; float:right">Close</a>
</div>
</div>
</dialog>

View file

@ -42,19 +42,20 @@ Sub Log (msg As String, msgType As String)
console.log(msgType + ":" + msg);
return;
}
var errorLine = await getErrorLine(new Error(), 1);
var errorLine = await IDE.getErrorLine(new Error(), 1);
var tr = document.createElement("tr");
addWarningCell(tr, msgType);
addWarningCell(tr, ":");
addWarningCell(tr, errorLine);
addWarningCell(tr, ":");
addWarningCell(tr, await func_EscapeHtml(msg), "99%");
IDE.addWarningCell(tr, msgType);
IDE.addWarningCell(tr, ":");
IDE.addWarningCell(tr, errorLine);
IDE.addWarningCell(tr, ":");
IDE.addWarningCell(tr, await func_EscapeHtml(msg), "99%");
tr.codeLine = errorLine - 1;
tr.onclick = gotoWarning;
tr.onclick = IDE.gotoWarning;
t.append(tr);
var container = document.getElementById("output-content");
container.scrollTop = container.scrollHeight;
changeTab("console");
IDE.changeTab("console");
IDE.showConsole();
$End If
End Sub
@ -66,12 +67,13 @@ Sub Echo (msg As String)
return;
}
var tr = document.createElement("tr");
addWarningCell(tr, await func_EscapeHtml(msg));
IDE.addWarningCell(tr, await func_EscapeHtml(msg));
tr.firstChild.colSpan = "5";
t.append(tr);
var container = document.getElementById("output-content");
container.scrollTop = container.scrollHeight;
changeTab("console");
IDE.changeTab("console");
IDE.showConsole();
$End If
End Sub

View file

@ -193,6 +193,7 @@ dialog textarea,
}
dialog a { color: #333 !important; }
dialog a:hover { color: #000 !important; }
dialog a.disabled, dialog a.disabled:hover { color: #999 !important; }
#logo {
position: absolute;
@ -213,7 +214,7 @@ dialog a:hover { color: #000 !important; }
padding: 5px;
border: 1px solid #333;
}
#fs-refresh, #fs-new-folder {
#fs-refresh, #fs-new-folder, #fs-upload {
float: right;
margin-top: -3px;
cursor: pointer;
@ -236,6 +237,13 @@ dialog a:hover { color: #000 !important; }
#fs-new-folder:hover {
background-image: url('img/new-folder-hover.svg');
}
#fs-upload {
margin-right: 8px;
background-image: url('img/upload.svg');
}
#fs-upload:hover {
background-image: url('img/upload-hover.svg');
}
.fs-file, .fs-dir, .fs-delete {
display: block;

View file

@ -1,21 +1,23 @@
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 = {
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"),
@ -52,13 +54,13 @@ var _e = {
helpSidebar: _el("help-sidebar"),
helpPage: _el("help-page"),
helpContainer: _el("help-container")
};
};
function _el(id) {
function _el(id) {
return document.getElementById(id);
}
}
async function init() {
async function _init() {
document.body.style.display = "initial";
if (window.innerWidth < 1200) {
@ -143,8 +145,14 @@ async function init() {
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();
_runProgram();
}
}
// compile
else if (event.code == 'F11') {
@ -166,7 +174,7 @@ async function init() {
// load a project
await loadProject(await res.arrayBuffer(), mainProg, function() {
if (appMode == "auto") {
runProgram();
_runProgram();
}
});
}
@ -179,15 +187,15 @@ async function init() {
}
var warnCount = 0;
changeTab("console");
_changeTab("console");
window.onresize();
if (appMode == "auto") {
runProgram();
_runProgram();
}
}
}
async function getErrorLine(error, stackDepth) {
function _getErrorLine(error, stackDepth) {
if (!stackDepth) {
stackDepth = 0;
}
@ -233,13 +241,13 @@ async function getErrorLine(error, stackDepth) {
}
return srcLine;
}
}
async function runProgram() {
async function _runProgram() {
_e.loadScreen.style.display = "none";
if (sizeMode == "max") {
slideLeft();
_slideLeft();
}
GX.reset();
QB.start();
@ -261,18 +269,18 @@ async function runProgram() {
console.error(error);
// find the source line, if possible
var srcLine = await getErrorLine(error);
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, "<div style='white-space:pre'>" + error.message + "\n<div style='color:#666'>" + error.stack + "</div></div>", "99%");
_addWarningCell(tr, "ERROR");
_addWarningCell(tr, ":");
_addWarningCell(tr, srcLine);
_addWarningCell(tr, ":");
_addWarningCell(tr, "<div style='white-space:pre'>" + error.message + "\n<div style='color:#666'>" + error.stack + "</div></div>", "99%");
tr.codeLine = srcLine - 1;
tr.onclick = gotoWarning;
tr.onclick = _gotoWarning;
table.append(tr);
}
@ -284,14 +292,14 @@ async function runProgram() {
_e.gxContainer.focus();
return false;
}
}
function stopProgram() {
function _stopProgram() {
QB.halt();
GX.sceneStop();
}
}
function shareProgram() {
function _shareProgram() {
var zout = new Shorty();
var b64 = LZUTF8.compress(editor.getValue(), { outputEncoding: "Base64" });
var baseUrl = location.href.split('?')[0];
@ -311,31 +319,40 @@ function shareProgram() {
codeShare.select();
var exportVisible = (mode == "play" || mode == "auto");
_e.exportButton.style.display = (exportVisible) ? "block" : "none";
}
_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) {
function _changeTheme(newTheme) {
theme = newTheme;
_e.ideTheme.href = "codemirror/themes/" + theme + ".css";
editor.setOption("theme", theme);
localStorage.setItem("@@_theme", theme);
}
}
function showOptionDialog() {
function _showOptionDialog() {
_e.themePicker.value = theme;
showDialog(_e.optionsDialog);
}
_showDialog(_e.optionsDialog);
}
function showDialog(dlg) {
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; }
async function exportProgram() {
var zip = new JSZip();
var qbCode = editor.getValue();
@ -369,9 +386,9 @@ async function exportProgram() {
link.click();
link.remove();
});
}
}
function addVFSFiles(vfs, zip, parent) {
function addVFSFiles(vfs, zip, parent) {
var files = vfs.getChildren(parent, vfs.FILE);
for (var i=0; i < files.length; i++) {
var f = files[i];
@ -383,9 +400,9 @@ function addVFSFiles(vfs, zip, parent) {
for (var i=0; i < dirs.length; i++) {
addVFSFiles(vfs, zip, dirs[i]);
}
}
}
async function saveProject() {
async function _saveProject() {
var vfs = QB.vfs();
var node = vfs.getNode("/");
var count = vfs.getChildren(node, vfs.FILE).length;
@ -412,13 +429,13 @@ async function saveProject() {
QB.downloadFile(content, "project.zip");
});
}
}
}
async function openProject() {
async function _openProject() {
_e.fileInput.click();
}
}
async function onOpenProject(event) {
async function onOpenProject(event) {
var f = event.target.files[0];
// load a single BASIC source file
@ -435,10 +452,10 @@ async function onOpenProject(event) {
await loadProject(f);
}
}
_e.fileInput.onchange = onOpenProject;
}
_e.fileInput.onchange = onOpenProject;
async function loadProject(zipData, mainFilename, fnCallback) {
async function loadProject(zipData, mainFilename, fnCallback) {
if (!mainFilename) {
mainFilename = "main.bas";
}
@ -477,10 +494,10 @@ async function loadProject(zipData, mainFilename, fnCallback) {
var opt = new Option(basFiles[i], basFiles[i]);
fileList.append(opt);
}
showDialog(_e.progSelDialog);
_showDialog(_e.progSelDialog);
}
refreshFS();
_refreshFS();
if (fnCallback) {
fnCallback();
}
@ -503,9 +520,9 @@ async function loadProject(zipData, mainFilename, fnCallback) {
}
return parent;
}
}
}
function onSelMainProg() {
function _onSelMainProg() {
var fileList = _e.progSelSources;
if (fileList.value == "") {
alert("No file selected.");
@ -517,9 +534,9 @@ function onSelMainProg() {
vfs.removeFile(file);
closeProgSelDlg();
}
}
}
async function getFile(path, type) {
async function getFile(path, type) {
var file = await fetch(path);
if (type == "text") {
return await file.text();
@ -527,20 +544,20 @@ async function getFile(path, type) {
else if (type == "blob") {
return await file.blob();
}
}
}
function testShare() {
function _testShare() {
open(_e.shareCode.value, "_blank");
}
}
function closeDialog() {
function _closeDialog() {
_e.shareDialog.close();
_e.progSelDialog.close();
_e.optionsDialog.close();
_e.aboutDialog.close();
}
}
async function displayWarnings() {
async function displayWarnings() {
var wstr = "";
var w = await QBCompiler.getWarnings();
warnCount = w.length;
@ -562,29 +579,29 @@ async function displayWarnings() {
var td1 = document.createElement("td");
var td2 = document.createElement("td");
var td3 = document.createElement("td");
addWarningCell(tr, "WARN");
addWarningCell(tr, ":");
addWarningCell(tr, w[i].line);
addWarningCell(tr, ":");
addWarningCell(tr, w[i].text, "99%");
_addWarningCell(tr, "WARN");
_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;
tr.onclick = _gotoWarning;
}
}
if (!consoleVisible && w.length > 0) {
consoleVisible = true;
}
}
}
function gotoWarning() {
function _gotoWarning() {
if (selectedError ) { selectedError.classList.remove("selected"); }
editor.setCursor({ line: this.codeLine});
this.classList.add("selected");
selectedError = this;
};
}
function addWarningCell(tr, text, width) {
function _addWarningCell(tr, text, width) {
var td = document.createElement("td");
td.innerHTML = text;
td.vAlign = "top";
@ -592,9 +609,9 @@ function addWarningCell(tr, text, width) {
td.width = width;
}
tr.append(td);
}
}
function showConsole() {
function _showConsole() {
consoleVisible = !consoleVisible;
if (!consoleVisible) {
_e.tbConsoleShow.style.display = "inline-block";
@ -606,9 +623,9 @@ function showConsole() {
_e.tbConsoleShow.style.display = "none";
}
window.dispatchEvent(new Event('resize'));
}
}
function changeTab(tabName) {
function _changeTab(tabName) {
if (tabName == currTab) { return; }
_el("tab-" + currTab).classList.remove("active");
_el("tab-" + tabName).classList.add("active");
@ -631,7 +648,7 @@ function changeTab(tabName) {
_e.warningContainer.style.display = "none";
_e.jsCode.style.display = "none";
_e.help.style.display = "none";
refreshFS();
_refreshFS();
}
else if (currTab == "help") {
_e.warningContainer.style.display = "none";
@ -639,20 +656,20 @@ function changeTab(tabName) {
_e.fsBrowser.style.display = "none";
_e.help.style.display = "block";
}
}
}
function showHelp(page) {
changeTab("help");
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();
}
_showConsole();
}
function displayTypes() {
function displayTypes() {
var tstr = "";
var t = QBCompiler.getTypes();
for (var i=0; i < t.length; i++) {
@ -660,9 +677,9 @@ function displayTypes() {
}
var wdiv = _e.warningContainer;
wdiv.innerHTML = tstr;
}
}
function slideLeft() {
function _slideLeft() {
_e.tbSlideRight.style.display = "inline-block";
if (sizeMode == "max" && window.innerWidth >= 1200) {
sizeMode = "normal"
@ -672,9 +689,9 @@ function slideLeft() {
_e.tbSlideLeft.style.display = "none";
}
window.dispatchEvent(new Event('resize'));
}
}
function slideRight() {
function _slideRight() {
_e.tbSlideLeft.style.display = "inline-block";
if (sizeMode == "min" && window.innerWidth >= 1200) {
sizeMode = "normal"
@ -684,9 +701,9 @@ function slideRight() {
_e.tbSlideRight.style.display = "none";
}
window.dispatchEvent(new Event('resize'));
}
}
window.onresize = function() {
window.onresize = function() {
if (!editor) { return; }
var f = _e.gxContainer;
@ -755,11 +772,11 @@ window.onresize = function() {
_e.slider.style.height = (window.innerHeight - 40) + "px";
}
QB.resize(f.clientWidth, f.clientHeight);
}
window.onresize();
}
window.onresize();
function checkButtonState() {
function checkButtonState() {
var stopButton = _e.tbStop;
var runButton = _e.tbRun;
if (GX.sceneActive() || QB.running()) {
@ -771,12 +788,12 @@ function checkButtonState() {
runButton.style.display = "inline-block";
}
setTimeout(checkButtonState, 100);
}
checkButtonState();
init();
}
checkButtonState();
_init();
// Virtual File System Viewer
function refreshFS() {
// Virtual File System Viewer
function _refreshFS() {
var vfs = QB.vfs();
var node = vfs.getNode(currPath);
if (!node) {
@ -840,7 +857,7 @@ function refreshFS() {
function deleteFile(node) {
if (confirm("This will permanently delete file '" + node.name + "'.\nAre you sure you wish to continue?")) {
vfs.removeFile(node);
refreshFS();
_refreshFS();
}
}
@ -851,27 +868,27 @@ function refreshFS() {
}
if (confirm("This will permanently delete directory '" + node.name + "'.\nAre you sure you wish to continue?")) {
vfs.removeDirectory(node);
refreshFS();
_refreshFS();
}
}
}
}
function onNewDirectory() {
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();
_refreshFS();
}
}
}
function chdir(path) {
function chdir(path) {
currPath = path;
refreshFS();
}
_refreshFS();
}
function saveFile(path) {
function saveFile(path) {
var vfs = QB.vfs();
var fileNode = vfs.getNode(path);
var fileBlob = new Blob([fileNode.data]);
@ -881,9 +898,9 @@ function saveFile(path) {
link.href = url;
link.download = fileNode.name;
link.click();
}
}
async function fileDrop(e) {
async function fileDrop(e) {
if (currTab != "fs") { return; }
e.stopPropagation();
e.preventDefault();
@ -896,7 +913,6 @@ async function fileDrop(e) {
var parentDir = vfs.getNode(currPath);
var fr = new FileReader();
console.log(files.length);
for (var i=0; i < files.length; i++) {
var f = files[i];
if (!f.type && f.size%4096 == 0) {
@ -909,17 +925,66 @@ async function fileDrop(e) {
vfs.writeData(file, data);
}
refreshFS();
}
_refreshFS();
}
_e.slider.addEventListener("mousedown", function(event) {
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) {
});
_e.vslider.addEventListener("mousedown", function(event) {
vsliding = true;
});
});
window.addEventListener("mousemove", function(event) {
window.addEventListener("mousemove", function(event) {
if (!sliding && !vsliding) { return; }
if (sliding) {
splitWidth = event.pageX - 10;
@ -929,54 +994,80 @@ window.addEventListener("mousemove", function(event) {
splitHeight = window.innerHeight - event.pageY + 35;
window.onresize();
}
});
});
window.addEventListener("mouseup", function() {
window.addEventListener("mouseup", function() {
sliding = false;
vsliding = false;
});
});
function fileDragEnter(e) {
function fileDragEnter(e) {
if (currTab != "fs") { return; }
e.stopPropagation();
e.preventDefault();
dropArea.style.backgroundColor = "rgb(255,255,255,.1)";
}
}
function fileDragLeave(e) {
function fileDragLeave(e) {
if (currTab != "fs") { return; }
e.stopPropagation();
e.preventDefault();
dropArea.style.backgroundColor = "transparent";
}
}
function fileDragOver(e) {
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);
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") {
if (!inIframe() && appMode == "ide") {
addEventListener("beforeunload", function(e) {
e.preventDefault();
return e.returnValue = "stop";
});
}
}
function inIframe () {
function inIframe () {
try {
return window.self !== window.top;
} catch (e) {
return true;
}
}
}
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;
};