working on crop/uncrop changes + notes...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2023-10-24 17:35:28 +03:00
parent 0e4344a711
commit b292a7ff23
2 changed files with 117 additions and 30 deletions

View File

@ -597,12 +597,80 @@ var escaping = {
//--------------------------------------------------------------------- //---------------------------------------------------------------------
var JSONOutline = { var JSONOutline = {
// Format:
// <json> ::= [
// {
// text: <text>,
// children: <json>,
// ...
// },
// ...
// ]
json: undefined, json: undefined,
// format:
// {
// <id>: <node>,
// ...
// }
__id_index: undefined,
// format:
// Map([
// [<node>, <path>],
// ...
// ])
__nodes: undefined,
__path: undefined,
current: undefined,
__iter: function*(node, path, mode){
if(typeof(path) == 'string'){
mode = path
path = null }
path ??= []
yield [path, node]
if(mode == 'visible'
&& node.collapsed){
return }
var i = 0
for(var e of node.children ?? []){
yield* this.__iter(e, [...path, i++], mode) } },
// XXX revise...
nodes: function*(node, mode){
var i = 0
// all nodes..
if(node == null || node == 'all' || node == 'visible'){
for(var e of this.json){
yield* this.__iter(e, [i++], node) }
// single node...
} else {
var args = [...arguments]
// XXX revise...
if(['all', 'visible'].includes(args.at(-1))){
mode = args.pop() }
yield* this.__iter(
this.get(...args),
mode) } },
[Symbol.iterator]: function*(mode='all'){
for(var node of this.json){
for(var [_, n] of this.__iter(node, mode)){
yield n } } },
iter: function*(node, mode){
for(var [_, n] of this.nodes(...arguments)){
yield n } },
// XXX
path: function(){}, path: function(){},
get: function(){}, get: function(node, offset){
at: function(){}, },
focus: function(){}, focus: function(node, offset){
return this.get(
this.__path = this.path(...arguments)) },
index: function(){},
at: function(index){},
indent: function(){}, indent: function(){},
deindent: function(){}, deindent: function(){},
@ -612,7 +680,7 @@ var JSONOutline = {
remove: function(){}, remove: function(){},
clear: function(){}, clear: function(){},
crom: function(){}, crop: function(){},
uncrop: function(){}, uncrop: function(){},
parseBlockAttrs: function(){}, parseBlockAttrs: function(){},
@ -623,6 +691,7 @@ var JSONOutline = {
text: function(){}, text: function(){},
} }
// XXX experiment with a concatinative model... // XXX experiment with a concatinative model...
// .get(..) -> Outline (view) // .get(..) -> Outline (view)
var Outline = { var Outline = {
@ -686,7 +755,7 @@ var Outline = {
path: function(node='focused', mode='index'){ path: function(node='focused', mode='index'){
if(['index', 'text', 'node'].includes(node)){ if(['index', 'text', 'node', 'data'].includes(node)){
mode = node mode = node
node = 'focused' } node = 'focused' }
var outline = this.outline var outline = this.outline
@ -698,6 +767,8 @@ var Outline = {
this.get(node, 'siblings').indexOf(node) this.get(node, 'siblings').indexOf(node)
: mode == 'text' ? : mode == 'text' ?
node.querySelector('.view').innerText node.querySelector('.view').innerText
: mode == 'data' ?
this.data(node)
: node) : node)
node = this.get(node, 'parent') } node = this.get(node, 'parent') }
return path }, return path },
@ -1074,43 +1145,54 @@ var Outline = {
return this }, return this },
// crop... // crop...
// XXX shoud we control crops as "crop in" / "crop out" instead of crom/uncrop???
// XXX add crop-level/path indicator... // XXX add crop-level/path indicator...
__crop_stack: undefined, __crop_stack: undefined,
crop: function(node='focused'){ crop: function(node='focused'){
var that = this var that = this
var stack = this.__crop_stack ??= []
var path = this.path()
// XXX make this linkable...
var header = '/ '
+ this.path(path.slice(0,-1), 'text')
.map(function(text, i){
return `<span>${text.split(/\n/)[0]}</span>` })
.join(' / ')
stack.push([this.json(), path]) // XXX make this relative to this.__crop_root
var stack =
this.__crop_stack = [
...this.__crop_stack ?? [],
[
this.json(),
this.path(),
this.path('text').slice(0, -1),
],
]
this.load(this.data()) this.load(this.data())
this.header.innerHTML = header // XXX make this linkable...
this.header.innerHTML = '/ '
+ stack
.map(function([s,p,t]){
return t})
.flat()
.join(' / ')
this.dom.classList.add('crop') this.dom.classList.add('crop')
return this }, return this },
// XXX use JSON API... // XXX use JSON API...
// XXX add depth argument + 'all' // XXX add depth argument + 'all'
uncrop: function(){ uncrop: function(mode=1){
if(this.__crop_stack == null){ if(this.__crop_stack == null){
return this} return this}
var [state, path] = this.__crop_stack.pop()
if(this.__crop_stack.length == 0){
this.__crop_stack = undefined
this.header.innerHTML = ''
this.dom.classList.remove('crop') }
// update state...
path
.slice(0, -1)
.reduce(function(res, i){
return res[i].children }, state)
.splice(path.at(-1), 1, ...this.json())
this.load(state) // XXX replace relevant node in this.__crop_root with state...
// XXX should this be done on the way down or on the way up???
/* XXX
var state = this.json()
while(this.__crop_stack.length > 0){
}
//*/
this.load(this.__crop_stack[0][0])
this.header.innerHTML = ''
this.__crop_stack = undefined
this.dom.classList.remove('crop')
return this }, return this },
@ -1622,7 +1704,9 @@ var Outline = {
if(this.get('edited')){ if(this.get('edited')){
this.focus() this.focus()
} else { } else {
this.uncrop() } }, evt.shiftKey ?
this.uncrop('all')
: this.uncrop() } },
c: function(evt){ c: function(evt){
if(!this.get('edited')){ if(!this.get('edited')){
this.crop() } }, this.crop() } },

View File

@ -51,7 +51,8 @@ var setup = function(){
- BUG: mobile browsers behave quite chaotically ignoring parts of the styling... - BUG: mobile browsers behave quite chaotically ignoring parts of the styling...
- -
- ## ToDo: - ## ToDo:
- crop: show crop path (and depth) - Q: crop: should we control crop via "crop-in"/"crop-out" instead of crop/uncrop??
- crop: make path clickable
- undo - undo
collapsed:: true collapsed:: true
- edit stack (position, action, ...) - edit stack (position, action, ...)
@ -111,6 +112,8 @@ var setup = function(){
- NOTE: this is only a problem if making list-items manually -- disable??? - NOTE: this is only a problem if making list-items manually -- disable???
- empty item height is a bit off... - empty item height is a bit off...
- search? - search?
- _...not sure if search should be internal or external yet..._
- DONE crop: show crop path (and depth)
- DONE over-travel pause -- when going fast over start/end stop... - DONE over-travel pause -- when going fast over start/end stop...
- DONE focus: - DONE focus:
collapsed:: true collapsed:: true