Unify selection on mousedown
This commit is contained in:
parent
3919585db4
commit
f3459430b0
|
@ -32,6 +32,8 @@
|
||||||
right: $input-padding;
|
right: $input-padding;
|
||||||
height: $selector-height;
|
height: $selector-height;
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
|
padding-left: $indentation-width;
|
||||||
|
z-index: 1;
|
||||||
|
|
||||||
.selector {
|
.selector {
|
||||||
margin-top: $selector-height / 2;
|
margin-top: $selector-height / 2;
|
||||||
|
@ -39,13 +41,13 @@
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
.selector {
|
.selector {
|
||||||
border: 1px dashed $selection-background;
|
border: 1px dashed $theme-color;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
&.selected {
|
&.selected {
|
||||||
.selector {
|
.selector {
|
||||||
border: 1px dashed $theme-color;
|
border: 1px dashed $gray;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -54,8 +56,12 @@
|
||||||
top: -$selector-height/2 - 1px;
|
top: -$selector-height/2 - 1px;
|
||||||
}
|
}
|
||||||
|
|
||||||
.after-node-selector {
|
.append-node-selector {
|
||||||
bottom: -$selector-height/2 - 1px;
|
bottom: -$selector-height/2 - 1px;
|
||||||
|
|
||||||
|
.selector {
|
||||||
|
margin-top: $selector-height / 2 - 2px;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.header {
|
.header {
|
||||||
|
|
|
@ -14,7 +14,10 @@
|
||||||
import { singleton } from './singleton.js'
|
import { singleton } from './singleton.js'
|
||||||
import {
|
import {
|
||||||
getPlainText,
|
getPlainText,
|
||||||
isChildOfButton, isContentEditableDiv,
|
isAppendNodeSelector,
|
||||||
|
isBeforeNodeSelector,
|
||||||
|
isChildOfButton,
|
||||||
|
isContentEditableDiv,
|
||||||
setPlainText
|
setPlainText
|
||||||
} from './utils/domUtils.js'
|
} from './utils/domUtils.js'
|
||||||
import Icon from 'svelte-awesome'
|
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
|
// 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
|
// initialize dragging a selection
|
||||||
singleton.mousedown = true
|
singleton.mousedown = true
|
||||||
singleton.selectionAnchor = path
|
singleton.selectionAnchor = path
|
||||||
|
@ -228,17 +251,18 @@
|
||||||
anchorPath: singleton.selectionAnchor,
|
anchorPath: singleton.selectionAnchor,
|
||||||
focusPath: singleton.selectionFocus
|
focusPath: singleton.selectionFocus
|
||||||
})
|
})
|
||||||
|
|
||||||
event.stopPropagation()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
event.stopPropagation()
|
||||||
|
event.preventDefault()
|
||||||
|
|
||||||
// we attache the mouse up event listener to the global document,
|
// 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
|
// so we will not miss if the mouse up is happening outside of the editor
|
||||||
document.addEventListener('mouseup', handleMouseUp)
|
document.addEventListener('mouseup', handleMouseUp)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleMouseMove (event) {
|
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.preventDefault()
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
|
|
||||||
|
@ -314,10 +338,10 @@
|
||||||
on:mousemove={handleMouseMove}
|
on:mousemove={handleMouseMove}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
|
data-type="before-node-selector"
|
||||||
class="before-node-selector"
|
class="before-node-selector"
|
||||||
class:selected={selectedBefore}
|
class:selected={selectedBefore}
|
||||||
style={indentationStyle}
|
style={indentationStyle}
|
||||||
on:click={handleSelectBefore}
|
|
||||||
>
|
>
|
||||||
<div class="selector"></div>
|
<div class="selector"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -372,10 +396,10 @@
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
<div
|
<div
|
||||||
|
data-type="append-node-selector"
|
||||||
class="append-node-selector"
|
class="append-node-selector"
|
||||||
class:selected={selectedAppend}
|
class:selected={selectedAppend}
|
||||||
style={indentationStyle}
|
style={indentationStyle}
|
||||||
on:click={handleSelectAfter}
|
|
||||||
>
|
>
|
||||||
<div class="selector"></div>
|
<div class="selector"></div>
|
||||||
</div>
|
</div>
|
||||||
|
@ -440,10 +464,10 @@
|
||||||
/>
|
/>
|
||||||
{/each}
|
{/each}
|
||||||
<div
|
<div
|
||||||
|
data-type="append-node-selector"
|
||||||
class="append-node-selector"
|
class="append-node-selector"
|
||||||
class:selected={selectedAppend}
|
class:selected={selectedAppend}
|
||||||
style={indentationStyle}
|
style={indentationStyle}
|
||||||
on:click={handleSelectAfter}
|
|
||||||
>
|
>
|
||||||
<div class="selector"></div>
|
<div class="selector"></div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -21,6 +21,7 @@ $highlight-active-hover-color: #f3cd00;
|
||||||
$warning-color: #FBB917;
|
$warning-color: #FBB917;
|
||||||
$error-background-color: #ffef8b;
|
$error-background-color: #ffef8b;
|
||||||
$error-border-color: #ffd700;
|
$error-border-color: #ffd700;
|
||||||
|
$dark-gray: #656565;
|
||||||
$gray: #9d9d9d;
|
$gray: #9d9d9d;
|
||||||
$gray-icon: $gray;
|
$gray-icon: $gray;
|
||||||
$light-gray: #c0c0c0;
|
$light-gray: #c0c0c0;
|
||||||
|
|
|
@ -181,16 +181,44 @@ export function traverseInnerText (element, buffer) {
|
||||||
|
|
||||||
// test whether a DOM element is a child of a button
|
// test whether a DOM element is a child of a button
|
||||||
export function isChildOfButton (element) {
|
export function isChildOfButton (element) {
|
||||||
let e = element
|
return isChildOf(element, e => e.nodeName === 'BUTTON')
|
||||||
|
|
||||||
while (e && e.nodeName !== 'BUTTON') {
|
|
||||||
e = e.parentNode
|
|
||||||
}
|
|
||||||
|
|
||||||
return e && e.nodeName === 'BUTTON'
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// test whether a DOM element is a content editable div
|
// test whether a DOM element is a content editable div
|
||||||
export function isContentEditableDiv (element) {
|
export function isContentEditableDiv (element) {
|
||||||
return (element.nodeName === 'DIV' && element.contentEditable === 'true')
|
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