X-Git-Url: http://git.scottworley.com/vopamoi/blobdiff_plain/58b569ce38e1d658d0cdfb31d53f2cad2d00e5bd..1804fd5af88aa31a9fc2847492480609dc592c77:/vopamoi.ts?ds=inline diff --git a/vopamoi.ts b/vopamoi.ts index 931505b..bdc8b0d 100644 --- a/vopamoi.ts +++ b/vopamoi.ts @@ -67,7 +67,7 @@ const Model = { return tag; } } - task.appendChild(tag); + task.insertBefore(tag, task.getElementsByClassName("desc")[0]!); return tag; }, @@ -76,7 +76,7 @@ const Model = { if (!target) return null; if (target.hasAttribute("data-description")) { // Oh no: An edit has arrived from a replica while a local edit is in progress. - const input = target.firstChild as HTMLInputElement; + const input = target.getElementsByTagName("input")[0]!; if ( input.value === target.getAttribute("data-description") && input.selectionStart === input.value.length && @@ -120,6 +120,17 @@ const Model = { } }, + insertInPriorityOrder: function (task: Element, dest: Element) { + const priority = this.getPriority(task); + for (const t of dest.children) { + if (t !== task && this.getPriority(t) < priority) { + dest.insertBefore(task, t); + return; + } + } + dest.appendChild(task); + }, + removeTag: function (createTimestamp: string, tagName: string) { const task = this.getTask(createTimestamp); if (!task) return null; @@ -133,13 +144,7 @@ const Model = { const target = this.getTask(createTimestamp); if (!target) return null; target.setAttribute("data-priority", `${priority}`); - for (const task of document.getElementsByClassName("task")) { - if (task !== target && this.getPriority(task) < priority) { - task.parentElement!.insertBefore(target, task); - return target; - } - } - document.getElementById("tasks")!.appendChild(target); + this.insertInPriorityOrder(target, target.parentElement!); return target; }, @@ -276,6 +281,7 @@ function BrowserUI() { todo: "White", waiting: "MediumOrchid", }; + var currentTagView: string | null = null; var currentViewState = "todo"; var taskFocusedBeforeJumpingToInput: HTMLElement | null = null; var lastTagNameEntered = ""; @@ -291,15 +297,17 @@ function BrowserUI() { this.firstVisibleTask()?.focus(); } input.value = ""; + if (currentTagView) { + ui.addTag(task.getAttribute("data-created")!, currentTagView); + } if (event.getModifierState("Control")) { this.makeBottomPriority(task); } }, beginEdit: function (event: Event) { - var task = document.activeElement; + const task = this.currentTask(); if (!task) return; - if (task.classList.contains("tag")) task = task.parentElement!; const input = document.createElement("input"); const desc = task.getElementsByClassName("desc")[0]; const oldDescription = desc.textContent!; @@ -313,7 +321,7 @@ function BrowserUI() { }, beginTagEdit: function (event: Event) { - const task = document.activeElement; + const task = this.currentTask(); if (!task) return; const input = document.createElement("input"); input.classList.add("tag"); @@ -366,19 +374,28 @@ function BrowserUI() { return target; }, + currentTask: function (): HTMLElement | null { + var target = document.activeElement; + if (!target) return null; + if (target.classList.contains("tag")) target = target.parentElement!; + return target as HTMLElement; + }, + firstVisibleTask: function () { for (const task of document.getElementsByClassName("task")) { const state = task.getAttribute("data-state"); - if (task instanceof HTMLElement && (state === currentViewState || (currentViewState === "all" && state !== "deleted"))) { + if ( + task instanceof HTMLElement && + (state === currentViewState || (currentViewState === "all" && state !== "deleted")) && + !task.classList.contains("hide") + ) { return task; } } }, focusTaskNameInput: function (event: Event) { - if (document.activeElement instanceof HTMLElement) { - taskFocusedBeforeJumpingToInput = document.activeElement; - } + taskFocusedBeforeJumpingToInput = this.currentTask(); document.getElementById("taskName")!.focus(); window.scroll(0, 0); event.preventDefault(); @@ -392,7 +409,10 @@ function BrowserUI() { cursor = increment > 0 ? cursor.nextElementSibling : cursor.previousElementSibling; if (!cursor || !(cursor instanceof HTMLElement)) break; const state = cursor.getAttribute("data-state")!; - if (state === currentViewState || (currentViewState === "all" && state !== "deleted")) { + if ( + (state === currentViewState || (currentViewState === "all" && state !== "deleted")) && + !cursor.classList.contains("hide") + ) { offset -= increment; valid_cursor = cursor; } @@ -409,20 +429,20 @@ function BrowserUI() { }, makeBottomPriority: function (task: Element | null = null) { - if (!task) task = document.activeElement; + if (!task) task = this.currentTask(); if (!task) return; this.setPriority(task, document.getElementById("tasks")!.lastElementChild, null); }, makeTopPriority: function (task: Element | null = null) { - if (!task) task = document.activeElement; + if (!task) task = this.currentTask(); if (!task) return; ui.setPriority(task.getAttribute("data-created")!, clock.now(), Model.getPriority(task)); task instanceof HTMLElement && task.focus(); }, moveCursor: function (offset: number): boolean { - const active = document.activeElement; + const active = this.currentTask(); if (!active) return false; const dest = this.visibleTaskAtOffset(active, offset); if (dest !== active && dest instanceof HTMLElement) { @@ -433,7 +453,7 @@ function BrowserUI() { }, moveTask: function (offset: number) { - const active = document.activeElement; + const active = this.currentTask(); if (!active) return; const dest = this.visibleTaskAtOffset(active, offset); if (dest === active) return; // Already extremal @@ -452,8 +472,16 @@ function BrowserUI() { ui.removeTag(target.parentElement!.getAttribute("data-created")!, target.textContent!); }, + resetTagView: function () { + currentTagView = null; + for (const task of document.getElementsByClassName("task")) { + task.classList.remove("hide"); + } + }, + resetView: function () { this.setView("todo"); + this.resetTagView(); }, returnFocusAfterInput: function (): boolean { @@ -479,7 +507,7 @@ function BrowserUI() { }, setState: function (newState: string) { - const task = document.activeElement; + const task = this.currentTask(); if (!task) return; const oldState = task.getAttribute("data-state")!; if (newState === oldState) return; @@ -490,6 +518,20 @@ function BrowserUI() { return ui.setState(createTimestamp, newState, oldState); }, + setTagView: function () { + const target = this.currentTag(); + if (!target) return; + const tag = target.textContent!; + for (const task of document.getElementsByClassName("task")) { + if (Model.hasTag(task, tag)) { + task.classList.remove("hide"); + } else { + task.classList.add("hide"); + } + } + currentTagView = tag; + }, + setView: function (state: string) { const sheet = (document.getElementById("viewStyle") as HTMLStyleElement).sheet!; if (state === "all") { @@ -501,11 +543,21 @@ function BrowserUI() { sheet.removeRule(2); sheet.removeRule(2); currentViewState = state; - if (document.activeElement?.getAttribute("data-state") !== state) { + if (this.currentTask()?.getAttribute("data-state") !== state) { this.firstVisibleTask()?.focus(); } }, + setUntaggedView: function () { + for (const task of document.getElementsByClassName("task")) { + if (task.getElementsByClassName("tag").length === 0) { + task.classList.remove("hide"); + } else { + task.classList.add("hide"); + } + } + }, + undo: function () { const ret = ui.undo(); if (ret && ret instanceof HTMLElement) ret.focus(); @@ -582,8 +634,12 @@ function handleKey(event: any) { if (event.key == "a") return browserUI.setView("all"); if (event.key == "c") return browserUI.setView("cancelled"); if (event.key == "d") return browserUI.setView("done"); + if (event.key == "i") return browserUI.setUntaggedView(); if (event.key == "q") return browserUI.setView("todo"); if (event.key == "s") return (inputState = InputState.VS); + if (event.key == "T") return browserUI.resetTagView(); + if (event.key == "t") return browserUI.setTagView(); + if (event.key == "u") return browserUI.setUntaggedView(); if (event.key == "v") return browserUI.resetView(); if (event.key == "w") return browserUI.setView("waiting"); if (event.key == "x") return browserUI.setView("deleted");