aboutsummaryrefslogtreecommitdiff
path: root/_wui
diff options
context:
space:
mode:
authorShulhan <ms@kilabit.info>2023-11-17 23:53:22 +0700
committerShulhan <ms@kilabit.info>2023-11-17 23:53:22 +0700
commitba625cecb647ef5fec013aff10a96395f1122270 (patch)
tree0d3acc17c5d5e9e9eaec6a0f7cac4bdbdc4e9fe1 /_wui
parent49f18f5fde5350545c6399823edd31ad8826fb90 (diff)
downloadawwan-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.ts108
-rw-r--r--_wui/index.html54
-rw-r--r--_wui/main.js93
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}">&#9868;</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}">&#9868;</div>
+ <div id="${ID_COM_RESIZE_EDITOR}">&#9868;</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}">&#9868;</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}">&#9868;</div>
+ <div id="${ID_COM_RESIZE_EDITOR}">&#9868;</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) {