From 69f294cec3f45a8ea55afd920a0685be737c933e Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Sun, 8 Oct 2023 17:42:44 +0300 Subject: [PATCH] checkboxes now clickable + playing with markdown... Signed-off-by: Alex A. Naanou --- experiments/outline-editor/editor.css | 18 +++++++++ experiments/outline-editor/editor.js | 53 ++++++++++++++++++++++++--- experiments/outline-editor/index.html | 8 ++-- 3 files changed, 69 insertions(+), 10 deletions(-) diff --git a/experiments/outline-editor/editor.css b/experiments/outline-editor/editor.css index cfff949..368b941 100755 --- a/experiments/outline-editor/editor.css +++ b/experiments/outline-editor/editor.css @@ -8,6 +8,8 @@ /*text-size-adjust: none;*/ text-size-adjust: 150%; + + /*scroll-behavior: smooth;*/ } .editor { @@ -45,6 +47,7 @@ font-family: sans-serif; font-size: var(--font-size); + white-space: pre-wrap; outline: none; border: none; @@ -110,6 +113,7 @@ } +/*-------------------------------------------------------------------*/ /* Styles */ .editor .outline .heading-1>span, @@ -152,6 +156,7 @@ } /* XXX EXPERIMENTAL -- not sure about this... */ +.editor .outline .list-item:before, .editor .outline .list>[tabindex]:before { display: inline-block; position: absolute; @@ -163,6 +168,19 @@ background: silver; } +.editor .outline .XXX>span { + background: yellow; +} +.editor .outline .comment>span { + color: silver; +} +.editor .outline [tabindex]>span>input[type=checkbox] { + --width: 3em; + + height: 1em; + width: var(--width); + margin-left: calc(-1 * var(--width)); +} diff --git a/experiments/outline-editor/editor.js b/experiments/outline-editor/editor.js index 1d790ab..47c1d75 100755 --- a/experiments/outline-editor/editor.js +++ b/experiments/outline-editor/editor.js @@ -331,28 +331,44 @@ var Outline = { elem.style = style return text } } elem.text = code - // attributes... + // hidden attributes... // XXX make this generic... - .replace(/\n\s*collapsed::\s*(.*)\s*$/, + // XXX should these be hidden from code too??? + // collapsed... + .replace(/(\n|^)\s*collapsed::\s*(.*)\s*(\n|$)/, + function(_, value){ + elem.collapsed = value.trim() == 'true' + return '' }) + // id... + .replace(/(\n|^)\s*id::\s*(.*)\s*(\n|$)/, function(_, value){ elem.collapsed = value.trim() == 'true' return '' }) // markdown... + // ToDo... .replace(/^TODO\s*(.*)$/, ' $1') .replace(/^DONE\s*(.*)$/, ' $1') + // style: headings... .replace(/^######\s*(.*)$/, style('heading-6')) .replace(/^#####\s*(.*)$/, style('heading-5')) .replace(/^####\s*(.*)$/, style('heading-4')) .replace(/^###\s*(.*)$/, style('heading-3')) .replace(/^##\s*(.*)$/, style('heading-2')) .replace(/^#\s*(.*)$/, style('heading-1')) - //.replace(/^[-\*]\s*(.*)$/, style('list')) + // style: list... + .replace(/^[-\*]\s+(.*)$/, style('list-item')) .replace(/^\s*(.*):\s*$/, style('list')) + // style: misc... + .replace(/^((\/\/|;)\s+.*)$/, style('comment')) + .replace(/^XXX\s+(.*)$/, style('XXX')) + .replace(/^(.*)\s*XXX$/, style('XXX')) + // basic styling... + // XXX these are quite naive... .replace(/\*(.*)\*/g, '$1') .replace(/~([^~]*)~/g, '$1') .replace(/_([^_]*)_/g, '$1') + // elements... .replace(/(\n|^)---*\h*(\n|$)/, '$1
') - .replace(/\n/g, '
\n') return elem }, // serialization... @@ -419,7 +435,10 @@ var Outline = { collapsed = value == 'true' return '' }) parent.push({ - text: block, + text: block + // normalize indent... + .split(new RegExp('\n'+sep+' ', 'g')) + .join('\n'), collapsed, children: [], }) @@ -570,7 +589,7 @@ var Outline = { Escape: function(evt){ this.outline.querySelector('textarea:focus')?.parentElement?.focus() }, Delete: function(evt){ - if(evt.target.isContentEditable){ + if(this.get('edited')){ return } this.remove() }, @@ -597,6 +616,18 @@ var Outline = { // update stuff already in DOM... for(var elem of [...outline.querySelectorAll('textarea')]){ elem.autoUpdateSize() } + // click... + outline.addEventListener('click', + function(evt){ + var elem = evt.target + // toggle checkbox... + if(elem.nodeName == 'INPUT' && elem.type == 'checkbox'){ + var node = elem.parentElement.parentElement + var text = node.querySelector('textarea') + text.value = + elem.checked ? + text.value.replace(/^\s*TODO(\s*)/, 'DONE$1') + : text.value.replace(/^\s*DONE(\s*)/, 'TODO$1') } }) // heboard handling... outline.addEventListener('keydown', function(evt){ @@ -606,6 +637,16 @@ var Outline = { outline.addEventListener('focusin', function(evt){ var node = evt.target + // scroll... + // XXX a bit odd still and not smooth... + ;((node.nodeName == 'SPAN' + || node.nodeName == 'TEXTAREA') ? + node + : node.querySelector('textarea+span')) + ?.scrollIntoView({ + block: 'nearest', + behavior: 'smooth', + }) // handle focus... for(var e of [...that.dom.querySelectorAll('.focused')]){ e.classList.remove('focused') } diff --git a/experiments/outline-editor/index.html b/experiments/outline-editor/index.html index b7373a5..0a6d57b 100755 --- a/experiments/outline-editor/index.html +++ b/experiments/outline-editor/index.html @@ -28,9 +28,6 @@ var setup = function(){
- # Outline editor prototype - ## TODO - - BUG: delete in edit mode deletes node - - BUG: multiline blocks do not indent correctly in editor - - make checkboxes clickable - editor: enter on an expanded parent node should create child (currently next sibling) - editor: bksapce/del at start/end of a block should join it with prev/next - editor: pressing enter in text edit mode should split text into two blocks @@ -58,7 +55,7 @@ var setup = function(){ - ~add optional text styling to nodes~ - - ## TEST - - Formatting + - Formatting: - Styles - # Heading 1 - ## Heading 2 @@ -71,6 +68,9 @@ var setup = function(){ - a - b - c + - // C-style comment + - ; ASM-style comment + - XXX Highlight - line - --- - basic inline *bold*, _italic_ and ~striked~