diff --git a/experiments/outline-editor/editor.js b/experiments/outline-editor/editor.js index 6d51122..1879a0a 100755 --- a/experiments/outline-editor/editor.js +++ b/experiments/outline-editor/editor.js @@ -1947,7 +1947,23 @@ var Outline = { // XXX move the code here into methods/actions... // XXX use keyboard.js... __overtravel_timeout: undefined, + // XXX this needs to be dropped on any edit keyboard input, not sure + // how to do this cleanly (including focus clicks)... + __caret_x: undefined, keyboard: { + // XXX might be a good feature to add to keyboard.js... + // ...might even be fun to extend this and add key classes, + // like: + // LetterKey + // ModifierKey + // FunctionKey + // ... + Any: function(evt, key){ + if(this.get('edited') + && key != 'ArrowUp' + && key != 'ArrowDown'){ + this.__caret_x = undefined } }, + // vertical navigation... // XXX this is a bit hacky but it works -- the caret blinks at // start/end of block before switching to next, would be @@ -1968,10 +1984,29 @@ var Outline = { var edited = this.get('edited') if(edited){ - var line = edited.getTextGeometry().line - if(line == 0){ + var g = edited.getTextGeometry() + if(g.line == 0){ evt.preventDefault() - that.edit('prev') } + //var left = edited.getBoundingClientRect().x + g.offsetLeft + var left = this.__caret_x = + this.__caret_x + ?? edited.getBoundingClientRect().x + g.offsetLeft + edited = that.edit('prev') + // keep caret horizontally constrained... + var bottom = edited.getBoundingClientRect().bottom + /*/ XXX CARET_V_MOVE this is not correct yet... + var view = this.get(edited).querySelector('.view') + var c = getCharOffset(view, left, bottom - 1) + var m = getMarkdownOffset(edited.value, view.innerText, c) + console.log('---', c, m) + edited.selectionStart = + edited.selectionEnd = + c - m } + /*/ + edited.selectionStart = + edited.selectionEnd = + edited.getTextOffsetAt(left, bottom - 1) } + //*/ } else { evt.preventDefault() this.focus('focused', -1) } }, @@ -1991,10 +2026,29 @@ var Outline = { var edited = this.get('edited') if(edited){ - var {line, lines} = edited.getTextGeometry() - if(lines == 0 || line == lines - 1){ + var g = edited.getTextGeometry() + if(g.lines == 0 || g.line == g.lines - 1){ evt.preventDefault() - that.edit('next') } + //var left = edited.getBoundingClientRect().x + g.offsetLeft + var left = this.__caret_x = + this.__caret_x + ?? edited.getBoundingClientRect().x + g.offsetLeft + edited = that.edit('next') + // keep caret horizontally constrained... + var top = edited.getBoundingClientRect().y + /* XXX CARET_V_MOVE this needs fixing... + var view = this.get(edited).querySelector('.view') + var c = getCharOffset(view, left, top - 1) + var m = getMarkdownOffset(edited.value, view.innerText, c) + console.log('---', c, m) + edited.selectionStart = + edited.selectionEnd = + c - m } + /*/ + edited.selectionStart = + edited.selectionEnd = + edited.getTextOffsetAt(left, top + 1) } + //*/ } else { evt.preventDefault() this.focus('focused', 1) } }, @@ -2305,11 +2359,11 @@ var Outline = { // place the cursor where the user clicked in code/text... if(elem.classList.contains('code') && document.activeElement !== elem){ + that.__caret_x = undefined var view = that.get(elem).querySelector('.view') var initial = elem.selectionStart var c = getCharOffset(view, evt.clientX, evt.clientY) var m = getMarkdownOffset(elem.value, view.innerText, c) - console.log('---', c, m) // selecting an element with text offset by markup... if(m != 0){ evt.preventDefault() @@ -2416,8 +2470,10 @@ var Outline = { && keys.push('s_' + evt.key) keys.push(evt.key) for(var k of keys){ + if('Any' in that.keyboard){ + that.keyboard.Any.call(that, evt, k) } if(k in that.keyboard){ - that.keyboard[k].call(that, evt) + that.keyboard[k].call(that, evt, k) break } } }) // update code block... outline.addEventListener('keyup', diff --git a/experiments/outline-editor/generic.js b/experiments/outline-editor/generic.js index 54ac7ad..7cb4435 100755 --- a/experiments/outline-editor/generic.js +++ b/experiments/outline-editor/generic.js @@ -109,29 +109,33 @@ HTMLTextAreaElement.prototype.getTextGeometry = function(func){ var style = getComputedStyle(this) var paddingV = parseFloat(style.paddingTop) + parseFloat(style.paddingBottom) - var carret = document.createElement('span') - carret.innerText = '|' - carret.style.margin = '0px' - carret.style.padding = '0px' + var caret = document.createElement('span') + caret.innerText = '|' + caret.style.margin = '0px' + caret.style.padding = '0px' var span = cloneAsOffscreenSpan(this) span.append( text.slice(0, offset), - carret, - // NOTE: wee need the rest of the text for the carret to be typeset + caret, + // NOTE: wee need the rest of the text for the caret to be typeset // to the correct line... text.slice(offset)) document.body.append(span) var res = { length: text.length, + lines: Math.floor( (this.offsetHeight - paddingV) - / carret.offsetHeight), - line: Math.floor(carret.offsetTop / carret.offsetHeight), + / caret.offsetHeight), + line: Math.floor(caret.offsetTop / caret.offsetHeight), + + caretHeight: caret.offsetHeight, + offset: offset, - offsetLeft: carret.offsetLeft, - offsetTop: carret.offsetTop, + offsetLeft: caret.offsetLeft, + offsetTop: caret.offsetTop, } if(typeof(func) == 'function'){ diff --git a/experiments/outline-editor/index.html b/experiments/outline-editor/index.html index c6905d9..9934a81 100755 --- a/experiments/outline-editor/index.html +++ b/experiments/outline-editor/index.html @@ -118,8 +118,7 @@ var setup = function(){ - _also this would be a nice opportunity to start the move to a newer electron version_ - might be a good idea to make the heading level depend on its depth... - might be a good idea to think how to avoid the constant selections on focus... - - Q: do we want to place the caret when moving between nodes??? - - _would be nice to remember the caret horizontal offset for vertical movement_ + - Q: when moving up/down between nodes do we want to place the caret relative to markdown (current) or to view? (see: CARET_V_MOVE) - Q: should we use `HTMLTextAreaElement.autoUpdateSize(..)` or handle it globally in setup??? - _...I'm leaning towards the later..._ - Q: can we place a cursor in a table correctly??? @@ -221,6 +220,7 @@ var setup = function(){ - `` -- field marker - each child node will copy the template and allow editing of only fields - not clear how to handle template changes... + - DONE place the caret when moving between nodes - DONE selecting expanded code by _click-n-drag_ collapsed:: true - # this is a test