mirror of
https://github.com/flynx/pWiki.git
synced 2025-12-25 04:11:56 +00:00
Compare commits
6 Commits
a3e5e4e326
...
d21d233b07
| Author | SHA1 | Date | |
|---|---|---|---|
| d21d233b07 | |||
| b80312497c | |||
| f07a4e5b66 | |||
| bf8ac4e089 | |||
| e2092e808d | |||
| 2bd9781951 |
@ -47,16 +47,39 @@
|
||||
display: none;
|
||||
}
|
||||
|
||||
.editor .children {
|
||||
|
||||
/* header */
|
||||
.editor .header {
|
||||
margin: 1em var(--outline-padding);
|
||||
padding-bottom: 1.2em;
|
||||
|
||||
border-bottom: solid 1px rgba(0,0,0,0.15);
|
||||
}
|
||||
.editor .header:empty {
|
||||
display: none;
|
||||
}
|
||||
.editor .header .path-item {
|
||||
color: gray;
|
||||
cursor: pointer;
|
||||
/* XXX needs more work... */
|
||||
max-width: 10rem;
|
||||
text-overflow: ellipsis;
|
||||
}
|
||||
.editor .header .path-item:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
.editor .header .path-item:first-child {
|
||||
padding-left: 3em;
|
||||
margin-left: -2em;
|
||||
}
|
||||
|
||||
.editor .header,
|
||||
|
||||
.editor .outline {
|
||||
display: block;
|
||||
position: relative;
|
||||
|
||||
padding: 1em var(--outline-padding);
|
||||
padding-bottom: 1.2em
|
||||
padding-bottom: 1.2em;
|
||||
}
|
||||
|
||||
/* virtual empty block... */
|
||||
@ -69,21 +92,6 @@
|
||||
.editor .outline:empty:hover:after {
|
||||
}
|
||||
|
||||
/* XXX header */
|
||||
.editor .header {
|
||||
}
|
||||
.editor .header:empty {
|
||||
display: none;
|
||||
}
|
||||
/* XXX needs more work... *//*
|
||||
.editor .header span {
|
||||
display: inline;
|
||||
max-width: 10rem;
|
||||
text-overflow: ellipsis;
|
||||
overflow: hidden;
|
||||
}
|
||||
*/
|
||||
|
||||
|
||||
.editor .outline .block {
|
||||
position: relative;
|
||||
@ -93,7 +101,8 @@
|
||||
.editor.block-offsets .outline .block {
|
||||
border-left: solid 1px silver;
|
||||
}
|
||||
.editor .outline .block .block {
|
||||
.editor .outline .block .block,
|
||||
.editor.crop .outline .block[cropped] .block[cropped] {
|
||||
margin-left: var(--item-indent);
|
||||
}
|
||||
.editor .outline .block>.text {
|
||||
@ -255,6 +264,25 @@ editor .outline .block:focus {
|
||||
}
|
||||
|
||||
|
||||
/* crop... */
|
||||
/* NOTE: also see rules for: .editor .outline .block .block
|
||||
* ...can we avoid this?? (XXX) */
|
||||
.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;
|
||||
|
||||
@ -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,70 +1145,35 @@ 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...
|
||||
__crop_stack: undefined,
|
||||
crop: function(node='focused'){
|
||||
var that = this
|
||||
|
||||
var stack = this.__crop_stack =
|
||||
this.__crop_stack ?? []
|
||||
var state = stack[0] = stack[0] ?? this.json()
|
||||
var path = stack[1] = stack[1] ?
|
||||
[...stack[1], ...this.path().slice(1)]
|
||||
: this.path(...arguments)
|
||||
stack[2] = [
|
||||
...(stack[2] ?? []),
|
||||
...this.path('text').slice(0, -1),
|
||||
]
|
||||
// clear focused -- prevent focus from shifting on uncrop...
|
||||
var e = state
|
||||
for(var i of path.slice(0, -1)){
|
||||
e = e[i].children }
|
||||
delete e[path.at(-1)].focused
|
||||
|
||||
|
||||
this.load(this.data(...arguments))
|
||||
|
||||
// XXX make this linkable...
|
||||
this.header.innerHTML = '/ ' + stack[2].join(' / ')
|
||||
this.dom.classList.add('crop')
|
||||
for(var block of [...this.outline.querySelectorAll('[cropped]')]){
|
||||
block.removeAttribute('cropped') }
|
||||
this.get(...arguments).setAttribute('cropped', '')
|
||||
this.header.innerHTML =
|
||||
`<span class="path-item" onclick="editor.uncrop('all')">/</span> `
|
||||
+ this.path(...arguments, 'text')
|
||||
.slice(0, -1)
|
||||
.map(function(s, i, {length}){
|
||||
return `<span class="path-item" onclick="editor.uncrop(${ length-i })">${s}</span> ` })
|
||||
.join(' / ')
|
||||
return this },
|
||||
// XXX use JSON API...
|
||||
uncrop: function(mode=undefined){
|
||||
if(this.__crop_stack == null){
|
||||
return this }
|
||||
// XXX is this a good way do go???
|
||||
if(mode == 'all'){
|
||||
while(this.__crop_stack != null){
|
||||
this.uncrop() }
|
||||
return this }
|
||||
|
||||
// merge changes into the state above...
|
||||
var stack = this.__crop_stack
|
||||
var [state, path, text] = stack
|
||||
var s = state
|
||||
for(var i of path.slice(0, -1)){
|
||||
s = s[i].children }
|
||||
s.splice(path.at(-1), 1, ...this.json())
|
||||
|
||||
if(path.length > 1){
|
||||
path.pop()
|
||||
text.pop()
|
||||
s = state
|
||||
for(var i of path.slice(0, -1)){
|
||||
s = s[i].children }
|
||||
s = s[path.at(-1)]
|
||||
this.load(s)
|
||||
this.header.innerHTML =
|
||||
'/ ' + stack[2].join(' / ')
|
||||
|
||||
} else {
|
||||
this.load(state)
|
||||
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.__crop_stack = undefined
|
||||
this.header.innerHTML = '' }
|
||||
|
||||
this.header.innerHTML = ''
|
||||
} else {
|
||||
this.crop(top) }
|
||||
return this },
|
||||
|
||||
// block render...
|
||||
@ -1364,7 +1329,7 @@ var Outline = {
|
||||
// ...putting the same pattern in a normal group and
|
||||
// returning it works fine...
|
||||
//.replace(/(?<=[\n\h]*)(?:(?:\n|^)\s*\w*\s*::\s*[^\n]*\s*)*$/,
|
||||
.replace(/([\n\t ]*)(?:(?:\n|^)[\t ]*\w*[\t ]*::[\t ]*[^\n]*[\t ]*)+$/,
|
||||
.replace(/([\n\t ]*)(?:(?:\n|^)[\t ]*\w+[\t ]*::[\t ]*[^\n]+[\t ]*)+$/,
|
||||
function(match, ws){
|
||||
var attrs = match
|
||||
.trim()
|
||||
@ -1434,6 +1399,8 @@ var Outline = {
|
||||
var block = document.createElement('div')
|
||||
block.classList.add('block')
|
||||
block.setAttribute('tabindex', '0')
|
||||
// XXX hack??
|
||||
block.setAttribute('cropped', '')
|
||||
// code...
|
||||
var code = document.createElement('textarea')
|
||||
.autoUpdateSize()
|
||||
@ -1457,10 +1424,10 @@ var Outline = {
|
||||
: place
|
||||
;(place == 'next'
|
||||
&& (cur.querySelector('.block')
|
||||
|| cur.nextElementSibling)) ?
|
||||
|| cur !== this.get(-1))) ?
|
||||
this.get(place).before(block)
|
||||
: (place == 'next'
|
||||
&& !cur.nextElementSibling) ?
|
||||
&& cur === this.get(-1)) ?
|
||||
cur.after(block)
|
||||
: (place == 'before' || place == 'after') ?
|
||||
cur[place](block)
|
||||
|
||||
@ -51,8 +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
|
||||
- edit stack (position, action, ...)
|
||||
@ -113,6 +111,9 @@ var setup = function(){
|
||||
- empty item height is a bit off...
|
||||
- search?
|
||||
- _...not sure if search should be internal or external yet..._
|
||||
- DONE crop: make path clickable
|
||||
- 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:
|
||||
@ -172,6 +173,9 @@ var setup = function(){
|
||||
- DONE add optional text styling to nodes
|
||||
-
|
||||
- ## Refactoring:
|
||||
- Q: Implementation: JSON-based, DOM-based (current) or both?
|
||||
- implement JSON-based
|
||||
- compare and decide...
|
||||
- Plugin architecture
|
||||
- DONE basic structure
|
||||
- plugin handler sequencing (see: `<editor>.setup(..)`)
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user