output-frame.ts

85 lines | 2.683 kB Blame History Raw Download
import { BaseElement } from "../../../shared/_base";
import './output-frame.less';
import { GetOutputFrameUrl } from "../../../shared/url-helpers";
import { GetNotificationBubbles } from "../../../shared/getdom";
import { postMessage } from "../../../shared/post-message";

export class OutputFrame extends BaseElement {
    public Iframe: HTMLIFrameElement | null = null;
    private CurrentIframeScriptRemoveResponseListener: Function | null = null;

    constructor() {
        super();
    }

    private scripts: any = {};

    onInit(): void {
        this.reset();
    }

    onUpdate(): void {
    }

    reset(onload: ((ev: Event) => void) | null = null, resetNotificationBubbles: boolean = true) {
        if (this.CurrentIframeScriptRemoveResponseListener != null) {
            this.CurrentIframeScriptRemoveResponseListener();
            this.CurrentIframeScriptRemoveResponseListener = null;
        }

        if (this.Iframe && this.hasChild(this.Iframe)) {
            this.removeChild(this.Iframe);
        }

        this.Iframe = document.createElement("iframe");
        this.Iframe.setAttribute("sandbox", "allow-pointer-lock allow-same-origin allow-scripts");
        this.Iframe.src = GetOutputFrameUrl();

        if (onload) {
            this.Iframe.onload = ((ev) => {
                onload(ev);
            });
        }

        this.appendChild(this.Iframe);

        if (resetNotificationBubbles) {
            var bubbles = GetNotificationBubbles();
            if (bubbles && bubbles.reset) {
                bubbles.reset();
            }
        }
    }

    setError() {
        this.reset(() => {
            if (this.Iframe)
                this.Iframe.src = GetOutputFrameUrl() + "execution-time-error.html";
        });
    }

    setScript(language: string, value: string) {
        this.scripts[language] = value;
        this.reset(() => {
            for (const lang in this.scripts) {
                if (lang != "javascript")
                    this.doPostMessage(lang, this.scripts[lang]);
            }

            if (this.scripts["javascript"])
                this.doPostMessage("javascript", this.scripts["javascript"]);
        });
    }

    doPostMessage(language: string, value: string) {
        this.CurrentIframeScriptRemoveResponseListener = postMessage(this.Iframe?.contentWindow, language, this.scripts[language], language == 'javascript' ? (executeTimeInMs, exceedTimeInMs) => {
            if (executeTimeInMs === -1) {
                this.setError();
            }
            else {
                var bubbles = GetNotificationBubbles();
                bubbles.add(language + " executed in: " + executeTimeInMs + "ms", "info");
            }
        } : undefined);
    }
}