diff options
| author | Shulhan <ms@kilabit.info> | 2023-11-17 23:53:22 +0700 |
|---|---|---|
| committer | Shulhan <ms@kilabit.info> | 2023-11-17 23:53:22 +0700 |
| commit | ba625cecb647ef5fec013aff10a96395f1122270 (patch) | |
| tree | 0d3acc17c5d5e9e9eaec6a0f7cac4bdbdc4e9fe1 /_wui | |
| parent | 49f18f5fde5350545c6399823edd31ad8826fb90 (diff) | |
| download | awwan-ba625cecb647ef5fec013aff10a96395f1122270.tar.xz | |
_wui: add vertical resizer, to resize between VFS and editor
While at it, refactoring the layout using flex.
Diffstat (limited to '_wui')
| -rw-r--r-- | _wui/awwan.ts | 108 | ||||
| -rw-r--r-- | _wui/index.html | 54 | ||||
| -rw-r--r-- | _wui/main.js | 93 |
3 files changed, 197 insertions, 58 deletions
diff --git a/_wui/awwan.ts b/_wui/awwan.ts index 3352c0f..96ad15f 100644 --- a/_wui/awwan.ts +++ b/_wui/awwan.ts @@ -7,6 +7,7 @@ import { WuiResponseInterface } from "./wui/response.js"; import { WuiVfs, WuiVfsOptions, WuiVfsNodeInterface } from "./wui/vfs/vfs.js"; const CLASS_EDITOR_ACTION = "editor_action"; +const ID_AWWAN_NAV_LEFT = "awwan_nav_left"; const ID_BTN_DECRYPT = "com_btn_decrypt"; const ID_BTN_ENCRYPT = "com_btn_encrypt"; const ID_BTN_EXEC_LOCAL = "com_btn_local"; @@ -15,7 +16,9 @@ const ID_BTN_NEW_DIR = "com_btn_new_dir"; const ID_BTN_NEW_FILE = "com_btn_new_file"; const ID_BTN_REMOVE = "com_btn_remove"; const ID_BTN_SAVE = "com_btn_save"; -const ID_COM_RESIZE = "com_resize"; +const ID_COM_EDITOR_OUT = "com_editor_output"; +const ID_COM_RESIZE_EDITOR = "com_resize_editor"; +const ID_COM_RESIZE_VFS = "com_resize_vfs"; const ID_EDITOR = "com_editor"; const ID_INP_LINE_RANGE = "com_inp_line_range"; const ID_VFS_INPUT = "com_vfs_input"; @@ -47,16 +50,19 @@ export function renderHtml() { const el = document.createElement("div"); el.classList.add("awwan"); el.innerHTML = ` - <div class="awwan_nav_left"> - <div class="${ID_VFS_INPUT}"> - <input id="${ID_VFS_INPUT}" placeholder="Input text to filter (allow regexp)" /> + <div id="${ID_AWWAN_NAV_LEFT}" class="awwan_nav_left"> + <div class="awwan_vfs_form"> + <div class="${ID_VFS_INPUT}"> + <input id="${ID_VFS_INPUT}" placeholder="Input text to filter (allow regexp)" /> + </div> + <button id="${ID_BTN_NEW_DIR}">New dir.</button> + <button id="${ID_BTN_NEW_FILE}">New file</button> + <button id="${ID_BTN_REMOVE}">Remove</button> </div> - <button id="${ID_BTN_NEW_DIR}">New dir.</button> - <button id="${ID_BTN_NEW_FILE}">New file</button> - <button id="${ID_BTN_REMOVE}">Remove</button> <div id="${ID_VFS}"></div> </div> - <div class="awwan_content"> + <div id="${ID_COM_RESIZE_VFS}">⚌</div> + <div id="${ID_COM_EDITOR_OUT}" class="awwan_content"> <div class="boxheader"> <span class="tag">File</span> <span id="${ID_VFS_PATH}">-</span> @@ -65,7 +71,7 @@ export function renderHtml() { <button id="${ID_BTN_DECRYPT}" disabled="true">Decrypt</button> </div> <div id="${ID_EDITOR}"></div> - <div id="${ID_COM_RESIZE}">⚌</div> + <div id="${ID_COM_RESIZE_EDITOR}">⚌</div> <div id="${ID_OUTPUT_WRAPPER}" class="output"> <div> <div class="${CLASS_EDITOR_ACTION}"> @@ -89,6 +95,12 @@ export function renderHtml() { } export class Awwan { + // comNavLeft define a wrapper for left navigation, the left side. + private comNavLeft!: HTMLElement; + + // comEditorOutput element that wrap editor and output, the right side. + private comEditorOutput!: HTMLElement; + private comBtnEncrypt!: HTMLButtonElement; private comBtnLocal!: HTMLButtonElement; private comBtnNewDir!: HTMLButtonElement; @@ -115,10 +127,37 @@ export class Awwan { private notif!: WuiNotif; private vfs!: WuiVfs; private orgContent: string = ""; + private _posx: number = 0; private _posy: number = 0; constructor() { - let el = document.getElementById(ID_BTN_EXEC_LOCAL); + let el: HTMLElement | null; + + el = document.getElementById(ID_AWWAN_NAV_LEFT); + if (el) { + this.comNavLeft = el; + } + el = document.getElementById(ID_COM_EDITOR_OUT); + if (el) { + this.comEditorOutput = el; + } + + el = document.getElementById(ID_COM_RESIZE_VFS); + if (el) { + const doResizeVfs = (ev: MouseEvent) => this.doResizeVfs(ev); + + el.addEventListener("mousedown", () => { + this._posx = 0; + document.addEventListener("mousemove", doResizeVfs); + }); + + document.addEventListener("mouseup", () => { + document.removeEventListener("mousemove", doResizeVfs); + this._posx = 0; + }); + } + + el = document.getElementById(ID_BTN_EXEC_LOCAL); if (el) { this.comBtnLocal = el as HTMLButtonElement; this.comBtnLocal.onclick = () => { @@ -244,11 +283,11 @@ export class Awwan { this.onHashChange(url.hash); }; - const elResize = document.getElementById(ID_COM_RESIZE); - if (elResize) { - const onMouseMove = (ev: MouseEvent) => this.doResize(ev); + const elResizeEditor = document.getElementById(ID_COM_RESIZE_EDITOR); + if (elResizeEditor) { + const onMouseMove = (ev: MouseEvent) => this.doResizeEditor(ev); - elResize.addEventListener("mousedown", () => { + elResizeEditor.addEventListener("mousedown", () => { this._posy = 0; document.addEventListener("mousemove", onMouseMove); }); @@ -636,18 +675,51 @@ export class Awwan { this.vfs.filter(val); } - doResize(ev: MouseEvent) { + doResizeVfs(ev: MouseEvent) { + ev.preventDefault(); + + if (this._posx == 0) { + this._posx = ev.clientX; + return false; + } + const diff = this._posx - ev.clientX; + if (diff > 0) { + this.resizeVfsLeft(diff); + } else { + this.resizeVfsRight(diff * -1); + } + this._posx = ev.clientX; + return false; + } + + private resizeVfsLeft(diff: number) { + if (this.comNavLeft.clientWidth <= 300) { + return; + } + const width = this.comNavLeft.clientWidth - diff; + this.comNavLeft.style.width = `${width}px`; + } + + private resizeVfsRight(diff: number) { + if (this.comEditorOutput.clientWidth <= 600) { + return; + } + const width = this.comNavLeft.clientWidth + diff; + this.comNavLeft.style.width = `${width}px`; + } + + doResizeEditor(ev: MouseEvent) { if (this._posy == 0) { - this._posy = ev.screenY; + this._posy = ev.clientY; return true; } - const diff = this._posy - ev.screenY; + const diff = this._posy - ev.clientY; if (diff > 0) { this.resizeUp(diff); } else if (diff < 0) { this.resizeDown(diff * -1); } - this._posy = ev.screenY; + this._posy = ev.clientY; return true; } diff --git a/_wui/index.html b/_wui/index.html index 7b65ec7..8bf7dc1 100644 --- a/_wui/index.html +++ b/_wui/index.html @@ -15,15 +15,25 @@ margin: 0px 8px; } + .awwan { + height: calc(100vh - 4em); + display: flex; + flex-direction: row; + } + .awwan_nav_left { + display: flex; + flex-direction: column; font-family: monospace; - position: fixed; - height: calc(100% - 54px); width: 300px; } + .awwan_vfs_form { + height: 6em; + } + .wui_vfs_list { - height: calc(100% - 7em); + height: calc(100vh - 15em); overflow: auto; } @@ -33,18 +43,11 @@ height: 1.6em; } - #com_vfs { - height: calc(100% - 4em); - margin-top: 1em; - } - .awwan_content { - height: calc(100% - 7em); - left: 310px; - margin: 0 10px; - padding: 0 10px; - position: fixed; - width: calc(100% - 356px); + height: calc(100vh - 4em); + flex: 1; + display: flex; + flex-direction: column; } #vfs_path { @@ -52,8 +55,7 @@ } #com_editor { - width: calc(100% - 2px); - height: 50%; + height: 50vh; border: 1px solid silver; resize: vertical; } @@ -76,19 +78,27 @@ width: 50px; } - #com_resize { + #com_resize_vfs, + #com_resize_editor { background-color: gainsboro; border: 1px; - cursor: row-resize; font-size: 8px; text-align: center; - width: 100%; + } + + #com_resize_vfs { + cursor: col-resize; + margin: 0 2px; + } + + #com_resize_editor { + cursor: row-resize; } .output { - position: relative; - bottom: 0px; - height: 40%; + display: flex; + flex-direction: column; + flex: 1; } #output { diff --git a/_wui/main.js b/_wui/main.js index 2489c40..d890817 100644 --- a/_wui/main.js +++ b/_wui/main.js @@ -451,6 +451,7 @@ var awwan = (() => { // _wui/awwan.ts var CLASS_EDITOR_ACTION = "editor_action"; + var ID_AWWAN_NAV_LEFT = "awwan_nav_left"; var ID_BTN_DECRYPT = "com_btn_decrypt"; var ID_BTN_ENCRYPT = "com_btn_encrypt"; var ID_BTN_EXEC_LOCAL = "com_btn_local"; @@ -459,7 +460,9 @@ var awwan = (() => { var ID_BTN_NEW_FILE = "com_btn_new_file"; var ID_BTN_REMOVE = "com_btn_remove"; var ID_BTN_SAVE = "com_btn_save"; - var ID_COM_RESIZE = "com_resize"; + var ID_COM_EDITOR_OUT = "com_editor_output"; + var ID_COM_RESIZE_EDITOR = "com_resize_editor"; + var ID_COM_RESIZE_VFS = "com_resize_vfs"; var ID_EDITOR = "com_editor"; var ID_INP_LINE_RANGE = "com_inp_line_range"; var ID_VFS_INPUT = "com_vfs_input"; @@ -472,16 +475,19 @@ var awwan = (() => { const el = document.createElement("div"); el.classList.add("awwan"); el.innerHTML = ` - <div class="awwan_nav_left"> - <div class="${ID_VFS_INPUT}"> - <input id="${ID_VFS_INPUT}" placeholder="Input text to filter (allow regexp)" /> + <div id="${ID_AWWAN_NAV_LEFT}" class="awwan_nav_left"> + <div class="awwan_vfs_form"> + <div class="${ID_VFS_INPUT}"> + <input id="${ID_VFS_INPUT}" placeholder="Input text to filter (allow regexp)" /> + </div> + <button id="${ID_BTN_NEW_DIR}">New dir.</button> + <button id="${ID_BTN_NEW_FILE}">New file</button> + <button id="${ID_BTN_REMOVE}">Remove</button> </div> - <button id="${ID_BTN_NEW_DIR}">New dir.</button> - <button id="${ID_BTN_NEW_FILE}">New file</button> - <button id="${ID_BTN_REMOVE}">Remove</button> <div id="${ID_VFS}"></div> </div> - <div class="awwan_content"> + <div id="${ID_COM_RESIZE_VFS}">⚌</div> + <div id="${ID_COM_EDITOR_OUT}" class="awwan_content"> <div class="boxheader"> <span class="tag">File</span> <span id="${ID_VFS_PATH}">-</span> @@ -490,7 +496,7 @@ var awwan = (() => { <button id="${ID_BTN_DECRYPT}" disabled="true">Decrypt</button> </div> <div id="${ID_EDITOR}"></div> - <div id="${ID_COM_RESIZE}">⚌</div> + <div id="${ID_COM_RESIZE_EDITOR}">⚌</div> <div id="${ID_OUTPUT_WRAPPER}" class="output"> <div> <div class="${CLASS_EDITOR_ACTION}"> @@ -524,8 +530,30 @@ var awwan = (() => { line_range: "" }; this.orgContent = ""; + this._posx = 0; this._posy = 0; - let el = document.getElementById(ID_BTN_EXEC_LOCAL); + let el; + el = document.getElementById(ID_AWWAN_NAV_LEFT); + if (el) { + this.comNavLeft = el; + } + el = document.getElementById(ID_COM_EDITOR_OUT); + if (el) { + this.comEditorOutput = el; + } + el = document.getElementById(ID_COM_RESIZE_VFS); + if (el) { + const doResizeVfs = (ev) => this.doResizeVfs(ev); + el.addEventListener("mousedown", () => { + this._posx = 0; + document.addEventListener("mousemove", doResizeVfs); + }); + document.addEventListener("mouseup", () => { + document.removeEventListener("mousemove", doResizeVfs); + this._posx = 0; + }); + } + el = document.getElementById(ID_BTN_EXEC_LOCAL); if (el) { this.comBtnLocal = el; this.comBtnLocal.onclick = () => { @@ -635,10 +663,10 @@ var awwan = (() => { const url = new URL(hashchange.newURL); this.onHashChange(url.hash); }; - const elResize = document.getElementById(ID_COM_RESIZE); - if (elResize) { - const onMouseMove = (ev) => this.doResize(ev); - elResize.addEventListener("mousedown", () => { + const elResizeEditor = document.getElementById(ID_COM_RESIZE_EDITOR); + if (elResizeEditor) { + const onMouseMove = (ev) => this.doResizeEditor(ev); + elResizeEditor.addEventListener("mousedown", () => { this._posy = 0; document.addEventListener("mousemove", onMouseMove); }); @@ -966,18 +994,47 @@ var awwan = (() => { onVfsInputFilter(val) { this.vfs.filter(val); } - doResize(ev) { + doResizeVfs(ev) { + ev.preventDefault(); + if (this._posx == 0) { + this._posx = ev.clientX; + return false; + } + const diff = this._posx - ev.clientX; + if (diff > 0) { + this.resizeVfsLeft(diff); + } else { + this.resizeVfsRight(diff * -1); + } + this._posx = ev.clientX; + return false; + } + resizeVfsLeft(diff) { + if (this.comNavLeft.clientWidth <= 300) { + return; + } + const width = this.comNavLeft.clientWidth - diff; + this.comNavLeft.style.width = `${width}px`; + } + resizeVfsRight(diff) { + if (this.comEditorOutput.clientWidth <= 600) { + return; + } + const width = this.comNavLeft.clientWidth + diff; + this.comNavLeft.style.width = `${width}px`; + } + doResizeEditor(ev) { if (this._posy == 0) { - this._posy = ev.screenY; + this._posy = ev.clientY; return true; } - const diff = this._posy - ev.screenY; + const diff = this._posy - ev.clientY; if (diff > 0) { this.resizeUp(diff); } else if (diff < 0) { this.resizeDown(diff * -1); } - this._posy = ev.screenY; + this._posy = ev.clientY; return true; } resizeUp(diff) { |
