added crop api...

Signed-off-by: Alex A. Naanou <alex.nanou@gmail.com>
This commit is contained in:
Alex A. Naanou 2023-10-23 04:26:00 +03:00
parent 6c484194ae
commit 04637c64a2
2 changed files with 101 additions and 11 deletions

View File

@ -596,6 +596,33 @@ var escaping = {
//--------------------------------------------------------------------- //---------------------------------------------------------------------
var JSONOutline = {
json: undefined,
path: function(){},
get: function(){},
at: function(){},
focus: function(){},
indent: function(){},
deindent: function(){},
shift: function(){},
show: function(){},
toggleCollapse: function(){},
remove: function(){},
clear: function(){},
crom: function(){},
uncrop: function(){},
parseBlockAttrs: function(){},
parse: function(){},
data: function(){},
load: 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 = {
@ -656,6 +683,15 @@ var Outline = {
return this.dom.querySelector('.toolbar') }, return this.dom.querySelector('.toolbar') },
path: function(node='focused'){
var outline = this.outline
var path = []
var node = this.get(node)
while(node != outline){
path.unshift(this.get(node, 'siblings').indexOf(node))
node = this.get(node, 'parent') }
return path },
// //
// .get([<offset>]) // .get([<offset>])
// .get('focused'[, <offset>]) // .get('focused'[, <offset>])
@ -726,6 +762,11 @@ var Outline = {
typeof(node) == 'number' ? typeof(node) == 'number' ?
[this.get('visible').at(node), [this.get('visible').at(node),
edited] edited]
: node instanceof Array ?
[node
.reduce(function(res, i){
return that.get(res, 'children')[i] }, outline),
edited]
: (node == 'outline' || node == 'root') ? : (node == 'outline' || node == 'root') ?
[outline, edited] [outline, edited]
: node == 'focused' ? : node == 'focused' ?
@ -797,8 +838,10 @@ var Outline = {
at: function(index, nodes='visible'){ at: function(index, nodes='visible'){
return this.get(nodes).at(index) }, return this.get(nodes).at(index) },
focus: function(node='focused', offset){ focus: function(node='focused', offset){
var elem = this.get(...arguments) var elem = this.get(...arguments)
elem?.focus() ?? this.get(0)
elem
&& elem.focus()
return elem }, return elem },
edit: function(node='focused', offset){ edit: function(node='focused', offset){
var elem = this.get(...arguments) var elem = this.get(...arguments)
@ -992,6 +1035,32 @@ var Outline = {
this.__change__() this.__change__()
return this }, return this },
// crop...
__crop_stack: undefined,
crop: function(node='focused'){
var stack = this.__crop_stack ??= []
stack.push([this.json(), this.path()])
this.load(this.data())
.focus()
return this },
// XXX use JSON API...
uncrop: function(){
if(this.__crop_stack == null){
return this}
var [state, path] = this.__crop_stack.pop()
if(this.__crop_stack.length == 0){
this.__crop_stack = undefined }
// 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)
.focus()
return this },
// block render... // block render...
// XXX need a way to filter input text... // XXX need a way to filter input text...
// use-case: hidden attributes... // use-case: hidden attributes...
@ -1250,8 +1319,10 @@ var Outline = {
load: function(data){ load: function(data){
var that = this var that = this
data = typeof(data) == 'string' ? data = typeof(data) == 'string' ?
this.parse(data) this.parse(data)
: data : data instanceof Array ?
data
: [data]
// generate dom... // generate dom...
var level = function(lst){ var level = function(lst){
return lst return lst
@ -1437,7 +1508,13 @@ var Outline = {
evt.preventDefault() evt.preventDefault()
this.edit() }, this.edit() },
Escape: function(evt){ Escape: function(evt){
this.focus() }, if(this.get('edited')){
this.focus()
} else {
this.uncrop() } },
c: function(evt){
if(!this.get('edited')){
this.crop() } },
Delete: function(evt){ Delete: function(evt){
var edited = this.get('edited') var edited = this.get('edited')
@ -1654,6 +1731,10 @@ var Outline = {
console.log(`Parse: ${Date.now() - t}ms`) } console.log(`Parse: ${Date.now() - t}ms`) }
this.runPlugins('__setup__', this) this.runPlugins('__setup__', this)
// autofocus...
if(this.dom.getAttribute('autofocus') != null){
this.focus() }
return this }, return this },
} }

View File

@ -31,7 +31,7 @@ var setup = function(){
</script> </script>
</head> </head>
<body onload="setup()"> <body onload="setup()">
<div class="editor"> <div class="editor" autofocus>
<!-- code --> <!-- code -->
<textarea class="code"> <textarea class="code">
- # Outline editor prototype - # Outline editor prototype
@ -44,17 +44,21 @@ var setup = function(){
- // Seems that I unintentionally implemented quite a chunk of the markdown spec ;) - // Seems that I unintentionally implemented quite a chunk of the markdown spec ;)
- -
- ## Bugs: - ## Bugs:
focused:: true
- BUG: editor: FF seems to update the style every other key press -- should be live... - BUG: editor: FF seems to update the style every other key press -- should be live...
- BUG: scrolling into view needs tuning... - BUG: scrolling into view needs tuning...
- BUG: mobile browsers behave quite chaotically ignoring parts of the styling... - BUG: mobile browsers behave quite chaotically ignoring parts of the styling...
- -
- ## ToDo: - ## ToDo:
- pgup/pgdown/~home/end~ buttons - pgup/pgdown/~home/end~ buttons
- identify a block (index, id, ...) - identify a block
- FEATURE: "crop" -- view block tree separately... - DONE index (flat)
- DONE path (index)
- id
- _the id attr is done, but we still need to get the node via id_
- focus - focus
- `<editor>.autofocus` - DONE `<editor>.autofocus`
- `focused:: true` attr (`.text(..)`/`.json(..)`/`.load(..)`) - DONE `focused:: true` attr (`.text(..)`/`.json(..)`/`.load(..)`)
- focusing editor -> focus focused block - focusing editor -> focus focused block
- undo - undo
collapsed:: true collapsed:: true
@ -90,7 +94,11 @@ var setup = function(){
- `<editable/>` -- field marker - `<editable/>` -- field marker
- each child node will copy the template and allow editing of only fields - each child node will copy the template and allow editing of only fields
- not clear how to handle template changes... - not clear how to handle template changes...
- might be a good idea to split the editor into a generic and dom versions... - JSON API
- `.path(..)`
- `.get(..)`
- `.at(..)`
- ...
- cli - cli
- Q: do we use \\t for indent? (option???) - Q: do we use \\t for indent? (option???)
- Q: persistent empty first/last node (a button to create a new node)? - Q: persistent empty first/last node (a button to create a new node)?
@ -106,6 +114,7 @@ var setup = function(){
block text block text
- 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...
- DONE FEATURE: "crop" -- view block tree separately...
- DONE unify attr parsing - DONE unify attr parsing
collapsed:: true collapsed:: true
- _now duplicated in `.parse(..)` and `.__code2html__(..)`_ - _now duplicated in `.parse(..)` and `.__code2html__(..)`_