Unify selection on mousedown
This commit is contained in:
parent
3919585db4
commit
f3459430b0
|
@ -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 {
|
||||
|
|
|
@ -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>
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue