mirror of
https://github.com/flynx/pWiki.git
synced 2025-12-25 04:11:56 +00:00
Compare commits
No commits in common. "2fd8fbdbeb308a47cc4426514531a1ba63ab9882" and "0c5c5f2a5f60b1f9d9fe2d841d39d357149bbb49" have entirely different histories.
2fd8fbdbeb
...
0c5c5f2a5f
@ -1,30 +1,17 @@
|
|||||||
|
|
||||||
:root {
|
:root {
|
||||||
--button-size: 5em;
|
|
||||||
|
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
font-size: 5mm;
|
font-size: 5mm;
|
||||||
}
|
}
|
||||||
|
|
||||||
.editor {
|
.editor [tabindex] {
|
||||||
display: block;
|
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
.editor div [tabindex] {
|
||||||
.editor .outline {
|
|
||||||
display: block;
|
|
||||||
position: relative;
|
|
||||||
width: calc(100% - var(--button-size));
|
|
||||||
}
|
|
||||||
|
|
||||||
.editor .outline [tabindex] {
|
|
||||||
position: relative;
|
|
||||||
}
|
|
||||||
.editor .outline div [tabindex] {
|
|
||||||
margin-left: 2em;
|
margin-left: 2em;
|
||||||
}
|
}
|
||||||
.editor .outline [tabindex]>span,
|
.editor [tabindex]>span,
|
||||||
.editor .outline [tabindex]>textarea {
|
.editor [tabindex]>textarea {
|
||||||
--padding: 0.2em;
|
--padding: 0.2em;
|
||||||
|
|
||||||
display: block;
|
display: block;
|
||||||
@ -41,61 +28,41 @@
|
|||||||
outline: none;
|
outline: none;
|
||||||
border: none;
|
border: none;
|
||||||
}
|
}
|
||||||
.editor .outline [tabindex]>textarea {
|
.editor [tabindex]>textarea {
|
||||||
height: calc(2 * var(--padding) + 1em);
|
height: calc(2 * var(--padding) + 1em);
|
||||||
overflow: hidden;
|
overflow: hidden;
|
||||||
resize: none;
|
resize: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* show/hide node's view/code... */
|
/* show/hide node's view/code... */
|
||||||
.editor .outline [tabindex]>span+textarea:not(:focus),
|
.editor [tabindex]>span+textarea:not(:focus),
|
||||||
/* XXX not sure how to do this without :has(..)... */
|
/* XXX not sure how to do this without :has(..)... */
|
||||||
.editor .outline [tabindex]:has(>span+textarea:focus)>span:has(+textarea),
|
.editor [tabindex]:has(>span+textarea:focus)>span:has(+textarea),
|
||||||
.editor .outline [tabindex]:focus>span+textarea {
|
.editor [tabindex]:focus>span+textarea {
|
||||||
position: absolute;
|
position: absolute;
|
||||||
opacity: 0;
|
opacity: 0;
|
||||||
top: 0;
|
top: 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* focus... */
|
.editor div[collapsed] {
|
||||||
.editor .outline [tabindex]:focus {
|
|
||||||
/*outline: solid 0.2em silver;*/
|
|
||||||
outline: none;
|
|
||||||
}
|
|
||||||
.editor .outline [tabindex]:focus>span,
|
|
||||||
.editor .outline [tabindex]:focus>textarea {
|
|
||||||
background: rgba(0,0,0,0.1);
|
|
||||||
}
|
|
||||||
.editor .outline [tabindex].focused:not(:focus)>span,
|
|
||||||
.editor .outline [tabindex].focused:not(:focus)>textarea {
|
|
||||||
background: rgba(0,0,0,0.05);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
.editor .outline div[collapsed] {
|
|
||||||
border-bottom: solid 1px silver;
|
border-bottom: solid 1px silver;
|
||||||
}
|
}
|
||||||
.editor .outline div[collapsed] div {
|
.editor div[collapsed] div {
|
||||||
display: none;
|
display: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* XXX are we selecting subtrees or blocks??? */
|
/* XXX are we selecting subtrees or blocks??? */
|
||||||
.editor .outline [selected] {
|
.editor [selected] {
|
||||||
background: silver;
|
background: silver;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.editor div:focus {
|
||||||
.editor .toolbar {
|
/*outline: solid 0.2em silver;*/
|
||||||
display: inline-block;
|
outline: none;
|
||||||
position: absolute;
|
|
||||||
top: 1em;
|
|
||||||
right: 1em;
|
|
||||||
}
|
}
|
||||||
.editor .toolbar button {
|
.editor div:focus>span,
|
||||||
display: block;
|
.editor div:focus>textarea {
|
||||||
width: var(--button-size);
|
background: rgba(0,0,0,0.1);
|
||||||
height: var(--button-size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -121,7 +121,6 @@ var Outline = {
|
|||||||
// -> <nodes>
|
// -> <nodes>
|
||||||
//
|
//
|
||||||
// XXX add support for node ID...
|
// XXX add support for node ID...
|
||||||
// XXX need to be able to get the next elem on same level...
|
|
||||||
get: function(node='focused', offset){
|
get: function(node='focused', offset){
|
||||||
var that = this
|
var that = this
|
||||||
|
|
||||||
@ -168,8 +167,7 @@ var Outline = {
|
|||||||
this.at(node)
|
this.at(node)
|
||||||
: node == 'focused' ?
|
: node == 'focused' ?
|
||||||
(this.dom.querySelector(`[tabindex]:focus`)
|
(this.dom.querySelector(`[tabindex]:focus`)
|
||||||
|| this.dom.querySelector(`textarea:focus`)?.parentElement
|
|| this.dom.querySelector(`textarea:focus`)?.parentElement)
|
||||||
|| this.dom.querySelector('[tabindex].focused'))
|
|
||||||
: node == 'parent' ?
|
: node == 'parent' ?
|
||||||
this.get('focused')?.parentElement
|
this.get('focused')?.parentElement
|
||||||
: node
|
: node
|
||||||
@ -194,12 +192,6 @@ var Outline = {
|
|||||||
return elem.getAttribute('tabindex') != null }) }
|
return elem.getAttribute('tabindex') != null }) }
|
||||||
|
|
||||||
// offset...
|
// offset...
|
||||||
offset =
|
|
||||||
offset == 'next' ?
|
|
||||||
1
|
|
||||||
: offset == 'prev' ?
|
|
||||||
-1
|
|
||||||
: offset
|
|
||||||
if(typeof(offset) == 'number'){
|
if(typeof(offset) == 'number'){
|
||||||
nodes = this.get('visible')
|
nodes = this.get('visible')
|
||||||
var i = nodes.indexOf(node) + offset
|
var i = nodes.indexOf(node) + offset
|
||||||
@ -214,8 +206,8 @@ 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'){},
|
||||||
edit: function(node='focused', offset){},
|
edit: function(node='focused'){},
|
||||||
|
|
||||||
indent: function(node='focused', indent=true){
|
indent: function(node='focused', indent=true){
|
||||||
// .indent(<indent>)
|
// .indent(<indent>)
|
||||||
@ -229,7 +221,7 @@ var Outline = {
|
|||||||
// deindent...
|
// deindent...
|
||||||
if(!indent){
|
if(!indent){
|
||||||
var parent = cur.parentElement
|
var parent = cur.parentElement
|
||||||
if(!parent.classList.contains('.outline')){
|
if(!parent.classList.contains('.editor')){
|
||||||
var children = siblings.slice(siblings.indexOf(cur)+1)
|
var children = siblings.slice(siblings.indexOf(cur)+1)
|
||||||
parent.after(cur)
|
parent.after(cur)
|
||||||
children.length > 0
|
children.length > 0
|
||||||
@ -268,16 +260,9 @@ var Outline = {
|
|||||||
elem.updateSize() } }
|
elem.updateSize() } }
|
||||||
return node },
|
return node },
|
||||||
|
|
||||||
remove: function(node='focused', offset){
|
// XXX
|
||||||
var elem = this.get(...arguments)
|
remove: function(node){
|
||||||
var next
|
},
|
||||||
if(elem.classList.contains('focused')){
|
|
||||||
// XXX need to be able to get the next elem on same level...
|
|
||||||
this.toggleCollapse(elem)
|
|
||||||
next = this.get(elem, 'next') }
|
|
||||||
elem?.remove()
|
|
||||||
next?.focus()
|
|
||||||
return this },
|
|
||||||
|
|
||||||
// block serialization...
|
// block serialization...
|
||||||
__code2html__: function(code){
|
__code2html__: function(code){
|
||||||
@ -348,7 +333,7 @@ var Outline = {
|
|||||||
// horizontal navigation / collapse...
|
// horizontal navigation / collapse...
|
||||||
// XXX if at start/end of element move to prev/next...
|
// XXX if at start/end of element move to prev/next...
|
||||||
ArrowLeft: function(evt){
|
ArrowLeft: function(evt){
|
||||||
if(this.dom.querySelector('.outline textarea:focus')){
|
if(this.dom.querySelector('.editor textarea:focus')){
|
||||||
// XXX if at end of element move to next...
|
// XXX if at end of element move to next...
|
||||||
return }
|
return }
|
||||||
;((this.left_key_collapses
|
;((this.left_key_collapses
|
||||||
@ -358,7 +343,7 @@ var Outline = {
|
|||||||
this.toggleCollapse(true)
|
this.toggleCollapse(true)
|
||||||
: this.get('parent')?.focus() },
|
: this.get('parent')?.focus() },
|
||||||
ArrowRight: function(evt){
|
ArrowRight: function(evt){
|
||||||
if(this.dom.querySelector('.outline textarea:focus')){
|
if(this.dom.querySelector('.editor textarea:focus')){
|
||||||
// XXX if at end of element move to next...
|
// XXX if at end of element move to next...
|
||||||
return }
|
return }
|
||||||
if(this.right_key_expands){
|
if(this.right_key_expands){
|
||||||
@ -407,7 +392,10 @@ var Outline = {
|
|||||||
Delete: function(evt){
|
Delete: function(evt){
|
||||||
if(evt.target.isContentEditable){
|
if(evt.target.isContentEditable){
|
||||||
return }
|
return }
|
||||||
this.remove() },
|
this.toggleCollapse(true)
|
||||||
|
var next = this.get('next')
|
||||||
|
this.get()?.remove()
|
||||||
|
next?.focus() },
|
||||||
|
|
||||||
// select...
|
// select...
|
||||||
// XXX add:
|
// XXX add:
|
||||||
@ -426,26 +414,20 @@ var Outline = {
|
|||||||
setup: function(dom){
|
setup: function(dom){
|
||||||
var that = this
|
var that = this
|
||||||
this.dom = dom
|
this.dom = dom
|
||||||
var outline = dom.querySelector('.outline')
|
|
||||||
// update stuff already in DOM...
|
// update stuff already in DOM...
|
||||||
for(var elem of [...outline.querySelectorAll('textarea')]){
|
for(var elem of [...dom.querySelectorAll('.editor textarea')]){
|
||||||
elem.autoUpdateSize() }
|
elem.autoUpdateSize() }
|
||||||
|
|
||||||
// heboard handling...
|
// heboard handling...
|
||||||
outline.addEventListener('keydown',
|
dom.addEventListener('keydown',
|
||||||
function(evt){
|
function(evt){
|
||||||
evt.key in that.keyboard
|
evt.key in that.keyboard
|
||||||
&& that.keyboard[evt.key].call(that, evt) })
|
&& that.keyboard[evt.key].call(that, evt) })
|
||||||
|
|
||||||
// toggle view/code of nodes...
|
// toggle view/code of nodes...
|
||||||
outline.addEventListener('focusin',
|
dom.addEventListener('focusin',
|
||||||
function(evt){
|
function(evt){
|
||||||
var node = evt.target
|
var node = evt.target
|
||||||
// handle focus...
|
|
||||||
for(var e of [...that.dom.querySelectorAll('.focused')]){
|
|
||||||
e.classList.remove('focused') }
|
|
||||||
that.get('focused')?.classList?.add('focused')
|
|
||||||
// textarea...
|
|
||||||
if(node.nodeName == 'TEXTAREA'
|
if(node.nodeName == 'TEXTAREA'
|
||||||
&& node?.previousElementSibling?.nodeName == 'SPAN'){
|
&& node?.previousElementSibling?.nodeName == 'SPAN'){
|
||||||
node.value =
|
node.value =
|
||||||
@ -453,7 +435,7 @@ var Outline = {
|
|||||||
that.__html2code__(node.previousElementSibling.innerHTML)
|
that.__html2code__(node.previousElementSibling.innerHTML)
|
||||||
: node.previousElementSibling.innerHTML
|
: node.previousElementSibling.innerHTML
|
||||||
node.updateSize() } })
|
node.updateSize() } })
|
||||||
outline.addEventListener('focusout',
|
dom.addEventListener('focusout',
|
||||||
function(evt){
|
function(evt){
|
||||||
var node = evt.target
|
var node = evt.target
|
||||||
if(node.nodeName == 'TEXTAREA'
|
if(node.nodeName == 'TEXTAREA'
|
||||||
|
|||||||
@ -21,39 +21,30 @@ var setup = function(){
|
|||||||
</head>
|
</head>
|
||||||
<body onload="setup()">
|
<body onload="setup()">
|
||||||
<div class="editor">
|
<div class="editor">
|
||||||
<div class="outline">
|
<div tabindex=0>
|
||||||
<div tabindex=0>
|
<span><i>root</i></span><textarea></textarea>
|
||||||
<span><i>root</i></span><textarea></textarea>
|
<div tabindex=0 collapsed>
|
||||||
<div tabindex=0 collapsed>
|
<span>A</span><textarea></textarea>
|
||||||
<span>A</span><textarea></textarea>
|
<div tabindex=0><span>a</span><textarea></textarea>
|
||||||
<div tabindex=0><span>a</span><textarea></textarea>
|
|
||||||
</div>
|
|
||||||
<div tabindex=0><span>b</span><textarea></textarea>
|
|
||||||
</div>
|
|
||||||
<div tabindex=0><span>c</span><textarea></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div tabindex=0><span>B</span><textarea></textarea>
|
<div tabindex=0><span>b</span><textarea></textarea>
|
||||||
<div tabindex=0><span>d</span><textarea></textarea>
|
|
||||||
</div>
|
|
||||||
<div tabindex=0><span>e</span><textarea></textarea>
|
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
<div tabindex=0><span>C</span><textarea></textarea>
|
<div tabindex=0><span>c</span><textarea></textarea>
|
||||||
<div tabindex=0><span>This is a line of text</span><textarea></textarea>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div tabindex=0><span>This is a set
|
<div tabindex=0><span>B</span><textarea></textarea>
|
||||||
text lines</span><textarea></textarea>
|
<div tabindex=0><span>d</span><textarea></textarea>
|
||||||
</div>
|
</div>
|
||||||
|
<div tabindex=0><span>e</span><textarea></textarea>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div tabindex=0><span>C</span><textarea></textarea>
|
||||||
|
<div tabindex=0><span>This is a line of text</span><textarea></textarea>
|
||||||
|
</div>
|
||||||
|
<div tabindex=0><span>This is a set
|
||||||
|
text lines</span><textarea></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
<div class="toolbar">
|
|
||||||
<button onclick="editor.deindent()"><</button>
|
|
||||||
<button onclick="editor.indent()">></button>
|
|
||||||
<button onclick="editor.Block('before').focus()">O</button>
|
|
||||||
<button onclick="editor.Block('after').focus()">o</button>
|
|
||||||
<button onclick="editor.remove()">×</button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user