diff --git a/index.html b/index.html
index d12c00b..f692750 100644
--- a/index.html
+++ b/index.html
@@ -54,7 +54,7 @@
-
+
diff --git a/js/code-runner.js b/js/code-runner.js
new file mode 100644
index 0000000..ea2233f
--- /dev/null
+++ b/js/code-runner.js
@@ -0,0 +1,40 @@
+export class CodeRunner {
+ constructor(cons) {
+ this.console = cons;
+ this.isRunning = false;
+ }
+
+ setCode(code) {
+ this.code = code;
+ }
+
+ async run() {
+ this.isRunning = true;
+
+ this.console.log("Running code...");
+
+ // Stored globally so lib.js can access it
+ window.libInternalAbortController = new AbortController();
+
+ // Use RNG to prevent caching
+ const encodedText = encodeURIComponent(this.code + `/*(tph): ${Math.random()}*/`);
+
+ try {
+ await import(`data:text/javascript;charset=utf-8,${encodedText}`);
+ } catch (error) {
+ this.console.log(error);
+ }
+ }
+
+ stop() {
+ this.isRunning = false;
+
+ window.libInternalAbortController?.abort();
+ }
+
+ toggle() {
+ if (this.isRunning) this.stop();
+ else this.run();
+ }
+}
+
diff --git a/js/index.js b/js/index.js
index 8ff47a2..fa9ba40 100644
--- a/js/index.js
+++ b/js/index.js
@@ -1,21 +1,11 @@
///
import { Debounce } from "./debounce.js";
+import { PlaygroundConsole } from "./playground-console.js";
+import { CodeRunner } from "./code-runner.js";
-async function runCode(code, consoleCode) {
- consoleCode.textContent += `\nRunning code....\n`;
- try {
- window.libInternalAbortController?.abort();
- window.libInternalAbortController = new AbortController();
- await import(
- `data:text/javascript;charset=utf-8,${
- encodeURIComponent(code + `/*(tph): ${Math.random()}*/`)
- }`
- );
- } catch (error) {
- consoleCode.textContent += `${error}\n`;
- }
-}
+const playgroundConsole = new PlaygroundConsole(document.querySelector("#console-code"));
+const codeRunner = new CodeRunner(playgroundConsole);
const editor = ace.edit("editor");
editor.setTheme("ace/theme/gruvbox");
@@ -28,7 +18,6 @@ const saveButton = document.querySelector("#save-button");
const saveDropdown = document.querySelector("#save-dropdown");
const saveJsButton = document.querySelector("#save-js");
const saveHtmlButton = document.querySelector("#save-html");
-const consoleCode = document.querySelector("#console-code");
const sessionSaveDebounce = new Debounce(1000);
editor.addEventListener("change", (ev) => {
@@ -39,9 +28,17 @@ editor.addEventListener("change", (ev) => {
runButton.onclick = (ev) => {
const code = editor.getValue();
- runCode(code, consoleCode);
- runButton.textContent = "◼ Stop";
- runButton.classList.add("active");
+
+ codeRunner.setCode(code);
+ codeRunner.toggle();
+
+ if (codeRunner.isRunning) {
+ runButton.textContent = "✋ Stop";
+ runButton.classList.add("active");
+ } else {
+ runButton.textContent = "🏃 Run";
+ runButton.classList.remove("active");
+ }
};
function downloadFile(content, mime, extension) {
diff --git a/js/playground-console.js b/js/playground-console.js
new file mode 100644
index 0000000..2191731
--- /dev/null
+++ b/js/playground-console.js
@@ -0,0 +1,10 @@
+export class PlaygroundConsole {
+ constructor(elem) {
+ this.elem = elem;
+ }
+
+ log(text) {
+ this.elem.textContent += `\n${text}\n`;
+ }
+}
+