Compare commits

..

5 Commits

Author SHA1 Message Date
f5ea7b7919 notes...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2023-10-30 04:00:05 +03:00
e938bbc5aa cleanup...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2023-10-30 03:51:33 +03:00
cd20c5ab3e bugfix...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2023-10-30 03:46:07 +03:00
a24eb02876 node merging undo can merge merged sets...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2023-10-30 02:56:03 +03:00
426e8999ba fixed undo bug...
Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
2023-10-30 02:52:38 +03:00
3 changed files with 66 additions and 42 deletions

View File

@ -46,8 +46,8 @@ function clickPoint(x,y){
// elements. // elements.
// //
// XXX it would be a better idea to do a binary search instead of a liner // XXX it would be a better idea to do a binary search instead of a liner
// pass... but at this point this is not critical (unless we get // pass...
// gigantic blocks) // ...though b-search will get us to the target, we stll need to count...
// XXX HACK -- is there a better way to do this??? // XXX HACK -- is there a better way to do this???
var getCharOffset = function(elem, x, y, c){ var getCharOffset = function(elem, x, y, c){
c = c ?? 0 c = c ?? 0
@ -69,7 +69,7 @@ var getCharOffset = function(elem, x, y, c){
return Math.abs(b.x - x) <= Math.abs(prev.x - x) ? return Math.abs(b.x - x) <= Math.abs(prev.x - x) ?
c + i c + i
: c + i - 1 } } : c + i - 1 } }
c += i c += i - 1
// html node... // html node...
} else { } else {
var res = getCharOffset(e, x, y, c) var res = getCharOffset(e, x, y, c)
@ -1254,6 +1254,18 @@ var Outline = {
;(this.__undo_stack ??= []).push([path, action, args, next]) ;(this.__undo_stack ??= []).push([path, action, args, next])
this.__redo_stack = undefined this.__redo_stack = undefined
return this }, return this },
mergeUndo: function(n, stack){
stack ??= this.__undo_stack
if(stack == null || stack.length == 0){
return this }
stack.push(
stack.splice(-n, n)
.map(function(e){
return typeof(e[1]) == 'string' ?
[e]
: e })
.flat())
return this },
clearUndo: function(){ clearUndo: function(){
this.__undo_stack = undefined this.__undo_stack = undefined
this.__redo_stack = undefined this.__redo_stack = undefined
@ -1262,14 +1274,19 @@ var Outline = {
if(from == null if(from == null
|| from.length == 0){ || from.length == 0){
return [from, to] } return [from, to] }
var [path, action, args, next] = from.pop() var actions = from.pop()
actions = typeof(actions[1]) == 'string' ?
[actions]
: actions
while(actions.length > 0){
var [path, action, args, next] = actions.pop()
var l = from.length var l = from.length
path != null path != null
&& this.focus(path) && this.focus(path)
this[action](...args) this[action](...args)
next != null ? next != null ?
this.focus(next) this.focus(next)
: this.focus() : this.focus() }
if(l < from.length){ if(l < from.length){
to ??= [] to ??= []
to.push( to.push(
@ -1551,7 +1568,9 @@ var Outline = {
cur.after(block) cur.after(block)
: (place == 'before' || place == 'after') ? : (place == 'before' || place == 'after') ?
cur[place](block) cur[place](block)
: undefined } : undefined
this.setUndo(this.path(cur), 'remove', [this.path(block)]) }
return block }, return block },
// XXX see inside... // XXX see inside...
load: function(data){ load: function(data){
@ -1789,15 +1808,20 @@ var Outline = {
evt.preventDefault() evt.preventDefault()
var a = edited.selectionStart var a = edited.selectionStart
var b = edited.selectionEnd var b = edited.selectionEnd
// position 0: focus empty node above...
if(a == 0){
this.Block('prev')
this.edit('prev')
// focus new node...
} else {
var prev = edited.value.slice(0, a) var prev = edited.value.slice(0, a)
var next = edited.value.slice(b) var next = edited.value.slice(b)
edited.value = prev edited.value = prev
this.Block({text: next}, 'next') this.Block({text: next}, 'next')
// focus next if not at position 0, otherwise keep focus...
if(a != 0){
edited = this.edit('next') edited = this.edit('next')
edited.selectionStart = 0 edited.selectionStart = 0
edited.selectionEnd = 0 } edited.selectionEnd = 0
this.mergeUndo(2) }
return } return }
// view -> edit... // view -> edit...
evt.preventDefault() evt.preventDefault()
@ -1950,6 +1974,7 @@ var Outline = {
elem.selectionStart = elem.value.length elem.selectionStart = elem.value.length
elem.selectionEnd = elem.value.length elem.selectionEnd = elem.value.length
} else { } else {
console.log('---', c)
var m = getMarkdownOffset(elem.value, view.innerText, c) var m = getMarkdownOffset(elem.value, view.innerText, c)
elem.focus() elem.focus()
elem.selectionStart = c + m elem.selectionStart = c + m
@ -2199,20 +2224,10 @@ Object.assign(
return this.dom?.querySelector('.toolbar') }, return this.dom?.querySelector('.toolbar') },
set toolbar(val){}, set toolbar(val){},
// XXX these are generic...
encode: function(text){
var span = document.createElement('span')
span.innerText = text
return span.innerHTML },
decode: function(text){
var span = document.createElement('span')
span.innerHTML = text
return span.innerText },
get code(){ get code(){
return this.hasAttribute('value') ? return this.hasAttribute('value') ?
this.getAttribute('value') this.getAttribute('value')
: this.decode(this.innerHTML) }, : HTMLElement.decode(this.innerHTML) },
set code(value){ set code(value){
if(value == null){ if(value == null){
return } return }
@ -2220,7 +2235,7 @@ Object.assign(
if(this.hasAttribute('value')){ if(this.hasAttribute('value')){
this.setAttribute('value', value) this.setAttribute('value', value)
} else { } else {
this.innerHTML = this.encode(value) } }, this.innerHTML = HTMLElement.encode(value) } },
// XXX do we need this??? // XXX do we need this???
// ...rename .code -> .value ??? // ...rename .code -> .value ???

View File

@ -22,6 +22,20 @@ Element.prototype.visibleInViewport = function(partial=false){
&& right <= innerWidth) } && right <= innerWidth) }
//---------------------------------------------------------------------
// XXX should these be here???
HTMLElement.encode = function(str){
var span = document.createElement('span')
span.innerText = str
return span.innerHTML }
HTMLElement.decode = function(str){
var span = document.createElement('span')
span.innerHTML = str
return span.innerText }
//--------------------------------------------------------------------- //---------------------------------------------------------------------
HTMLTextAreaElement.prototype.updateSize = function(){ HTMLTextAreaElement.prototype.updateSize = function(){
@ -60,15 +74,20 @@ HTMLTextAreaElement.prototype.getTextGeometry = function(){
position: 'fixed', position: 'fixed',
display: 'block', display: 'block',
/* DEBUG...
top: '0px',
left: '0px',
/*/
top: '-100%', top: '-100%',
left: '-100%', left: '-100%',
//*/
width: style.width, width: style.width,
height: style.height, height: style.height,
padding: style.padding, padding: style.padding,
boxSizing: style.boxSizing, boxSizing: style.boxSizing,
//whiteSpace: 'pre-wrap', whiteSpace: style.whiteSpace,
outline: 'solid 1px red', outline: 'solid 1px red',

View File

@ -48,16 +48,6 @@ var setup = function(){
- -
- ## Bugs: - ## Bugs:
focused:: true focused:: true
- BUG: focus at times seems to be biased a bit to the right -- the caret is placed to the right from where expected...
-
_this seems to only affect text with leading whitespace only, like this._
- BUG: undo: does not handle element splitting correctly...
- place cursor somewhere here, hit `Enter`, and then undo.
- _this will correctly restore the old node but will not remove the new one_
- need to:
- add undo to `.Block(..)`
- group `new` and `cange` into one undo action...
- _undo chaining? ...i.e. support nested arrays?_
- BUG: mobile browsers behave quite chaotically ignoring parts of the styling... - BUG: mobile browsers behave quite chaotically ignoring parts of the styling...
- FF: - FF:
- zooming on edited field - zooming on edited field