mirror of
https://github.com/flynx/pWiki.git
synced 2025-12-25 12:21:58 +00:00
Compare commits
No commits in common. "30bbe21088ae3d612e904a106fa8aec4b6b499c7" and "a7d9d9e40fe160adb663dc7da8d13942853e6b38" have entirely different histories.
30bbe21088
...
a7d9d9e40f
@ -1,6 +1,6 @@
|
|||||||
|
|
||||||
:root {
|
:root {
|
||||||
--button-size: 2em;
|
--button-size: 5em;
|
||||||
|
|
||||||
font-family: sans-serif;
|
font-family: sans-serif;
|
||||||
font-size: 5mm;
|
font-size: 5mm;
|
||||||
@ -93,11 +93,8 @@
|
|||||||
}
|
}
|
||||||
.editor .toolbar button {
|
.editor .toolbar button {
|
||||||
display: block;
|
display: block;
|
||||||
|
|
||||||
width: var(--button-size);
|
width: var(--button-size);
|
||||||
height: var(--button-size);
|
height: var(--button-size);
|
||||||
|
|
||||||
font-size: var(--button-size);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@ -24,7 +24,6 @@ var atLine = function(elem, index){
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
//---------------------------------------------------------------------
|
//---------------------------------------------------------------------
|
||||||
|
|
||||||
var Node = {
|
var Node = {
|
||||||
@ -76,12 +75,6 @@ var Outline = {
|
|||||||
right_key_expands: true,
|
right_key_expands: true,
|
||||||
|
|
||||||
|
|
||||||
get outline(){
|
|
||||||
return this.dom.querySelector('.outline') },
|
|
||||||
get toolbar(){
|
|
||||||
return this.dom.querySelector('.toolbar') },
|
|
||||||
|
|
||||||
|
|
||||||
// XXX revise name...
|
// XXX revise name...
|
||||||
Block: function(place=none){
|
Block: function(place=none){
|
||||||
var block = document.createElement('div')
|
var block = document.createElement('div')
|
||||||
@ -137,23 +130,21 @@ var Outline = {
|
|||||||
if(node == 'prev' || node == 'previous'){
|
if(node == 'prev' || node == 'previous'){
|
||||||
return this.get('focused', -1) }
|
return this.get('focused', -1) }
|
||||||
|
|
||||||
var outline = this.outline
|
|
||||||
|
|
||||||
// node lists...
|
// node lists...
|
||||||
var NO_NODES = {}
|
var NO_NODES = {}
|
||||||
var nodes =
|
var nodes =
|
||||||
node == 'all' ?
|
node == 'all' ?
|
||||||
[...outline.querySelectorAll('[tabindex]')]
|
[...this.dom.querySelectorAll('[tabindex]')]
|
||||||
: node == 'visible' ?
|
: node == 'visible' ?
|
||||||
[...outline.querySelectorAll('[tabindex]')]
|
[...this.dom.querySelectorAll('[tabindex]')]
|
||||||
.filter(function(e){
|
.filter(function(e){
|
||||||
return e.offsetParent != null })
|
return e.offsetParent != null })
|
||||||
: node == 'editable' ?
|
: node == 'editable' ?
|
||||||
[...outline.querySelectorAll('[tabindex]>textarea')]
|
[...this.dom.querySelectorAll('[tabindex]>textarea')]
|
||||||
: node == 'selected' ?
|
: node == 'selected' ?
|
||||||
[...outline.querySelectorAll('[tabindex][selected]')]
|
[...this.dom.querySelectorAll('[tabindex][selected]')]
|
||||||
: node == 'top' ?
|
: node == 'top' ?
|
||||||
[...outline.children]
|
[...this.dom.children]
|
||||||
.filter(function(elem){
|
.filter(function(elem){
|
||||||
return elem.getAttribute('tabindex') != null })
|
return elem.getAttribute('tabindex') != null })
|
||||||
: ['siblings', 'children'].includes(node) ?
|
: ['siblings', 'children'].includes(node) ?
|
||||||
@ -175,15 +166,15 @@ var Outline = {
|
|||||||
typeof(node) == 'number' ?
|
typeof(node) == 'number' ?
|
||||||
this.at(node)
|
this.at(node)
|
||||||
: node == 'focused' ?
|
: node == 'focused' ?
|
||||||
(outline.querySelector(`[tabindex]:focus`)
|
(this.dom.querySelector(`[tabindex]:focus`)
|
||||||
|| outline.querySelector(`textarea:focus`)?.parentElement
|
|| this.dom.querySelector(`textarea:focus`)?.parentElement
|
||||||
|| outline.querySelector('[tabindex].focused'))
|
|| this.dom.querySelector('[tabindex].focused'))
|
||||||
: node == 'parent' ?
|
: node == 'parent' ?
|
||||||
this.get('focused')?.parentElement
|
this.get('focused')?.parentElement
|
||||||
: node
|
: node
|
||||||
var edited
|
var edited
|
||||||
if(node == 'edited'){
|
if(node == 'edited'){
|
||||||
edited = outline.querySelector(`textarea:focus`)
|
edited = this.dom.querySelector(`textarea:focus`)
|
||||||
node = edited?.parentElement }
|
node = edited?.parentElement }
|
||||||
|
|
||||||
if(!node || typeof(node) == 'string'){
|
if(!node || typeof(node) == 'string'){
|
||||||
@ -288,22 +279,14 @@ var Outline = {
|
|||||||
|
|
||||||
// block serialization...
|
// block serialization...
|
||||||
__code2html__: function(code){
|
__code2html__: function(code){
|
||||||
return code
|
return code },
|
||||||
// XXX STUB...
|
|
||||||
.replace(/\*(.*)\*/g, '<b>$1</b>')
|
|
||||||
.replace(/~([^~]*)~/g, '<s>$1</s>')
|
|
||||||
.replace(/_([^_]*)_/g, '<i>$1</i>') },
|
|
||||||
__html2code__: function(html){
|
__html2code__: function(html){
|
||||||
return html
|
return html },
|
||||||
// XXX STUB...
|
|
||||||
.replace(/<b>(.*)<\/b>/g, '*$1*')
|
|
||||||
.replace(/<s>(.*)<\/s>/g, '~$1~')
|
|
||||||
.replace(/<i>(.*)<\/i>/g, '_$1_') },
|
|
||||||
|
|
||||||
// serialization...
|
// serialization...
|
||||||
json: function(node){
|
json: function(node){
|
||||||
var that = this
|
var that = this
|
||||||
node ??= this.outline
|
node ??= this.dom
|
||||||
return [...node.children]
|
return [...node.children]
|
||||||
.map(function(elem){
|
.map(function(elem){
|
||||||
return elem.nodeName != 'DIV' ?
|
return elem.nodeName != 'DIV' ?
|
||||||
@ -335,14 +318,7 @@ var Outline = {
|
|||||||
return text },
|
return text },
|
||||||
|
|
||||||
// XXX use .__code2html__(..)
|
// XXX use .__code2html__(..)
|
||||||
load: function(data){
|
load: function(){},
|
||||||
// text...
|
|
||||||
if(typeof(data) == 'string'){
|
|
||||||
// XXX
|
|
||||||
}
|
|
||||||
// json...
|
|
||||||
// XXX
|
|
||||||
},
|
|
||||||
|
|
||||||
// XXX add scrollIntoView(..) to nav...
|
// XXX add scrollIntoView(..) to nav...
|
||||||
keyboard: {
|
keyboard: {
|
||||||
@ -370,7 +346,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.outline.querySelector('textarea:focus')){
|
if(this.dom.querySelector('.outline 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
|
||||||
@ -380,7 +356,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.outline.querySelector('textarea:focus')){
|
if(this.dom.querySelector('.outline 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){
|
||||||
@ -425,7 +401,7 @@ var Outline = {
|
|||||||
this.Block('after')?.querySelector('textarea')?.focus()
|
this.Block('after')?.querySelector('textarea')?.focus()
|
||||||
: this.get()?.querySelector('textarea')?.focus() },
|
: this.get()?.querySelector('textarea')?.focus() },
|
||||||
Escape: function(evt){
|
Escape: function(evt){
|
||||||
this.outline.querySelector('textarea:focus')?.parentElement?.focus() },
|
this.dom.querySelector('textarea:focus')?.parentElement?.focus() },
|
||||||
Delete: function(evt){
|
Delete: function(evt){
|
||||||
if(evt.target.isContentEditable){
|
if(evt.target.isContentEditable){
|
||||||
return }
|
return }
|
||||||
@ -448,17 +424,17 @@ 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')
|
||||||
// outline...
|
|
||||||
var outline = this.outline
|
|
||||||
// update stuff already in DOM...
|
// update stuff already in DOM...
|
||||||
for(var elem of [...outline.querySelectorAll('textarea')]){
|
for(var elem of [...outline.querySelectorAll('textarea')]){
|
||||||
elem.autoUpdateSize() }
|
elem.autoUpdateSize() }
|
||||||
|
|
||||||
// heboard handling...
|
// heboard handling...
|
||||||
outline.addEventListener('keydown',
|
outline.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',
|
outline.addEventListener('focusin',
|
||||||
function(evt){
|
function(evt){
|
||||||
@ -485,25 +461,6 @@ var Outline = {
|
|||||||
that.__code2html__(node.value)
|
that.__code2html__(node.value)
|
||||||
: node.value } })
|
: node.value } })
|
||||||
|
|
||||||
// toolbar...
|
|
||||||
var toolbar = this.toolbar
|
|
||||||
if(toolbar){
|
|
||||||
// handle return of focus when clicking toolbar...
|
|
||||||
var focus_textarea
|
|
||||||
var cahceNodeType = function(){
|
|
||||||
// NOTE: for some reason .activeElement returns an element
|
|
||||||
// that is not in the DOM after the action is done...
|
|
||||||
focus_textarea = document.activeElement.nodeName == 'TEXTAREA' }
|
|
||||||
var refocusNode = function(){
|
|
||||||
focus_textarea ?
|
|
||||||
editor.get().querySelector('textarea').focus()
|
|
||||||
: editor.get().focus()
|
|
||||||
focus_textarea = undefined }
|
|
||||||
// cache the focused node type before focus changes...
|
|
||||||
toolbar.addEventListener('mousedown', cahceNodeType)
|
|
||||||
// refocus the node after we are done...
|
|
||||||
toolbar.addEventListener('click', refocusNode) }
|
|
||||||
|
|
||||||
return this },
|
return this },
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -43,17 +43,18 @@ var setup = function(){
|
|||||||
<div tabindex=0><span>This is a line of text</span><textarea></textarea>
|
<div tabindex=0><span>This is a line of text</span><textarea></textarea>
|
||||||
</div>
|
</div>
|
||||||
<div tabindex=0><span>This is a set
|
<div tabindex=0><span>This is a set
|
||||||
text lines</span><textarea></textarea>
|
text lines</span><textarea></textarea>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="toolbar">
|
<div class="toolbar">
|
||||||
<button onclick="editor.deindent().focus()"><</button>
|
<!-- XXX these all should focus the node back so as not to hide the keyboard on mobine -->
|
||||||
<button onclick="editor.indent().focus()">></button>
|
<button onclick="editor.deindent()"><</button>
|
||||||
<button onclick="editor.Block('before').focus()">-<sup>+</sup>-</button>
|
<button onclick="editor.indent()">></button>
|
||||||
<button onclick="editor.Block('after').focus()">-<sub>+</sub>-</button>
|
<button onclick="editor.Block('before').focus()" style="text-decoration:underline">+</button>
|
||||||
<button onclick="editor.toggleCollapse()?.focus()">˅˄</button>
|
<button onclick="editor.Block('after').focus()" style="text-decoration:overline">+</button>
|
||||||
|
<button onclick="editor.toggleCollapse()">+/-</button>
|
||||||
<button onclick="editor.remove()">×</button>
|
<button onclick="editor.remove()">×</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@ -62,9 +63,8 @@ text lines</span><textarea></textarea>
|
|||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
TODO:
|
TODO:
|
||||||
- Firefox compatibility -- remove ':has(..)'
|
- mouse controls
|
||||||
- <s>focus management</s>
|
- touch controls
|
||||||
- <s>mouse/touch controls</s>
|
|
||||||
- <s>navigation</s>
|
- <s>navigation</s>
|
||||||
- <s>expand/collapse subtree</s>
|
- <s>expand/collapse subtree</s>
|
||||||
- <s>shift subtree up/down</s>
|
- <s>shift subtree up/down</s>
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user