Update node content when toggling checkboxes
This commit is contained in:
parent
4e495a5c94
commit
df399f5d37
2 changed files with 56 additions and 18 deletions
|
|
@ -92,7 +92,8 @@ function escapeHtmlEntities(html, encode) {// {{{
|
||||||
|
|
||||||
export class MarkedPosition {
|
export class MarkedPosition {
|
||||||
constructor() {// {{{
|
constructor() {// {{{
|
||||||
window.setpos = (event) => this.setpos(event)
|
window.marked_setpos = (event) => this.setpos(event)
|
||||||
|
window.marked_changecheckbox = (event) => this.changecheckbox(event)
|
||||||
this.render()
|
this.render()
|
||||||
}// }}}
|
}// }}}
|
||||||
setpos(event) {// {{{
|
setpos(event) {// {{{
|
||||||
|
|
@ -106,6 +107,18 @@ export class MarkedPosition {
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}// }}}
|
}// }}}
|
||||||
|
changecheckbox(event) {// {{{
|
||||||
|
event.stopPropagation()
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
|
_mbus.dispatch('MARKDOWN_CHANGE_CHECKBOX', {
|
||||||
|
checkbox: event.target,
|
||||||
|
position: {
|
||||||
|
start: event.target.closest('[data-offset-start]').dataset.offsetStart,
|
||||||
|
end: event.target.closest('[data-offset-start]').dataset.offsetEnd,
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}// }}}
|
||||||
render() {// {{{
|
render() {// {{{
|
||||||
const markedObject = this
|
const markedObject = this
|
||||||
this.marked = new Marked()
|
this.marked = new Marked()
|
||||||
|
|
@ -116,7 +129,7 @@ export class MarkedPosition {
|
||||||
const content = this.parser.parseInline(token.tokens)
|
const content = this.parser.parseInline(token.tokens)
|
||||||
return `
|
return `
|
||||||
<div class="heading-container" data-heading="${token.depth}">
|
<div class="heading-container" data-heading="${token.depth}">
|
||||||
<h${token.depth} ondblclick="setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">${content}</h${token.depth}>\n
|
<h${token.depth} ondblclick="marked_setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">${content}</h${token.depth}>\n
|
||||||
<div class="line"></div>\n
|
<div class="line"></div>\n
|
||||||
</div>
|
</div>
|
||||||
`
|
`
|
||||||
|
|
@ -124,7 +137,7 @@ export class MarkedPosition {
|
||||||
|
|
||||||
paragraph(token) {
|
paragraph(token) {
|
||||||
const content = this.parser.parseInline(token.tokens)
|
const content = this.parser.parseInline(token.tokens)
|
||||||
return `<p ondblclick="setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">${content}</p>\n`
|
return `<p ondblclick="marked_setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">${content}</p>\n`
|
||||||
},
|
},
|
||||||
|
|
||||||
list(token) {
|
list(token) {
|
||||||
|
|
@ -143,7 +156,7 @@ export class MarkedPosition {
|
||||||
},
|
},
|
||||||
|
|
||||||
listitem(token) {
|
listitem(token) {
|
||||||
return `<li ondblclick="setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">${this.parser.parse(token.tokens)}</li>\n`
|
return `<li ondblclick="marked_setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">${this.parser.parse(token.tokens)}</li>\n`
|
||||||
},
|
},
|
||||||
|
|
||||||
code(token) {
|
code(token) {
|
||||||
|
|
@ -152,12 +165,12 @@ export class MarkedPosition {
|
||||||
const code = token.text.replace(other.endingNewline, '') + '\n'
|
const code = token.text.replace(other.endingNewline, '') + '\n'
|
||||||
|
|
||||||
if (!langString) {
|
if (!langString) {
|
||||||
return `<pre ondblclick="setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}"><code>`
|
return `<pre ondblclick="marked_setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}"><code>`
|
||||||
+ (token.escaped ? code : escapeHtmlEntities(code, true))
|
+ (token.escaped ? code : escapeHtmlEntities(code, true))
|
||||||
+ '</code></pre>\n'
|
+ '</code></pre>\n'
|
||||||
}
|
}
|
||||||
|
|
||||||
return `<pre ondblclick="setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}"><code class="language-`
|
return `<pre ondblclick="marked_setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}"><code class="language-`
|
||||||
+ escapeHtmlEntities(langString)
|
+ escapeHtmlEntities(langString)
|
||||||
+ '">'
|
+ '">'
|
||||||
+ (token.escaped ? code : escapeHtmlEntities(code, true))
|
+ (token.escaped ? code : escapeHtmlEntities(code, true))
|
||||||
|
|
@ -166,7 +179,7 @@ export class MarkedPosition {
|
||||||
|
|
||||||
blockquote(token) {
|
blockquote(token) {
|
||||||
const body = this.parser.parse(token.tokens)
|
const body = this.parser.parse(token.tokens)
|
||||||
return `<blockquote ondblclick="setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">\n${body}</blockquote>\n`
|
return `<blockquote ondblclick="marked_setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">\n${body}</blockquote>\n`
|
||||||
},
|
},
|
||||||
|
|
||||||
html(token) {
|
html(token) {
|
||||||
|
|
@ -178,13 +191,13 @@ export class MarkedPosition {
|
||||||
},
|
},
|
||||||
|
|
||||||
hr(token) {
|
hr(token) {
|
||||||
return `<hr ondblclick="setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">\n`
|
return `<hr ondblclick="marked_setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">\n`
|
||||||
},
|
},
|
||||||
|
|
||||||
checkbox(token) {
|
checkbox(token) {
|
||||||
return `<input ondblclick="setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}"`
|
return `<input ondblclick="marked_setpos(event)" onchange="marked_changecheckbox(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}"`
|
||||||
+ (token.checked ? 'checked="" ' : '')
|
+ (token.checked ? 'checked="" ' : '')
|
||||||
+ 'disabled="" type="checkbox"> '
|
+ 'type="checkbox"> '
|
||||||
},
|
},
|
||||||
|
|
||||||
table(token) {
|
table(token) {
|
||||||
|
|
@ -227,7 +240,7 @@ export class MarkedPosition {
|
||||||
if (token.tokens.length > 0) {
|
if (token.tokens.length > 0) {
|
||||||
const start = token.tokens[0].position.start.offset
|
const start = token.tokens[0].position.start.offset
|
||||||
const end = token.tokens[0].position.end.offset
|
const end = token.tokens[0].position.end.offset
|
||||||
ofs = `ondblclick="setpos(event)" data-offset-start="${start}" data-offset-end="${end}"`
|
ofs = `ondblclick="marked_setpos(event)" data-offset-start="${start}" data-offset-end="${end}"`
|
||||||
}
|
}
|
||||||
|
|
||||||
const content = this.parser.parseInline(token.tokens);
|
const content = this.parser.parseInline(token.tokens);
|
||||||
|
|
@ -239,23 +252,23 @@ export class MarkedPosition {
|
||||||
},
|
},
|
||||||
|
|
||||||
strong(token) {
|
strong(token) {
|
||||||
return `<strong ondblclick="setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">${this.parser.parseInline(token.tokens)}</strong>`
|
return `<strong ondblclick="marked_setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">${this.parser.parseInline(token.tokens)}</strong>`
|
||||||
},
|
},
|
||||||
|
|
||||||
em(token) {
|
em(token) {
|
||||||
return `<em ondblclick="setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">${this.parser.parseInline(token.tokens)}</em>`
|
return `<em ondblclick="marked_setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">${this.parser.parseInline(token.tokens)}</em>`
|
||||||
},
|
},
|
||||||
|
|
||||||
codespan(token) {
|
codespan(token) {
|
||||||
return `<code ondblclick="setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">${escapeHtmlEntities(token.text, true)}</code>`
|
return `<code ondblclick="marked_setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">${escapeHtmlEntities(token.text, true)}</code>`
|
||||||
},
|
},
|
||||||
|
|
||||||
br(token) {
|
br(token) {
|
||||||
return `<br ondblclick="setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">`
|
return `<br ondblclick="marked_setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">`
|
||||||
},
|
},
|
||||||
|
|
||||||
del(token) {
|
del(token) {
|
||||||
return `<del ondblclick="setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">${this.parser.parseInline(token.tokens)}</del>`
|
return `<del ondblclick="marked_setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}">${this.parser.parseInline(token.tokens)}</del>`
|
||||||
},
|
},
|
||||||
|
|
||||||
link(token) {
|
link(token) {
|
||||||
|
|
@ -265,7 +278,7 @@ export class MarkedPosition {
|
||||||
return text
|
return text
|
||||||
}
|
}
|
||||||
token.href = cleanHref
|
token.href = cleanHref
|
||||||
let out = '<a ondblclick="setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}" href="' + token.href + '"'
|
let out = '<a ondblclick="marked_setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}" href="' + token.href + '"'
|
||||||
if (token.title) {
|
if (token.title) {
|
||||||
out += ' title="' + (escapeHtmlEntities(token.title)) + '"'
|
out += ' title="' + (escapeHtmlEntities(token.title)) + '"'
|
||||||
}
|
}
|
||||||
|
|
@ -282,7 +295,7 @@ export class MarkedPosition {
|
||||||
return escapeHtmlEntities(token.text)
|
return escapeHtmlEntities(token.text)
|
||||||
}
|
}
|
||||||
token.href = cleanHref
|
token.href = cleanHref
|
||||||
let out = `<n2-file ondblclick="setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}" src="${token.href}" alt="${escapeHtmlEntities(token.text)}"`
|
let out = `<n2-file ondblclick="marked_setpos(event)" data-offset-start="${token.position.start.offset}" data-offset-end="${token.position.end.offset}" src="${token.href}" alt="${escapeHtmlEntities(token.text)}"`
|
||||||
if (token.title) {
|
if (token.title) {
|
||||||
out += ` title="${escapeHtmlEntities(token.title)}"`
|
out += ` title="${escapeHtmlEntities(token.title)}"`
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -64,6 +64,7 @@ export class N2PageNodeUI extends CustomHTMLElement {
|
||||||
|
|
||||||
_mbus.subscribe('MARKDOWN_TOGGLE', () => this.showMarkdown(!this.showMarkdown()))
|
_mbus.subscribe('MARKDOWN_TOGGLE', () => this.showMarkdown(!this.showMarkdown()))
|
||||||
_mbus.subscribe('MARKDOWN_EDIT', ({ detail }) => this.editMarkdown(detail.data))
|
_mbus.subscribe('MARKDOWN_EDIT', ({ detail }) => this.editMarkdown(detail.data))
|
||||||
|
_mbus.subscribe('MARKDOWN_CHANGE_CHECKBOX', ({ detail }) => this.checkboxUpdated(detail.data))
|
||||||
|
|
||||||
this.elName.addEventListener('click', async () => this.renameNode())
|
this.elName.addEventListener('click', async () => this.renameNode())
|
||||||
this.elNodeContent.addEventListener('input', event => this.contentChanged(event))
|
this.elNodeContent.addEventListener('input', event => this.contentChanged(event))
|
||||||
|
|
@ -288,6 +289,30 @@ export class N2PageNodeUI extends CustomHTMLElement {
|
||||||
|
|
||||||
return lines
|
return lines
|
||||||
}// }}}
|
}// }}}
|
||||||
|
// "marked" sends a messagebus event when checking/unchecking a checkbox.
|
||||||
|
// Updates node and content textarea.
|
||||||
|
checkboxUpdated(eventData) {// {{{
|
||||||
|
const checkbox = eventData.checkbox
|
||||||
|
const pos = eventData.position
|
||||||
|
const content = this.node.content()
|
||||||
|
|
||||||
|
// Basic validation to verify that Marked does what is known and expected at this writing.
|
||||||
|
const mdCheckboxStr = content.slice(pos.start, pos.end)
|
||||||
|
if (!mdCheckboxStr.match(/^\[[ xX]\] $/)) {
|
||||||
|
alert(`Checkbox string didn't pass validation: '${mdCheckboxStr}'`)
|
||||||
|
console.error(`Checkbox string didn't pass validation: '${mdCheckboxStr}'`)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Node is modified with the new value. User has to save manually, otherwise other changes could be saved
|
||||||
|
// when a save wasn't expected.
|
||||||
|
const newValue =`[${checkbox.checked ? 'x' : ' '}] `
|
||||||
|
const modifiedContent = this.node.content().slice(0, pos.start) + newValue + this.node.content().slice(pos.end)
|
||||||
|
this.node.setContent(modifiedContent)
|
||||||
|
|
||||||
|
// Also update the textarea since the node model doesn't know about it.
|
||||||
|
this.elNodeContent.setRangeText(newValue, pos.start, pos.end, 'select')
|
||||||
|
|
||||||
|
}// }}}
|
||||||
}
|
}
|
||||||
customElements.define('n2-nodeui', N2PageNodeUI)
|
customElements.define('n2-nodeui', N2PageNodeUI)
|
||||||
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue