checkboxes now clickable + playing with markdown...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2023-10-08 17:42:44 +03:00
parent 7f2b027a7b
commit 69f294cec3
3 changed files with 69 additions and 10 deletions

View File

@ -8,6 +8,8 @@
/*text-size-adjust: none;*/ /*text-size-adjust: none;*/
text-size-adjust: 150%; text-size-adjust: 150%;
/*scroll-behavior: smooth;*/
} }
.editor { .editor {
@ -45,6 +47,7 @@
font-family: sans-serif; font-family: sans-serif;
font-size: var(--font-size); font-size: var(--font-size);
white-space: pre-wrap;
outline: none; outline: none;
border: none; border: none;
@ -110,6 +113,7 @@
} }
/*-------------------------------------------------------------------*/
/* Styles */ /* Styles */
.editor .outline .heading-1>span, .editor .outline .heading-1>span,
@ -152,6 +156,7 @@
} }
/* XXX EXPERIMENTAL -- not sure about this... */ /* XXX EXPERIMENTAL -- not sure about this... */
.editor .outline .list-item:before,
.editor .outline .list>[tabindex]:before { .editor .outline .list>[tabindex]:before {
display: inline-block; display: inline-block;
position: absolute; position: absolute;
@ -163,6 +168,19 @@
background: silver; 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));
}

View File

@ -331,28 +331,44 @@ var Outline = {
elem.style = style elem.style = style
return text } } return text } }
elem.text = code elem.text = code
// attributes... // hidden attributes...
// XXX make this generic... // 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){ function(_, value){
elem.collapsed = value.trim() == 'true' elem.collapsed = value.trim() == 'true'
return '' }) return '' })
// markdown... // markdown...
// ToDo...
.replace(/^TODO\s*(.*)$/, '<input type="checkbox"> $1') .replace(/^TODO\s*(.*)$/, '<input type="checkbox"> $1')
.replace(/^DONE\s*(.*)$/, '<input type="checkbox" checked> $1') .replace(/^DONE\s*(.*)$/, '<input type="checkbox" checked> $1')
// style: headings...
.replace(/^######\s*(.*)$/, style('heading-6')) .replace(/^######\s*(.*)$/, style('heading-6'))
.replace(/^#####\s*(.*)$/, style('heading-5')) .replace(/^#####\s*(.*)$/, style('heading-5'))
.replace(/^####\s*(.*)$/, style('heading-4')) .replace(/^####\s*(.*)$/, style('heading-4'))
.replace(/^###\s*(.*)$/, style('heading-3')) .replace(/^###\s*(.*)$/, style('heading-3'))
.replace(/^##\s*(.*)$/, style('heading-2')) .replace(/^##\s*(.*)$/, style('heading-2'))
.replace(/^#\s*(.*)$/, style('heading-1')) .replace(/^#\s*(.*)$/, style('heading-1'))
//.replace(/^[-\*]\s*(.*)$/, style('list')) // style: list...
.replace(/^[-\*]\s+(.*)$/, style('list-item'))
.replace(/^\s*(.*):\s*$/, style('list')) .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, '<b>$1</b>') .replace(/\*(.*)\*/g, '<b>$1</b>')
.replace(/~([^~]*)~/g, '<s>$1</s>') .replace(/~([^~]*)~/g, '<s>$1</s>')
.replace(/_([^_]*)_/g, '<i>$1</i>') .replace(/_([^_]*)_/g, '<i>$1</i>')
// elements...
.replace(/(\n|^)---*\h*(\n|$)/, '$1<hr>') .replace(/(\n|^)---*\h*(\n|$)/, '$1<hr>')
.replace(/\n/g, '<br>\n')
return elem }, return elem },
// serialization... // serialization...
@ -419,7 +435,10 @@ var Outline = {
collapsed = value == 'true' collapsed = value == 'true'
return '' }) return '' })
parent.push({ parent.push({
text: block, text: block
// normalize indent...
.split(new RegExp('\n'+sep+' ', 'g'))
.join('\n'),
collapsed, collapsed,
children: [], children: [],
}) })
@ -570,7 +589,7 @@ var Outline = {
Escape: function(evt){ Escape: function(evt){
this.outline.querySelector('textarea:focus')?.parentElement?.focus() }, this.outline.querySelector('textarea:focus')?.parentElement?.focus() },
Delete: function(evt){ Delete: function(evt){
if(evt.target.isContentEditable){ if(this.get('edited')){
return } return }
this.remove() }, this.remove() },
@ -597,6 +616,18 @@ var Outline = {
// update stuff already in DOM... // update stuff already in DOM...
for(var elem of [...outline.querySelectorAll('textarea')]){ for(var elem of [...outline.querySelectorAll('textarea')]){
elem.autoUpdateSize() } 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... // heboard handling...
outline.addEventListener('keydown', outline.addEventListener('keydown',
function(evt){ function(evt){
@ -606,6 +637,16 @@ var Outline = {
outline.addEventListener('focusin', outline.addEventListener('focusin',
function(evt){ function(evt){
var node = evt.target 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... // handle focus...
for(var e of [...that.dom.querySelectorAll('.focused')]){ for(var e of [...that.dom.querySelectorAll('.focused')]){
e.classList.remove('focused') } e.classList.remove('focused') }

View File

@ -28,9 +28,6 @@ var setup = function(){
<div class="code"> <div class="code">
- # Outline editor prototype - # Outline editor prototype
- ## TODO - ## 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: 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: 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 - 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~ - ~add optional text styling to nodes~
- -
- ## TEST - ## TEST
- Formatting - Formatting:
- Styles - Styles
- # Heading 1 - # Heading 1
- ## Heading 2 - ## Heading 2
@ -71,6 +68,9 @@ var setup = function(){
- a - a
- b - b
- c - c
- // C-style comment
- ; ASM-style comment
- XXX Highlight
- line - line
- --- - ---
- basic inline *bold*, _italic_ and ~striked~ - basic inline *bold*, _italic_ and ~striked~