X-Git-Url: http://git.scottworley.com/vopamoi/blobdiff_plain/36fa06f4ee3f58be1677a326c38731553f0f3995..88bd89ef027fe592d38d5e99a3fbeff8109d8c0a:/vopamoi.ts diff --git a/vopamoi.ts b/vopamoi.ts index 3ccc562..57c7686 100644 --- a/vopamoi.ts +++ b/vopamoi.ts @@ -46,7 +46,8 @@ const Model = { task.setAttribute("tabindex", "0"); task.setAttribute("data-created", timestamp); task.setAttribute("data-state", "todo"); - document.getElementById("tasks")!.appendChild(task); + const tasks = document.getElementById("tasks")!; + tasks.insertBefore(task, tasks.firstElementChild); return task; }, @@ -133,7 +134,7 @@ const Model = { if (!target) return null; target.setAttribute("data-priority", `${priority}`); for (const task of document.getElementsByClassName("task")) { - if (task !== target && this.getPriority(task) > priority) { + if (task !== target && this.getPriority(task) < priority) { task.parentElement!.insertBefore(target, task); return target; } @@ -282,13 +283,14 @@ function BrowserUI() { } input.value = ""; if (event.getModifierState("Control")) { - this.makeTopPriority(task); + this.makeBottomPriority(task); } }, beginEdit: function (event: Event) { - const task = document.activeElement; + var task = document.activeElement; 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!; @@ -358,6 +360,7 @@ function BrowserUI() { taskFocusedBeforeJumpingToInput = document.activeElement; } document.getElementById("taskName")!.focus(); + window.scroll(0, 0); event.preventDefault(); }, @@ -378,10 +381,24 @@ function BrowserUI() { return valid_cursor; }, + jumpCursor: function (position: number) { + const first = this.firstVisibleTask(); + if (!first) return; + const dest = this.visibleTaskAtOffset(first, position - 1); + if (dest instanceof HTMLElement) dest.focus(); + }, + + makeBottomPriority: function (task: Element | null = null) { + if (!task) task = document.activeElement; + if (!task) return; + this.setPriority(task, document.getElementById("tasks")!.lastElementChild, null); + }, + makeTopPriority: function (task: Element | null = null) { if (!task) task = document.activeElement; if (!task) return; - this.setPriority(task, null, document.getElementsByClassName("task")[0]); + ui.setPriority(task.getAttribute("data-created")!, clock.now(), Model.getPriority(task)); + task instanceof HTMLElement && task.focus(); }, moveCursor: function (offset: number): boolean { @@ -430,14 +447,14 @@ function BrowserUI() { // Change task's priority to be between other tasks a and b. setPriority: function (task: Element, a: Element | null, b: Element | null) { - const aPriority = a === null ? 0 : Model.getPriority(a); - const bPriority = b === null ? clock.now() : Model.getPriority(b); - console.assert(aPriority < bPriority, aPriority, "<", bPriority); - const span = bPriority - aPriority; - const newPriority = aPriority + 0.1 * span + 0.8 * span * Math.random(); - console.assert(aPriority < newPriority && newPriority < bPriority, aPriority, "<", newPriority, "<", bPriority); + const aPriority = a === null ? clock.now() : Model.getPriority(a); + const bPriority = b === null ? 0 : Model.getPriority(b); + console.assert(aPriority > bPriority, aPriority, ">", bPriority); + const span = aPriority - bPriority; + const newPriority = bPriority + 0.1 * span + 0.8 * span * Math.random(); + console.assert(aPriority > newPriority && newPriority > bPriority, aPriority, ">", newPriority, ">", bPriority); const newPriorityRounded = Math.round(newPriority); - const okToRound = aPriority < newPriorityRounded && newPriorityRounded < bPriority; + const okToRound = aPriority > newPriorityRounded && newPriorityRounded > bPriority; ui.setPriority(task.getAttribute("data-created")!, okToRound ? newPriorityRounded : newPriority, Model.getPriority(task)); task instanceof HTMLElement && task.focus(); }, @@ -482,6 +499,7 @@ function BrowserUI() { } const browserUI = BrowserUI(); +const scrollIncrement = 60; enum InputState { Root, S, @@ -492,6 +510,7 @@ var inputState = InputState.Root; var inputCount: number | null = null; function handleKey(event: any) { + if (["Alt", "Control", "Meta", "Shift"].includes(event.key)) return; if (event.target.tagName === "INPUT") { if (event.target.id === "taskName") { if (event.key == "Enter") return browserUI.addTask(event); @@ -509,24 +528,30 @@ function handleKey(event: any) { return (inputCount = (inputCount ?? 0) * 10 + parseInt(event.key)); } try { - if (event.key == "j") return browserUI.moveCursor(inputCount ?? 1); - if (event.key == "k") return browserUI.moveCursor(-(inputCount ?? 1)); - if (event.key == "J") return browserUI.moveTask(1); - if (event.key == "K") return browserUI.moveTask(-1); - if (event.key == "T") return browserUI.makeTopPriority(); - if (event.key == "n") return browserUI.focusTaskNameInput(event); - if (event.key == "c") return browserUI.setState("cancelled"); - if (event.key == "d") return browserUI.setState("done"); - if (event.key == "q") return browserUI.setState("todo"); - if (event.key == "s") return (inputState = InputState.S); - if (event.key == "w") return browserUI.setState("waiting"); - if (event.key == "X") return browserUI.setState("deleted"); - if (event.key == "x") return browserUI.removeTag(); - if (event.key == "u") return browserUI.undo(); - if (event.key == "r") return browserUI.redo(); - if (event.key == "e") return browserUI.beginEdit(event); - if (event.key == "t") return browserUI.beginTagEdit(event); - if (event.key == "v") return (inputState = InputState.V); + if (event.ctrlKey) { + if (event.key == "e") return window.scrollBy(0, (inputCount ?? 1) * scrollIncrement); + if (event.key == "y") return window.scrollBy(0, (inputCount ?? 1) * -scrollIncrement); + } else { + if (event.key == "j") return browserUI.moveCursor(inputCount ?? 1); + if (event.key == "k") return browserUI.moveCursor(-(inputCount ?? 1)); + if (event.key == "J") return browserUI.moveTask(inputCount ?? 1); + if (event.key == "K") return browserUI.moveTask(-(inputCount ?? 1)); + if (event.key == "G") return browserUI.jumpCursor(inputCount ?? MAX_SAFE_INTEGER); + if (event.key == "T") return browserUI.makeTopPriority(); + if (event.key == "n") return browserUI.focusTaskNameInput(event); + if (event.key == "c") return browserUI.setState("cancelled"); + if (event.key == "d") return browserUI.setState("done"); + if (event.key == "q") return browserUI.setState("todo"); + if (event.key == "s") return (inputState = InputState.S); + if (event.key == "w") return browserUI.setState("waiting"); + if (event.key == "X") return browserUI.setState("deleted"); + if (event.key == "x") return browserUI.removeTag(); + if (event.key == "u") return browserUI.undo(); + if (event.key == "r") return browserUI.redo(); + if (event.key == "e") return browserUI.beginEdit(event); + if (event.key == "t") return browserUI.beginTagEdit(event); + if (event.key == "v") return (inputState = InputState.V); + } } finally { inputCount = null; }