diff --git a/experiments/outline-editor/editor.js b/experiments/outline-editor/editor.js index a6fb293..d62bc0e 100755 --- a/experiments/outline-editor/editor.js +++ b/experiments/outline-editor/editor.js @@ -769,13 +769,18 @@ var Outline = { get header(){ return this.dom.querySelector('.header') }, - get code(){ - return this.dom.querySelector('.code') }, get outline(){ return this.dom.querySelector('.outline') }, get toolbar(){ return this.dom.querySelector('.toolbar') }, + get code(){ + return this.dom.querySelector('.code')?.value }, + set code(value){ + var c = this.dom.querySelector('.code') + if(c){ + c.value = value } }, + path: function(node='focused', mode='index'){ if(['index', 'text', 'node', 'data'].includes(node)){ @@ -1026,14 +1031,15 @@ var Outline = { var parsed = {} if('text' in data){ - var text = node.querySelector('textarea') - var html = node.querySelector('span') + var text = node.querySelector('.code') + var html = node.querySelector('.view') if(this.__code2html__){ // NOTE: we are ignoring the .collapsed attr here parsed = this.__code2html__(data.text, {...data}) html.innerHTML = parsed.text // heading... - node.classList.remove(...this.__styles) + this.__styles != null + && node.classList.remove(...this.__styles) parsed.style && node.classList.add(...parsed.style) delete parsed.style @@ -1201,6 +1207,7 @@ var Outline = { return node }, // crop... + // XXX the header links are not component-compatible... crop: function(node='focused'){ this.dom.classList.add('crop') for(var block of [...this.outline.querySelectorAll('[cropped]')]){ @@ -1212,7 +1219,9 @@ var Outline = { + this.path(...arguments, 'text') .slice(0, -1) .map(function(s, i, {length}){ - return `${s} ` }) + return `${ + plugin.encode(s) + } ` }) .join(' / ') return this }, uncrop: function(count=1){ @@ -1563,20 +1572,20 @@ var Outline = { .clear() .outline .append(...level(data)) - /* XXX do we actually need this??? // update sizes of all the textareas (transparent)... + // NOTE: this is needed to make initial clicking into multi-line + // blocks place the cursor into the clicked location. + // ...this is done by expanding the textarea to the element + // size and enabling it to intercept clicks correctly... setTimeout(function(){ for(var e of [...that.outline.querySelectorAll('textarea')]){ e.updateSize() } }, 0) - //*/ // restore focus... this.focus() return this }, sync: function(){ - var code = this.code - if(code){ - code.value = this.text() } + this.code = this.text() return this }, @@ -2109,7 +2118,7 @@ var Outline = { var code = this.code if(code){ var t = Date.now() - this.load(code.value + this.load(code .replace(/</g, '<') .replace(/>/g, '>')) console.log(`Parse: ${Date.now() - t}ms`) } @@ -2126,5 +2135,99 @@ var Outline = { +//--------------------------------------------------------------------- +// Custom element... + +window.customElements.define('outline-editor', +window.OutlineEditor = + Object.assign( + function(){ + var obj = Reflect.construct(HTMLElement, [...arguments], OutlineEditor) + + obj.editor = { + __proto__: Outline, + + get code(){ + return obj.hasAttribute('value') ? + obj.getAttribute('value') + : (obj.children.length == 1 + && obj.children[0].nodeName == 'TEXTAREA') ? + obj.children[0].value + : obj.innerHTML }, + set code(value){ + // XXX this can break in conjunction with .attributeChangedCallback(..) + if(obj.hasAttribute('value')){ + obj.setAttribute('value', value) + } else if(obj.children.length == 1 + && obj.children[0].nodeName == 'TEXTAREA'){ + obj.children[0].value = value + } else { + obj.innerHTML = value } }, + } + + return obj }, + { + // constructor stuff... + observedAttributes: [ + 'value', + ], + + // instance stuff... + prototype: { + __proto__: HTMLElement.prototype, + + get value(){ + return this.getAttribute('value') }, + set value(value){ + this.setAttribute('value', value) }, + + connectedCallback: function(){ + var that = this + var shadow = this.attachShadow({mode: 'open'}) + + var style = document.createElement('link'); + style.setAttribute('rel', 'stylesheet'); + style.setAttribute('href', 'editor.css'); + + // XXX it is not rational to have this... + var editor = document.createElement('div') + editor.classList.add('editor') + + var header = document.createElement('div') + header.classList.add('header') + + var outline = document.createElement('div') + outline.classList.add('outline') + outline.setAttribute('tabindex', '0') + + //var toolbar = document.createElement('div') + //toolbar.classList.add('toolbar') + + // load the data... + setTimeout(function(){ + that.editor.setup(editor) }, 0) + + editor.append( + style, + header, + outline) + shadow.append(editor) }, + disconnectedCallback: function(){ + }, + adoptedCallback: function(){ + }, + attributeChangedCallback: function(name, oldvalue, newvalue){ + if(name == 'value'){ + console.log('---', newvalue) + //oldvalue != newvalue + // && this.editor.load(newvalue) + return } + }, + }, + })) + + + + /********************************************************************** * vim:set ts=4 sw=4 : */ diff --git a/experiments/outline-editor/index.html b/experiments/outline-editor/index.html index 86e56ac..660894a 100755 --- a/experiments/outline-editor/index.html +++ b/experiments/outline-editor/index.html @@ -354,7 +354,6 @@ var setup = function(){ -