moveable divider
authorBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 21 Jul 2021 13:05:04 +0000 (08:05 -0500)
committerBrendan Hansen <brendan.f.hansen@gmail.com>
Wed, 21 Jul 2021 13:05:04 +0000 (08:05 -0500)
static/css/index.css
static/src/index.js
static/src/resizer.js [new file with mode: 0644]
templates/index.html

index dc3f536333576779c03e54c9fdfb1c782d2bc540..3cb273b4f5d07d7abed6f9f1f31c1e3f9d68507f 100644 (file)
@@ -1,5 +1,7 @@
 :root {
     --menu-bar-height: 32px;
+    --divider-size: 4px;
+    --left-half-width: 70%;
 }
 
 * {
@@ -49,24 +51,27 @@ button:hover {
 }
 
 .left-half, .right-half {
-    width: 50%;
-    height: 100%;
+    height: calc(100% - var(--menu-bar-height));
     float: left;
     display: inline-block;
 }
 
+.left-half {
+    width: calc(var(--left-half-width) - var(--divider-size) / 2);
+}
+
+.right-half {
+    width: calc((100% - var(--left-half-width)) - var(--divider-size) / 2);
+}
+
 .top-half, .bottom-half {
     width: 100%;
     float: left;
     display: inline-block;
 }
 
-.top-half {
-    height: var(--menu-bar-height);
-}
-
-.bottom-half {
-    height: calc(100% - var(--menu-bar-height));
+.menu-bar {
+    min-height: var(--menu-bar-height);
 }
 
 #code-editor {
@@ -91,3 +96,12 @@ button:hover {
     color: #f55;
 }
 
+#horizontal-divider {
+    min-width: var(--divider-size);
+    height: 100%;
+    background-color: #777;
+    cursor: col-resize;
+
+    display: inline-block;
+    float: left;
+}
index c5a8625fdbe1f6cb4deb7e2399ff0cb2707c10c7..830352fd4aaab54b108b2d7d083187dcb35e8a91 100644 (file)
@@ -204,4 +204,8 @@ window.onload = () => {
     editor.session.setMode('ace/mode/onyx');
 
     load_settings();
+
+    make_resizer("horizontal-divider", "--left-half-width", (e) => {
+        editor.resize(true);
+    });
 };
diff --git a/static/src/resizer.js b/static/src/resizer.js
new file mode 100644 (file)
index 0000000..5952c3b
--- /dev/null
@@ -0,0 +1,52 @@
+function make_resizer(divider_id, css_prop_name, on_resize) {
+    const elem = document.getElementById(divider_id);
+    const left_elem = elem.previousElementSibling;
+    const right_elem = elem.nextElementSibling;
+    const root = document.documentElement;
+
+    let mx = 0;
+    let my = 0;
+    let left_width = 0;   // in percent
+
+    const mouse_move_handler = (e) => {
+        const dx = e.clientX - mx;
+        const dy = e.clientY - my;
+
+        const lw = (left_width + dx) * 100 / elem.parentNode.getBoundingClientRect().width;
+        root.style.setProperty(css_prop_name, `${lw}%`);
+
+        document.body.style.cursor = 'col-resize';
+
+        left_elem.style.userSelect = 'none';
+        left_elem.style.pointerEvents = 'none';
+
+        right_elem.style.userSelect = 'none';
+        right_elem.style.pointerEvents = 'none';
+
+        if (on_resize != null) on_resize(e);
+    };
+
+    const mouse_up_handler = (e) => {
+        document.removeEventListener("mousemove", mouse_move_handler);
+        document.removeEventListener("mouseup",   mouse_up_handler);
+
+        document.body.style.removeProperty("cursor");
+
+        left_elem.style.removeProperty('user-select');
+        left_elem.style.removeProperty('pointer-events');
+
+        right_elem.style.removeProperty('user-select');
+        right_elem.style.removeProperty('pointer-events');
+    };
+
+    const mouse_down_handler = (e) => {
+        mx = e.clientX;
+        my = e.clientY;
+        left_width = left_elem.getBoundingClientRect().width;
+
+        document.addEventListener("mousemove", mouse_move_handler);
+        document.addEventListener("mouseup",   mouse_up_handler);
+    };
+
+    elem.addEventListener("mousedown", mouse_down_handler);
+}
index b2c6ed052bfaeb044713fcfff4264a554c7c77ec..83cb65aeb2a0e6500be54f7cf8d092c6c7a12e52 100644 (file)
@@ -6,39 +6,39 @@
         <link rel="stylesheet" href="{{ config['ENDPOINT'] + url_for('static', filename='css/index.css') }}" />
 
         <script> window.ROOT_ENDPOINT = "{{ config['ENDPOINT']}}" </script>
+        <script src="{{ config['ENDPOINT'] + url_for('static', filename='src/resizer.js') }}"></script>
         <script src="{{ config['ENDPOINT'] + url_for('static', filename='src/index.js') }}"></script>
         <script src="{{ config['ENDPOINT'] + url_for('static', filename='src/vendor/ace/ace.js') }}"></script>
     </head>
 
     <body>
+        <div class="menu-bar">
+            <select aria-label="Keybindings" name="keybindings" id="code-editor-keybindings" onchange="change_keybindings()">
+                <option value="normal">Normal</option>
+                <option value="vim">Vim</option>
+                <option value="emacs">Emacs</option>
+                <option value="sublime">Sublime Text</option>
+                <option value="vscode">VS Code</option>
+            </select>
+
+            <select aria-label="Theme" name="editor-theme" id="code-editor-theme" onchange="change_editor_theme()">
+                <option value="ambiance">Ambiance</option>
+                <option value="chaos">Chaos</option>
+                <option value="chrome">Chrome</option>
+                <option value="clouds">Clouds</option>
+                <option value="github">Github</option>
+                <option selected value="monokai">Monokai</option>
+                <option value="tomorrow-night-bright">Tomorrow Night Bright</option>
+            </select>
+
+            <button onclick="prompt_download()">Save</button>
+            <button onclick="submit_code()">Run</button>
+            <button onclick="kill_code()">Stop</button>
+
+            <span id="running-msg"></span>
+        </div>
+
         <div class="left-half">
-            <div class="top-half">
-                <select aria-label="Keybindings" name="keybindings" id="code-editor-keybindings" onchange="change_keybindings()">
-                    <option value="normal">Normal</option>
-                    <option value="vim">Vim</option>
-                    <option value="emacs">Emacs</option>
-                    <option value="sublime">Sublime Text</option>
-                    <option value="vscode">VS Code</option>
-                </select>
-
-                <select aria-label="Theme" name="editor-theme" id="code-editor-theme" onchange="change_editor_theme()">
-                    <option value="ambiance">Ambiance</option>
-                    <option value="chaos">Chaos</option>
-                    <option value="chrome">Chrome</option>
-                    <option value="clouds">Clouds</option>
-                    <option value="github">Github</option>
-                    <option selected value="monokai">Monokai</option>
-                    <option value="tomorrow-night-bright">Tomorrow Night Bright</option>
-                </select>
-
-                <button onclick="prompt_download()">Save</button>
-                <button onclick="submit_code()">Run</button>
-                <button onclick="kill_code()">Stop</button>
-
-                <span id="running-msg"></span>
-            </div>
-
-            <div class="bottom-half">
             <pre id="code-editor" ondragover="handle_dragover(event);" ondrop="handle_drop(event);">
 #load "core/std"
 
@@ -47,17 +47,13 @@ use package core
 main :: (args: [] cstr) {
     println("Hello, Onyx!");
 }</pre>
-            </div>
         </div>
 
-        <div class="right-half">
-            <div class="top-half">
-            </div>
+        <div id="horizontal-divider"></div>
 
-            <div class="bottom-half">
-                <pre id="code-result">
-                </pre>
-            </div>
+        <div class="right-half">
+            <pre id="code-result">
+            </pre>
         </div>
     </body>
 </html>