Unify selection on mousedown

This commit is contained in:
Jos de Jong 2020-07-15 10:24:39 +02:00
parent 3919585db4
commit f3459430b0
4 changed files with 77 additions and 18 deletions

View File

@ -32,6 +32,8 @@
right: $input-padding;
height: $selector-height;
box-sizing: border-box;
padding-left: $indentation-width;
z-index: 1;
.selector {
margin-top: $selector-height / 2;
@ -39,13 +41,13 @@
&:hover {
.selector {
border: 1px dashed $selection-background;
border: 1px dashed $theme-color;
}
}
&.selected {
.selector {
border: 1px dashed $theme-color;
border: 1px dashed $gray;
}
}
}
@ -54,8 +56,12 @@
top: -$selector-height/2 - 1px;
}
.after-node-selector {
.append-node-selector {
bottom: -$selector-height/2 - 1px;
.selector {
margin-top: $selector-height / 2 - 2px;
}
}
.header {

View File

@ -14,7 +14,10 @@
import { singleton } from './singleton.js'
import {
getPlainText,
isChildOfButton, isContentEditableDiv,
isAppendNodeSelector,
isBeforeNodeSelector,
isChildOfButton,
isContentEditableDiv,
setPlainText
} from './utils/domUtils.js'
import Icon from 'svelte-awesome'
@ -218,7 +221,27 @@
}
// check if the mouse down is not happening in the key or value input fields or on a button
if (!isContentEditableDiv(event.target) && !isChildOfButton(event.target)) {
if (isContentEditableDiv(event.target) || isChildOfButton(event.target)) {
return
}
if (isBeforeNodeSelector(event.target)) {
singleton.mousedown = true
singleton.selectionAnchor = path
singleton.selectionFocus = null
onSelect({
beforePath: path
})
} else if (isAppendNodeSelector(event.target)) {
singleton.mousedown = true
singleton.selectionAnchor = path
singleton.selectionFocus = null
onSelect({
appendPath: path
})
} else {
// initialize dragging a selection
singleton.mousedown = true
singleton.selectionAnchor = path
@ -228,17 +251,18 @@
anchorPath: singleton.selectionAnchor,
focusPath: singleton.selectionFocus
})
event.stopPropagation()
}
event.stopPropagation()
event.preventDefault()
// we attache the mouse up event listener to the global document,
// so we will not miss if the mouse up is happening outside of the editor
document.addEventListener('mouseup', handleMouseUp)
}
function handleMouseMove (event) {
if (singleton.mousedown) {
if (singleton.mousedown) { // TODO: Remove the need for this, only create mousemove handle when mouse is down
event.preventDefault()
event.stopPropagation()
@ -314,10 +338,10 @@
on:mousemove={handleMouseMove}
>
<div
data-type="before-node-selector"
class="before-node-selector"
class:selected={selectedBefore}
style={indentationStyle}
on:click={handleSelectBefore}
>
<div class="selector"></div>
</div>
@ -372,10 +396,10 @@
/>
{/each}
<div
data-type="append-node-selector"
class="append-node-selector"
class:selected={selectedAppend}
style={indentationStyle}
on:click={handleSelectAfter}
>
<div class="selector"></div>
</div>
@ -440,10 +464,10 @@
/>
{/each}
<div
data-type="append-node-selector"
class="append-node-selector"
class:selected={selectedAppend}
style={indentationStyle}
on:click={handleSelectAfter}
>
<div class="selector"></div>
</div>

View File

@ -21,6 +21,7 @@ $highlight-active-hover-color: #f3cd00;
$warning-color: #FBB917;
$error-background-color: #ffef8b;
$error-border-color: #ffd700;
$dark-gray: #656565;
$gray: #9d9d9d;
$gray-icon: $gray;
$light-gray: #c0c0c0;

View File

@ -181,16 +181,44 @@ export function traverseInnerText (element, buffer) {
// test whether a DOM element is a child of a button
export function isChildOfButton (element) {
let e = element
while (e && e.nodeName !== 'BUTTON') {
e = e.parentNode
}
return e && e.nodeName === 'BUTTON'
return isChildOf(element, e => e.nodeName === 'BUTTON')
}
// test whether a DOM element is a content editable div
export function isContentEditableDiv (element) {
return (element.nodeName === 'DIV' && element.contentEditable === 'true')
}
export function isBeforeNodeSelector (element) {
return isChildOf(element, e => {
return hasAttribute(e, 'data-type', 'before-node-selector')
})
}
export function isAppendNodeSelector (element) {
return isChildOf(element, e => {
return hasAttribute(e, 'data-type', 'append-node-selector')
})
}
function hasAttribute(element, name, value) {
return typeof element.getAttribute === 'function' && element.getAttribute(name) === value
}
/**
* Test if the element or one of it's parents has a certain predicate
* Can be use for example to check whether the element or it's parent has
* a specific attribute or nodeName.
* @param {HTMLElement} element
* @param {function (element: HTMLElement) : boolean} predicate
* @returns {*}
*/
export function isChildOf (element, predicate) {
let e = element
while (e && !predicate(e)) {
e = e.parentNode
}
return e && predicate(e)
}