From 2bd97819511a8ab3bdc1ccc07e77a4aac8d02aa6 Mon Sep 17 00:00:00 2001 From: "Alex A. Naanou" Date: Wed, 25 Oct 2023 15:04:41 +0300 Subject: [PATCH] implemented css-based crop... Signed-off-by: Alex A. Naanou --- experiments/outline-editor/editor.css | 35 +++++++++++++++---- experiments/outline-editor/editor.js | 49 ++++++++++++++++++++++----- experiments/outline-editor/index.html | 3 +- 3 files changed, 72 insertions(+), 15 deletions(-) diff --git a/experiments/outline-editor/editor.css b/experiments/outline-editor/editor.css index b40b100..e4033d1 100755 --- a/experiments/outline-editor/editor.css +++ b/experiments/outline-editor/editor.css @@ -69,20 +69,26 @@ .editor .outline:empty:hover:after { } -/* XXX header */ +/* header */ .editor .header { } .editor .header:empty { display: none; } -/* XXX needs more work... *//* -.editor .header span { - display: inline; +.editor .header .path-item { + color: gray; + cursor: pointer; + /* XXX needs more work... */ max-width: 10rem; text-overflow: ellipsis; - overflow: hidden; } -*/ +.editor .header .path-item:hover { + text-decoration: underline; +} +.editor .header .path-item:first-child { + padding-left: 3em; + margin-left: -2em; +} .editor .outline .block { @@ -255,6 +261,23 @@ editor .outline .block:focus { } +/* crop... */ +.editor.crop .outline .block:not([cropped]) { + padding: 0; + border: none; + background: none; +} +.editor.crop .outline .block:not([cropped])>.text { + display: none; +} +.editor.crop .outline .block[cropped] { + margin-left: 0; +} +.editor.crop .outline .block[cropped] .text { + display: block; +} + + .editor .toolbar { display: inline-block; position: absolute; diff --git a/experiments/outline-editor/editor.js b/experiments/outline-editor/editor.js index 17bc3df..0dcef02 100755 --- a/experiments/outline-editor/editor.js +++ b/experiments/outline-editor/editor.js @@ -895,18 +895,18 @@ var Outline = { : offset == 'visible' ? [...node.querySelectorAll('.block')] .filter(function(e){ - return e.offsetParent != null }) + return e.querySelector('.view').offsetParent != null }) : offset == 'viewport' ? [...node.querySelectorAll('.block')] .filter(function(e){ - return e.offsetParent != null + return e.querySelector('.view').offsetParent != null && e.querySelector('.code').visibleInViewport() }) : offset == 'editable' ? [...node.querySelectorAll('.block>.code')] : offset == 'selected' ? [...node.querySelectorAll('.block[selected]')] .filter(function(e){ - return e.offsetParent != null }) + return e.querySelector('.view').offsetParent != null }) : offset == 'children' ? children(node) : offset == 'siblings' ? @@ -1145,8 +1145,10 @@ var Outline = { return this }, // crop... - // XXX shoud we control crops as "crop in" / "crop out" instead of crom/uncrop??? - // XXX add crop-level/path indicator... + /*/ XXX structural crop... + // XXX this should not change what is written to code... + // ...make crops in a separate instance??? + // ......CSS? __crop_stack: undefined, crop: function(node='focused'){ var that = this @@ -1172,9 +1174,8 @@ var Outline = { // XXX make this linkable... this.header.innerHTML = '/ ' + stack[2].join(' / ') - this.dom.classList.add('crop') + //this.dom.classList.add('crop') return this }, - // XXX use JSON API... uncrop: function(mode=undefined){ if(this.__crop_stack == null){ return this } @@ -1205,11 +1206,43 @@ var Outline = { } else { this.load(state) - this.dom.classList.remove('crop') + //this.dom.classList.remove('crop') this.__crop_stack = undefined this.header.innerHTML = '' } return this }, + /*/// XXX CSS-based crop... + crop: function(node='focused'){ + this.dom.classList.add('crop') + for(var block of [...this.outline.querySelectorAll('[cropped]')]){ + block.removeAttribute('cropped') } + this.get(...arguments).setAttribute('cropped', '') + this.header.innerHTML = + `/ ` + + this.path(...arguments, 'text') + .slice(0, -1) + .map(function(s, i, {length}){ + return `${s} ` }) + .join(' / ') + return this }, + uncrop: function(mode=1){ + var outline = this.outline + var top = this.get(0) + for(var block of [...this.outline.querySelectorAll('[cropped]')]){ + block.removeAttribute('cropped') } + // crop parent if available... + while(mode != 'all' + && mode > 0 + && top !== outline){ + top = this.get(top, 'parent') + mode-- } + if(mode == 'all' || top === outline){ + this.dom.classList.remove('crop') + this.header.innerHTML = '' + } else { + this.crop(top) } + return this }, + //*/ // block render... // XXX need a way to filter input text... diff --git a/experiments/outline-editor/index.html b/experiments/outline-editor/index.html index 1d2e143..32b4748 100755 --- a/experiments/outline-editor/index.html +++ b/experiments/outline-editor/index.html @@ -51,7 +51,6 @@ var setup = function(){ - BUG: mobile browsers behave quite chaotically ignoring parts of the styling... - - ## ToDo: - - Q: crop: should we control crop via "crop-in"/"crop-out" instead of crop/uncrop?? - crop: make path clickable - undo collapsed:: true @@ -113,6 +112,8 @@ var setup = function(){ - empty item height is a bit off... - search? - _...not sure if search should be internal or external yet..._ + - DONE Q: crop: should we control crop via "crop-in"/"crop-out" instead of crop/uncrop?? + - _crop-in/crop-out seems more natural..._ - DONE crop: show crop path (and depth) - DONE over-travel pause -- when going fast over start/end stop... - DONE focus: