1
1
Fork 0
mirror of https://github.com/boxgaming/qbjs.git synced 2024-05-12 08:00:12 +00:00
qbjs/index.html
2022-03-30 17:37:36 -05:00

511 lines
19 KiB
HTML

<html>
<head>
<meta charset="utf-8"/>
<style>
@font-face {
font-family: dosvga;
src: url(lp-dosvga.ttf);
}
body {
background-color: rgb(0, 0, 39);
font-family: dosvga, Arial, Helvetica, sans-serif;
color: #999;
}
a, a:link, a:visited {
text-decoration: none;
color: #ccc;
}
a:hover { color: #fff; }
a:before { content: "< "; }
a:after { content: " >"; }
#code-container {
position: absolute;
left: 10px;
top: 10px;
}
#code {
/*width: 600px;*/
margin-bottom: 5px;
border: 1px solid #666;
}
#game-container {
position: absolute;
left: 620px;
top: 10px;
}
#gx-container {
border: 1px solid #666;
text-align: center;
background-color: #000;
}
#gx-canvas {
border: 1px solid #222;
background-color: #000;
}
#output-container {
position: absolute;
color: #ccc;
display: none;
}
#output-content {
border: 1px solid #666;
overflow: scroll;
height: 150px;
}
#js-code {
white-space: pre;
padding: 5px;
color: #999;
}
#show-js-container {
color: #666;
position: absolute;
padding-top: 3px;
}
#warning-container {
white-space: pre;
font-family: dosvga;
color: #999;
padding: 5px;
}
#share-button {
float: right;
}
#slider {
position: absolute;
top: 10px;
color: #666;
}
.slider-button {
padding-top: 2px;
}
.slider-button:hover {
color: #ccc;
cursor: pointer;
}
.modal {
display: none;
}
.modal.is-open {
display: block;
}
#tabs {
margin-bottom: -1px;
}
.tab {
display:inline-block;
padding: 5px 10px;
border: 1px solid #666;
border-bottom: 0px;
margin-right: 2px;
color: #999;
cursor: pointer;
}
.tab:hover {
color: #fff;
background-color: rgb(0, 49, 78);
}
#tabs .active {
border-bottom: 1px solid rgb(0, 0, 39);
color: #ccc;
}
#tabs .active:hover {
background-color: transparent;
color: #ccc;
}
#gx-load-screen {
display: none;
text-align: center;
margin: auto;
width: 600px;
height: 360px;
font-size: 24px;
color: #ccc;
border: 1px solid #000;
text-decoration: none;
background-position: center center;
background-image: url('play.png');
background-repeat: no-repeat;
background-color: #444;
}
#gx-load-screen:hover {
background-color: #555;
}
#gx-load-screen:before { content: ""; }
#gx-load-screen:after { content: ""; }
#gx-container a, #gx-container a:link, #gx-container a:visited {
color: rgb(69, 118, 147);
}
#gx-container a:hover {
color: rgb(69, 118, 147);
text-decoration: underline;
}
#gx-container a:before { content: ""; }
#gx-container a:after { content: ""; }
#gx-container, #gx-container table {
font-family: arial, helvetica, sans-serif;
font-size: 14px;
}
#share-dialog {
background-color:#ddd;
}
#share-dialog textarea {
font-family: dosvga;
font-size: 1em;
background-color: #efefef;
}
#share-dialog a { color: #333; }
#share-dialog a:hover { color: #000; }
</style>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.52.2/codemirror.min.css"></link>
<link rel="stylesheet" href="codemirror/qb-ide.css"></link>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.52.2/codemirror.min.js"></script>
<script type="text/javascript" src="codemirror/qb-lang.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/codemirror/5.52.2/addon/selection/active-line.js"></script>
<script type="text/javascript" src="util/shorty.min.js"></script>
</head>
<body>
<div id="code-container">
<div id="code"></div>
<a id="run-button" href="javascript:runProgram()">Run Program</a>
<a id="stop-button" href="javascript:stopProgram()">Stop</a>
<a id="share-button" href="javascript:shareProgram()">Share</a>
</div>
<div id="slider">
<div id="slider-left" class="slider-button" onclick="slideLeft()">&lt;</div>
<div id="slider-right" class="slider-button" onclick="slideRight()">&gt;</div>
</div>
<div id="game-container">
<div id="gx-container">
<a href="javascript:runProgram()" id="gx-load-screen">&nbsp;</a>
</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>
<div id="output-content">
<div id="warning-container"></div>
<div id="js-code"></div>
</div>
</div>
<div id="show-js-container"><a id="toggle-console" href="javascript:showConsole()">Show Console</a></div> <!-- <input type="checkbox" id="show-js" onclick="window.onresize()"/> Show Javascript</div> -->
</div>
<div id="gx-footer"></div>
<dialog id="share-dialog">
<div style="margin-bottom:5px">Copy the link below to share your code:</div>
<div><textarea id="share-code" rows="15" cols="80" readonly></textarea></div>
<div style="margin-top: 5px; float:left">Launch Mode:
<select id="share-mode" onchange="shareProgram()">
<option value="">IDE (Default)</option>
<option value="play">Play</option>
<option value="auto">Auto</option>
</select>
</div>
<a href="javascript:closeDialog()" style="display:block; float:right; margin-top: 5px">Close</a>
<a href="javascript:testShare()" style="display: block; float:right; margin-top: 5px; margin-right: 10px">Test</a>
</dialog>
</body>
<script language="javascript" src="gx/gx.js"></script>
<script language="javascript" src="qb.js"></script>
<script language="javascript" src="qb2js.js"></script>
<script language="javascript">
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 = "console";
if (url && url.indexOf("?")) {
var queryString = url.substring(url.indexOf("?")+1);
var nvpairs = queryString.split("&");
for (var i = 0; i < nvpairs.length; i++) {
var nv = nvpairs[i].split("=");
if (nv[0] == "qbcode") {
var zin = new Shorty();
qbcode = zin.inflate(atob(nv[1]));
break;
}
else if (nv[0] == "mode") {
appMode = nv[1];
}
}
}
if (appMode == "play") {
document.getElementById("gx-load-screen").style.display = "block";
}
// initialize the code editor
var editor = CodeMirror(document.querySelector("#code"), {
lineNumbers: true,
tabSize: 4,
indentUnit: 4,
value: qbcode,
module: "qbjs",
theme: "lesser-dark",
height: "auto",
styleActiveLine: true,
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);
}
});
var warnCount = 0;
async function runProgram() {
document.getElementById("gx-load-screen").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();
var jsDiv = document.getElementById("js-code");
jsDiv.innerHTML = jsCode;
window.onresize();
try {
const AsyncFunction = Object.getPrototypeOf(async function(){}).constructor;
var codeFn = new AsyncFunction(jsCode);
await codeFn();
}
catch (error) {
console.error(error);
var wdiv = document.getElementById("warning-container");
var html = wdiv.innerHTML;
if (html != "") { html += "\n" };
html += error.name + ": " + error.message + "\n";
html += error.stack;
wdiv.innerHTML = html;
consoleVisible = true;
window.onresize();
QB.halt();
GX.sceneStop();
}
document.getElementById("gx-container").focus();
return false;
}
function stopProgram() {
QB.halt();
GX.sceneStop();
}
function shareProgram() {
var zout = new Shorty();
var b64 = btoa(zout.deflate(editor.getValue()));
var baseUrl = location.href.split('?')[0];
var mode = document.getElementById("share-mode").value;
var codeShare = document.getElementById("share-code");
var url = baseUrl + "?";
if (mode) {
url += "mode=" + mode + "&";
}
url += "qbcode=" + b64;
codeShare.value = url;
document.getElementById("share-dialog").showModal();
codeShare.focus();
codeShare.select();
}
function testShare() {
var url = document.getElementById("share-code").value;
open(url, "_blank");
}
function closeDialog() {
document.getElementById("share-dialog").close();
}
async function displayWarnings() {
var wstr = "";
var w = await QBCompiler.getWarnings();
warnCount = w.length;
for (var i=0; i < w.length; i++) {
wstr += w[i].line + ": " + w[i].text + "\n";
}
var wdiv = document.getElementById("warning-container");
wdiv.innerHTML = wstr;
if (!consoleVisible && w.length > 0) {
consoleVisible = true;
}
}
function showConsole() {
consoleVisible = !consoleVisible;
window.dispatchEvent(new Event('resize'));
//window.onresize();
}
function changeTab(tabName) {
if (tabName == currTab) { return; }
document.getElementById("tab-" + currTab).classList.remove("active");
document.getElementById("tab-" + tabName).classList.add("active");
currTab = tabName;
if (currTab == "console") {
document.getElementById("warning-container").style.display = "block";
document.getElementById("js-code").style.display = "none";
}
else {
document.getElementById("warning-container").style.display = "none";
document.getElementById("js-code").style.display = "block";
}
}
function displayTypes() {
var tstr = "";
var t = QBCompiler.getTypes();
for (var i=0; i < t.length; i++) {
tstr += t[i].name
}
var wdiv = document.getElementById("warning-container");
wdiv.innerHTML = tstr;
}
function slideLeft() {
document.getElementById("slider-right").style.display = "block";
if (sizeMode == "max") {
sizeMode = "normal"
}
else {
sizeMode = "min"
document.getElementById("slider-left").style.display = "none";
}
//window.onresize();
window.dispatchEvent(new Event('resize'));
}
function slideRight() {
document.getElementById("slider-left").style.display = "block";
if (sizeMode == "min") {
sizeMode = "normal"
}
else {
sizeMode = "max"
document.getElementById("slider-right").style.display = "none";
}
//window.onresize();
window.dispatchEvent(new Event('resize'));
}
window.onresize = function() {
var f = document.getElementById("gx-container");
var jsDiv = document.getElementById("output-container");
if (appMode == "play" || appMode == "auto") {
f.style.left = "0px";
f.style.top = "0px";
f.style.width = window.innerWidth;
f.style.height = window.innerHeight;
f.style.border = "0px";
document.getElementById("code-container").style.display = "none";
document.getElementById("slider").style.display = "none";
document.getElementById("show-js-container").style.display = "none";
document.getElementById("game-container").style.left = "0px";
document.getElementById("game-container").style.top = "0px";
jsDiv.style.display = "none";
}
else {
var cmwidth = 600;
if (sizeMode == "min") {
cmwidth = 0;
editor.getWrapperElement().style.display = "none";
document.getElementById("code").style.borderRight = "0";
}
else if (sizeMode == "max") {
cmwidth = window.innerWidth - 25;
document.getElementById("game-container").style.display = "none";
document.getElementById("slider").style.border = "1px solid #666";
document.getElementById("slider").style.borderLeft = "0";
}
else {
editor.getWrapperElement().style.display = "block";
document.getElementById("game-container").style.display = "block";
document.getElementById("code").style.borderRight = "1px solid #666";
document.getElementById("slider").style.border = "0";
}
document.getElementById("game-container").style.left = (cmwidth + 20) + "px";
f.style.width = (window.innerWidth - (cmwidth + 35)) + "px";
jsDiv.style.width = f.style.width;
document.getElementById("slider").style.left = (cmwidth + 12) + "px";
if (consoleVisible) {
f.style.height = (window.innerHeight - 237) + "px";
jsDiv.style.display = "block";
jsDiv.style.top = (window.innerHeight - 227) + "px";
document.getElementById("toggle-console").innerHTML = "Hide Console";
if (currTab == "console") {
document.getElementById("warning-container").style.display = "block";
document.getElementById("js-code").style.display = "none";
}
else {
document.getElementById("warning-container").style.display = "none";
document.getElementById("js-code").style.display = "block";
}
}
else {
f.style.height = (window.innerHeight - 50) + "px";
jsDiv.style.display = "none";
document.getElementById("toggle-console").innerHTML = "Show Console";
}
document.getElementById("show-js-container").style.top = (window.innerHeight - 45) + "px";
document.getElementById("show-js-container").style.right = "5px";
editor.setSize(cmwidth, window.innerHeight - 50);
document.getElementById("code").style.height = (window.innerHeight - 50) + "px";
document.getElementById("slider").style.height = (window.innerHeight - 50) + "px";
}
//QB.resize(f.style.width.replace("px", ""), f.style.height.replace("px", ""));
QB.resize(f.clientWidth, f.clientHeight);
}
window.onresize();
function checkButtonState() {
var stopButton = document.getElementById("stop-button");
if (GX.sceneActive() || QB.running()) {
stopButton.style.display = "inline";
}
else {
stopButton.style.display = "none";
}
setTimeout(checkButtonState, 100);
}
checkButtonState();
if (appMode == "auto") {
runProgram();
}
</script>
</html>