code-editor

Details

diff --git a/codeeditor-app/app.html b/codeeditor-app/app.html
index 0febe63..d803575 100644
--- a/codeeditor-app/app.html
+++ b/codeeditor-app/app.html
@@ -1,15 +1,15 @@
 <div class="flex-vert">
     <div class="flex-shrink section top">
         <h1>code editor</h1>
-        <window-control>
+        <window-control distribute=".code-editor-containers">
             <window-control-connector target="code-editor-container[language='Javascript']" class="active">Javascript</window-control-connector>
             <window-control-connector target="code-editor-container[language='HTML']">HTML</window-control-connector>
             <window-control-connector target="code-editor-container[language='CSS']">CSS</window-control-connector>
         </window-control>
     </div>
-    <div class="flex-horiz">
-        <div class="code-editor-containers resize-target flex-vert" style="min-width: 50%; max-width: 50%;">
-            <code-editor-container language="Javascript" dir="vertical">
+    <div class="flex-dynamic">
+        <div class="code-editor-containers flex-vert">
+            <code-editor-container language="Javascript" dir="vertical" class="first-visible last-visible">
             </code-editor-container>
             
             <code-editor-container language="HTML" dir="vertical" style="display: none;">
@@ -18,8 +18,9 @@
             <code-editor-container language="CSS" dir="vertical" style="display: none;">
             </code-editor-container>
         </div>
-        <div>
-            <resize-handle target=".resize-target" dir="horizontal"></resize-handle>
+        <div class="output-frame-container">
+            <resize-handle target=".code-editor-containers" dir="horizontal"></resize-handle>
+            <resize-handle target=".code-editor-containers" dir="vertical" place="top"></resize-handle>
             <output-frame></output-frame>
         </div>
     </div>
diff --git a/codeeditor-app/app.less b/codeeditor-app/app.less
index 99cc228..9a7685e 100644
--- a/codeeditor-app/app.less
+++ b/codeeditor-app/app.less
@@ -22,6 +22,16 @@ html, body {
     height: 100%;
 }
 
+.flex-horiz > * {
+    min-height: auto !important;
+    max-height: none !important;
+}
+
+.flex-vert > * {
+    min-width: auto !important;
+    max-width: none !important;
+}
+
 
 .flex-horiz > *, .flex-vert > * {
     flex-grow: 1;
@@ -89,11 +99,57 @@ body {
     background: @editor-bg-white;
 }
 
-.code-editor-containers.force-close {
+.flex-dynamic.flex-horiz .code-editor-containers {
+    min-width: 50%;
+    max-width: 50%;
+}
+
+.flex-dynamic.flex-vert .code-editor-containers {
+    min-height: 50%;
+    max-height: 50%;
+}
+
+.flex-dynamic.flex-horiz .code-editor-containers.force-close {
     min-width: 0 !important;
     max-width: 0 !important;
 }
 
+.flex-dynamic.flex-vert .code-editor-containers.force-close {
+    min-height: 0 !important;
+    max-height: 0 !important;
+}
+
+.flex-dynamic.flex-horiz .code-editor-containers resize-handle[dir='vertical'] {
+    display: none;
+}
+
+.flex-dynamic.flex-vert .code-editor-containers resize-handle[dir='horizontal'] {
+    display: none;
+}
+
+@media (orientation: landscape) and (max-height: 320px) {
+    .output-frame-container {
+        display: none;
+    }
+
+    .code-editor-containers {
+        min-width: 100% !important;
+        max-width: 100% !important;
+    }
+}
+
+@media (orientation: portrait) and (max-height: 400px) {
+    .output-frame-container {
+        display: none;
+    }
+
+    .code-editor-containers {
+        min-height: 100% !important;
+        max-height: 100% !important;
+    }
+}
+
+
 @media (prefers-color-scheme: dark) {
     body {
         background: @median-bg-dark;
diff --git a/codeeditor-app/boot.ts b/codeeditor-app/boot.ts
index 0e4eb2b..b990417 100644
--- a/codeeditor-app/boot.ts
+++ b/codeeditor-app/boot.ts
@@ -1,7 +1,6 @@
 import './app.less';
 import bootHtml from './app.html';
 import { AppRoot } from './elements/app-root/app-root';
-import { CodeEditor } from './elements/code-editor/code-editor';
 import { OutputFrame } from './elements/output-frame/output-frame';
 import { NotificationBubbles } from './elements/notification-bubbles/notification-bubbles';
 import { NotificationBubble } from './elements/notification-bubbles/notification-bubble';
@@ -9,16 +8,24 @@ import { ResizeHandle } from './elements/resize-handle/resize-handle';
 import { CodeEditorContainer } from './elements/code-editor-container/code-editor-container';
 import { WindowControl } from './elements/window-control/window-control';
 import { WindowControlConnector } from './elements/window-control/window-control connector';
+import { JavascriptCodeEditor } from './elements/code-editor/javascript-code-editor';
+import { HtmlCodeEditor } from './elements/code-editor/html-code-editor';
+import { CssCodeEditor } from './elements/code-editor/css-code-editor';
+import { setDynamicFlexListener } from '../shared/set-dynamic-flex-listener';
 
 window.customElements.define('app-root', AppRoot);
-window.customElements.define('code-editor', CodeEditor);
+window.customElements.define('code-editor-container', CodeEditorContainer);
+window.customElements.define('javascript-code-editor', JavascriptCodeEditor);
+window.customElements.define('html-code-editor', HtmlCodeEditor);
+window.customElements.define('css-code-editor', CssCodeEditor);
 window.customElements.define('output-frame', OutputFrame);
 window.customElements.define('notification-bubbles', NotificationBubbles);
 window.customElements.define('notification-bubble', NotificationBubble);
 window.customElements.define('resize-handle', ResizeHandle);
-window.customElements.define('code-editor-container', CodeEditorContainer);
 window.customElements.define('window-control', WindowControl);
 window.customElements.define('window-control-connector', WindowControlConnector);
 
 
-document.body.innerHTML += bootHtml;
\ No newline at end of file
+document.body.innerHTML += bootHtml;
+
+setDynamicFlexListener();
diff --git a/codeeditor-app/elements/code-editor/code-editor.less b/codeeditor-app/elements/code-editor/code-editor.less
index 05271ad..f87f9bd 100644
--- a/codeeditor-app/elements/code-editor/code-editor.less
+++ b/codeeditor-app/elements/code-editor/code-editor.less
@@ -1,15 +1,15 @@
 @import url('../../../shared/theme.less');
 
-code-editor {
+code-editor, css-code-editor, html-code-editor, javascript-code-editor {
     width: 100%;
     height: 100%;
-    display: block;
+    position: absolute;
     background: @editor-bg-white;
     color: @primary-text-color-white;
 }
 
 @media (prefers-color-scheme: dark) {
-    code-editor {
+    code-editor, css-code-editor, html-code-editor, javascript-code-editor {
         background: @editor-bg-dark;
         color: @primary-text-color-dark;
     }
diff --git a/codeeditor-app/elements/code-editor/code-editor.ts b/codeeditor-app/elements/code-editor/code-editor.ts
index 25f231b..cdf8a1a 100644
--- a/codeeditor-app/elements/code-editor/code-editor.ts
+++ b/codeeditor-app/elements/code-editor/code-editor.ts
@@ -2,12 +2,7 @@ import { BaseElement } from "../../../shared/_base";
 import './code-editor.less';
 import * as monaco from 'monaco-editor';
 import { OutputFrame } from "../output-frame/output-frame";
-import initJs from '!!raw-loader!./injects/editor-init.js';
-import initHtml from '!!raw-loader!./injects/editor-init.html';
-import initCss from '!!raw-loader!./injects/editor-init.css';
-import spiralBoxesSolutionScript from '!!raw-loader!./injects/spiral-boxes-solution.js';
 import { debounceManager } from "../../../shared/ensure-debounce";
-import declarations from '!!raw-loader!./injects/declarations.d.ts';
 
 export class CodeEditor extends BaseElement {
 
@@ -17,8 +12,10 @@ export class CodeEditor extends BaseElement {
     onInit(): void {
 
         this.initWorkers();
-        this.language = this.getAttribute("language")?.toLocaleLowerCase() ?? "javascript";
-        this.input = this.setInitInput(this.language);
+        this.input = this.setInitInput();
+        this.language = this.tagName.substring(0, this.tagName.indexOf("-")).toLocaleLowerCase();
+
+        console.log(this.language);
 
         const prefersDarkScheme = window.matchMedia("(prefers-color-scheme: dark)");
 
@@ -34,72 +31,26 @@ export class CodeEditor extends BaseElement {
             theme: prefersDarkScheme.matches ? 'vs-dark' : 'vs-light'
         });
 
-
-
-
         var debounce = debounceManager(1000);
         editor.onDidChangeModelContent((e) => {
             this.input = editor.getValue();
             debounce.ensureDebounce(() => {
-                this.outputFrame.setScript(this.language, this.input);
+                this.outputFrame.setContent(this.language, this.input);
             });
         });
 
         this.waitFor(this.outputFrame, () => {
-            this.outputFrame.setScript(this.language, this.input);
+            this.outputFrame.setContent(this.language, this.input);
         });
 
     }
 
-    setInitInput(language: string | null) {
-        if (language) {
-            if (language.toLowerCase() === "javascript") {
-                this.initJs();
-                return initJs;
-            }
-            else if (language.toLowerCase() === 'html') {
-                return initHtml;
-            }
-            else if (language.toLowerCase() === 'css') {
-                return initCss;
-            }
-        }
+    setInitInput(): string {
         return "";
     }
 
-    initJs() {
-        monaco.languages.typescript.javascriptDefaults.addExtraLib(declarations, 'ts:filename/declarations.d.ts');
-
-        monaco.languages.registerCompletionItemProvider("javascript", {
-            provideCompletionItems: (model, position, context, token) => {
-                return {
-                    suggestions: [
-                        {
-                            label: 'for',
-                            kind: monaco.languages.CompletionItemKind.Snippet,
-                            insertText: 'for (let i = 0; i < ${1:array}.length; i++) {\n\t$0\n}',
-                            range: <any>null,
-                            insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet
-                        },
-                        {
-                            label: 'forr',
-                            kind: monaco.languages.CompletionItemKind.Snippet,
-                            insertText: 'for (var i = ${1:array}.length - 1; i >= 0; i--) {\n\t$0\n}',
-                            range: <any>null,
-                            insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet
-                        },
-                        {
-                            label: 'spiralBoxesSolutionSnippet',
-                            detail: "inserts solution of spiral boxes",
-                            kind: monaco.languages.CompletionItemKind.Snippet,
-                            insertText: spiralBoxesSolutionScript,
-                            range: <any>null,
-                            insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet
-                        }
-                    ]
-                }
-            }
-        });
+    setInitSettings(): void {
+
     }
 
 
diff --git a/codeeditor-app/elements/code-editor/css-code-editor.ts b/codeeditor-app/elements/code-editor/css-code-editor.ts
new file mode 100644
index 0000000..77f32f8
--- /dev/null
+++ b/codeeditor-app/elements/code-editor/css-code-editor.ts
@@ -0,0 +1,28 @@
+import { CodeEditor } from "./code-editor";
+import * as monaco from 'monaco-editor';
+import initCss from '!!raw-loader!./injects/editor-init.css';
+import { createScript } from "../../../shared/create-script";
+
+export class CssCodeEditor extends CodeEditor {
+    setInitInput(): string {
+        return initCss;
+    }
+
+    setInitSettings(): void {
+        monaco.languages.registerCompletionItemProvider("css", {
+            provideCompletionItems: (model, position, context, token) => {
+                return {
+                    suggestions: [
+                        {
+                            label: 'insert-flex',
+                            kind: monaco.languages.CompletionItemKind.Snippet,
+                            insertText: createScript('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js', false).toString(),
+                            range: <any>null,
+                            insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet
+                        }
+                    ]
+                }
+            }
+        });
+    }
+}
\ No newline at end of file
diff --git a/codeeditor-app/elements/code-editor/html-code-editor.ts b/codeeditor-app/elements/code-editor/html-code-editor.ts
new file mode 100644
index 0000000..fcb7cba
--- /dev/null
+++ b/codeeditor-app/elements/code-editor/html-code-editor.ts
@@ -0,0 +1,28 @@
+import { CodeEditor } from "./code-editor";
+import * as monaco from 'monaco-editor';
+import initHtml from '!!raw-loader!./injects/editor-init.html';
+import { createScript } from "../../../shared/create-script";
+
+export class HtmlCodeEditor extends CodeEditor {
+    setInitInput(): string {
+        return initHtml;
+    }
+
+    setInitSettings(): void {
+        monaco.languages.registerCompletionItemProvider("html", {
+            provideCompletionItems: (model, position, context, token) => {
+                return {
+                    suggestions: [
+                        {
+                            label: 'jqueryCDN',
+                            kind: monaco.languages.CompletionItemKind.Snippet,
+                            insertText: createScript('https://cdnjs.cloudflare.com/ajax/libs/jquery/3.6.0/jquery.min.js', false).toString(),
+                            range: <any>null,
+                            insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet
+                        }
+                    ]
+                }
+            }
+        });
+    }
+}
\ No newline at end of file
diff --git a/codeeditor-app/elements/code-editor/injects/editor-init.js b/codeeditor-app/elements/code-editor/injects/editor-init.js
index a74da39..d5256b5 100644
--- a/codeeditor-app/elements/code-editor/injects/editor-init.js
+++ b/codeeditor-app/elements/code-editor/injects/editor-init.js
@@ -1,4 +1,4 @@
-//create a box
+//create a box:
 box(10, 10, 20, 20);
 
 //use random:
diff --git a/codeeditor-app/elements/code-editor/javascript-code-editor.ts b/codeeditor-app/elements/code-editor/javascript-code-editor.ts
new file mode 100644
index 0000000..0324f2a
--- /dev/null
+++ b/codeeditor-app/elements/code-editor/javascript-code-editor.ts
@@ -0,0 +1,46 @@
+import { CodeEditor } from "./code-editor";
+import * as monaco from 'monaco-editor';
+import initScript from '!!raw-loader!./injects/editor-init.js';
+import spiralBoxesSolutionScript from '!!raw-loader!./injects/spiral-boxes-solution.js';
+import declarations from '!!raw-loader!./injects/declarations.d.ts';
+
+export class JavascriptCodeEditor extends CodeEditor {
+    setInitInput(): string {
+        return initScript;
+    }
+
+    setInitSettings(): void {
+        monaco.languages.typescript.javascriptDefaults.addExtraLib(declarations, 'ts:filename/declarations.d.ts');
+
+        monaco.languages.registerCompletionItemProvider("javascript", {
+            provideCompletionItems: (model, position, context, token) => {
+                return {
+                    suggestions: [
+                        {
+                            label: 'for',
+                            kind: monaco.languages.CompletionItemKind.Snippet,
+                            insertText: 'for (let i = 0; i < ${1:array}.length; i++) {\n\t$0\n}',
+                            range: <any>null,
+                            insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet
+                        },
+                        {
+                            label: 'forr',
+                            kind: monaco.languages.CompletionItemKind.Snippet,
+                            insertText: 'for (var i = ${1:array}.length - 1; i >= 0; i--) {\n\t$0\n}',
+                            range: <any>null,
+                            insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet
+                        },
+                        {
+                            label: 'spiralBoxesSolutionSnippet',
+                            detail: "inserts solution of spiral boxes",
+                            kind: monaco.languages.CompletionItemKind.Snippet,
+                            insertText: spiralBoxesSolutionScript,
+                            range: <any>null,
+                            insertTextRules: monaco.languages.CompletionItemInsertTextRule.InsertAsSnippet
+                        }
+                    ]
+                }
+            }
+        });
+    }
+}
\ No newline at end of file
diff --git a/codeeditor-app/elements/code-editor-container/code-editor-container.less b/codeeditor-app/elements/code-editor-container/code-editor-container.less
index 0b1e01b..ed386c7 100644
--- a/codeeditor-app/elements/code-editor-container/code-editor-container.less
+++ b/codeeditor-app/elements/code-editor-container/code-editor-container.less
@@ -1,12 +1,28 @@
 @import url('../../../shared/theme.less');
 
-div > code-editor-container.active:last-child {
+code-editor-container {
+    min-height: 100%; 
+    max-height: 100%;
+}
+
+code-editor-container.first-visible .code-editor-header {
+    border-top-color: transparent;
+}
+
+
+code-editor-container.last-visible {
     min-height: auto !important;
     max-height: none !important;
     min-width: auto !important;
     max-width: none !important;
 }
 
+code-editor-container.last-visible > resize-handle {
+    display: none !important;
+}
+
+
+
 .code-editor-header {
     padding: 10px 18px;
     background: lighten(@editor-bg-white, 1%);
@@ -17,6 +33,10 @@ div > code-editor-container.active:last-child {
     border-width: 1px;
 }
 
+.code-editor-content {
+
+}
+
 @media (prefers-color-scheme: dark) {
     .code-editor-header {
         background: lighten(@editor-bg-dark, 1%);
diff --git a/codeeditor-app/elements/code-editor-container/code-editor-container.ts b/codeeditor-app/elements/code-editor-container/code-editor-container.ts
index 2796983..665fbd4 100644
--- a/codeeditor-app/elements/code-editor-container/code-editor-container.ts
+++ b/codeeditor-app/elements/code-editor-container/code-editor-container.ts
@@ -23,12 +23,15 @@ export class CodeEditorContainer extends BaseElement {
     }
 
     createCodeEditor(language: string, expandDir: 'vertical' | 'horizontal') {
-        var codeEditor = <CodeEditor>document.createElement("code-editor");
-        codeEditor.setAttribute("language", language);
+        var codeEditorContent = document.createElement("div");
+        codeEditorContent.classList.add("code-editor-content");
+        var codeEditor = <CodeEditor>document.createElement(language + "-code-editor");
+        codeEditorContent.appendChild(codeEditor);
+
         var resizeHandle = <ResizeHandle>document.createElement("resize-handle");
         resizeHandle.setAttribute("dir", expandDir);
 
-        this.appendChild(codeEditor);
+        this.appendChild(codeEditorContent);
         this.appendChild(resizeHandle);
     }
 }
\ No newline at end of file
diff --git a/codeeditor-app/elements/output-frame/output-frame.ts b/codeeditor-app/elements/output-frame/output-frame.ts
index ff2215e..c56993d 100644
--- a/codeeditor-app/elements/output-frame/output-frame.ts
+++ b/codeeditor-app/elements/output-frame/output-frame.ts
@@ -12,7 +12,7 @@ export class OutputFrame extends BaseElement {
         super();
     }
 
-    private scripts: any = {};
+    private contents: any = {};
 
     onInit(): void {
         this.reset();
@@ -58,21 +58,21 @@ export class OutputFrame extends BaseElement {
         });
     }
 
-    setScript(language: string, value: string) {
-        this.scripts[language] = value;
+    setContent(language: string, value: string) {
+        this.contents[language] = value;
         this.reset(() => {
-            for (const lang in this.scripts) {
+            for (const lang in this.contents) {
                 if (lang != "javascript")
-                    this.doPostMessage(lang, this.scripts[lang]);
+                    this.doPostMessage(lang, this.contents[lang]);
             }
 
-            if (this.scripts["javascript"])
-                this.doPostMessage("javascript", this.scripts["javascript"]);
+            if (this.contents["javascript"])
+                this.doPostMessage("javascript", this.contents["javascript"]);
         });
     }
 
     doPostMessage(language: string, value: string) {
-        this.CurrentIframeScriptRemoveResponseListener = postMessage(this.Iframe?.contentWindow, language, this.scripts[language], language == 'javascript' ? (executeTimeInMs, exceedTimeInMs) => {
+        this.CurrentIframeScriptRemoveResponseListener = postMessage(this.Iframe?.contentWindow, language, this.contents[language], language == 'javascript' ? (executeTimeInMs, exceedTimeInMs) => {
             if (executeTimeInMs === -1) {
                 this.setError();
             }
diff --git a/codeeditor-app/elements/resize-handle/resize-handle.less b/codeeditor-app/elements/resize-handle/resize-handle.less
index 361f49f..78b4719 100644
--- a/codeeditor-app/elements/resize-handle/resize-handle.less
+++ b/codeeditor-app/elements/resize-handle/resize-handle.less
@@ -29,6 +29,11 @@ resize-handle:hover, resize-handle.active {
     transition: none;
 }
 
+resize-handle[dir="vertical"][place='top'] {
+    top: 0;
+    bottom: auto;
+}
+
 #fixed-resize-overlay {
     position: fixed;
     left: 0;
diff --git a/codeeditor-app/elements/resize-handle/resize-handle.ts b/codeeditor-app/elements/resize-handle/resize-handle.ts
index 89f7a3b..a9683f7 100644
--- a/codeeditor-app/elements/resize-handle/resize-handle.ts
+++ b/codeeditor-app/elements/resize-handle/resize-handle.ts
@@ -105,7 +105,7 @@ export class ResizeHandle extends BaseElement {
         overlay.addEventListener("touchmove", (evt: TouchEvent) => {
             this.getIframe().style.pointerEvents = "none";
             this.classList.add("active");
-            this.setSize(targetStartSize.width + (start.x - evt.touches[0].pageX), targetStartSize.height + (start.y - evt.touches[0].pageY));
+            this.setSize(targetStartSize.width + (evt.touches[0].pageX - start.x), targetStartSize.height + (evt.touches[0].pageY - start.y));
         });
 
         overlay.addEventListener("touchend", (evt: TouchEvent) => {
diff --git a/codeeditor-app/elements/window-control/window-control connector.ts b/codeeditor-app/elements/window-control/window-control connector.ts
index e846390..93030d2 100644
--- a/codeeditor-app/elements/window-control/window-control connector.ts
+++ b/codeeditor-app/elements/window-control/window-control connector.ts
@@ -1,5 +1,6 @@
 import { BaseElement } from "../../../shared/_base";
 import { CodeEditorContainer } from "../code-editor-container/code-editor-container";
+import { WindowControl } from "./window-control";
 import './window-control-connector.less';
 
 export class WindowControlConnector extends BaseElement {
@@ -25,7 +26,7 @@ export class WindowControlConnector extends BaseElement {
 
         if (target) {
             target.classList.add("active");
-            target.style.display = "block";
+            target.style.display = "";
         }
 
         this.distributeEvenly();
@@ -44,20 +45,40 @@ export class WindowControlConnector extends BaseElement {
     }
 
     private distributeEvenly() {
-        var elements = <CodeEditorContainer[]>this.findVisible("code-editor-container");
-        var containers = document.getElementsByClassName("code-editor-containers")[0];
 
-        if (elements.length === 0) {
-            containers.classList.add("force-close");
-        }
-        else {
-            containers.classList.remove("force-close");
-            var size = (100 / elements.length) + "%";
-            for (let i = 0; i < elements.length; i++) {
-                const element = elements[i];
+        var windowControl = <WindowControl>this.parentElement;
+        var distTarget = windowControl.getDistibuteTarget();
+
+        if (distTarget) {
+            var visibleTargetChildren = this.visibleChildren(distTarget);
+            console.log(visibleTargetChildren);
+
+            if (visibleTargetChildren.length === 0) {
+                distTarget.classList.add("force-close");
+            }
+            else {
+                distTarget.classList.remove("force-close");
+                var size = (100 / visibleTargetChildren.length) + "%";
+                for (let i = 0; i < visibleTargetChildren.length; i++) {
+                    const element = visibleTargetChildren[i];
+
+                    element.style.minHeight = size;
+                    element.style.maxHeight = size;
 
-                element.style.minHeight = size;
-                element.style.maxHeight = size;
+                    if (i === 0) {
+                        element.classList.add("first-visible");
+                    }
+                    else {
+                        element.classList.remove("first-visible");
+                    }
+                    
+                    if (i + 1 === visibleTargetChildren.length) {
+                        element.classList.add("last-visible");
+                    }
+                    else {
+                        element.classList.remove("last-visible");
+                    }
+                }
             }
         }
     }
diff --git a/codeeditor-app/elements/window-control/window-control.ts b/codeeditor-app/elements/window-control/window-control.ts
index f1474d9..bf373b0 100644
--- a/codeeditor-app/elements/window-control/window-control.ts
+++ b/codeeditor-app/elements/window-control/window-control.ts
@@ -15,4 +15,13 @@ export class WindowControl extends BaseElement {
             }
         }
     }
+
+    getDistibuteTarget() {
+        var attr = this.getAttribute("distribute");
+        if (attr) {
+            return <HTMLElement>document.querySelector(attr);
+        }
+
+        return null;
+    }
 }
\ No newline at end of file

shared/_base.ts 13(+13 -0)

diff --git a/shared/_base.ts b/shared/_base.ts
index 82bb140..b416a70 100644
--- a/shared/_base.ts
+++ b/shared/_base.ts
@@ -84,6 +84,19 @@ export class BaseElement extends HTMLElement {
         return result;
     }
 
+    visibleChildren(inElement: HTMLElement = this) {
+        var result = [];
+
+        for (let i = 0; i < inElement.children.length; i++) {
+            const child = <HTMLElement>inElement.children[i];
+            if (child.style.display !== "none") {
+                result.push(child);
+            }
+        }
+
+        return result;
+    }
+
     hasChild(element: Element, startsWidth: boolean = false): boolean {
         var ele = this;
 
diff --git a/shared/create-script.ts b/shared/create-script.ts
index 2119c3f..6822ec4 100644
--- a/shared/create-script.ts
+++ b/shared/create-script.ts
@@ -1,13 +1,16 @@
 import { executeDrawQueue } from "../outputframe-app/injects/dom-helpers";
 
-export function createScript(value: string) {
+export function createScript(value: string, appendToBody: boolean = true): HTMLScriptElement {
     var script: HTMLScriptElement = document.createElement("script");
     script.setAttribute("async", "");
     script.innerHTML = value;
 
-    document.body.appendChild(script);
+    if (appendToBody) {
+        document.body.appendChild(script);
+        executeDrawQueue();
+    }
 
-    executeDrawQueue();
+    return script;
 }
 
 export function createHtml(value: string) {
diff --git a/shared/set-dynamic-flex-listener.ts b/shared/set-dynamic-flex-listener.ts
new file mode 100644
index 0000000..62200c0
--- /dev/null
+++ b/shared/set-dynamic-flex-listener.ts
@@ -0,0 +1,26 @@
+export function setDynamicFlexListener() {
+    var run = () => {
+        var flexDynamics = document.body.getElementsByClassName("flex-dynamic");
+        var isPortrait = window.matchMedia("(orientation: portrait)");
+        for (let i = 0; i < flexDynamics.length; i++) {
+            const flexDynamic = <HTMLElement>flexDynamics[i];
+
+            if (isPortrait.matches) {
+                flexDynamic.classList.add("flex-vert");
+                flexDynamic.classList.remove("flex-horiz");
+            }
+            else {
+                flexDynamic.classList.add("flex-horiz");
+                flexDynamic.classList.remove("flex-vert");
+            }
+
+        }
+    }
+
+    run();
+
+    window.addEventListener("resize", () => {
+        run();
+    });
+
+}
\ No newline at end of file