Highlight object when hovering, select node only when clicking inside one of the selectable areas
This commit is contained in:
parent
22845a0cc8
commit
1477aaaa4b
|
@ -12,10 +12,20 @@
|
||||||
box-sizing: border-box;
|
box-sizing: border-box;
|
||||||
}
|
}
|
||||||
|
|
||||||
&.selected .header,
|
&.hovered {
|
||||||
&.selected .contents,
|
.header,
|
||||||
&.selected .footer {
|
.contents,
|
||||||
background-color: $selection-background;
|
.footer {
|
||||||
|
background-color: $hovered-background;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
&.selected {
|
||||||
|
.header,
|
||||||
|
.contents,
|
||||||
|
.footer {
|
||||||
|
background-color: $selection-background;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$selector-height: 8px; // must be about half a line height
|
$selector-height: 8px; // must be about half a line height
|
||||||
|
|
|
@ -15,9 +15,8 @@
|
||||||
} from '../constants.js'
|
} from '../constants.js'
|
||||||
import {
|
import {
|
||||||
getPlainText,
|
getPlainText,
|
||||||
isAppendNodeSelector,
|
isChildOfAttribute,
|
||||||
isBeforeNodeSelector,
|
isChildOfNodeName,
|
||||||
isChildOfButton,
|
|
||||||
isContentEditableDiv,
|
isContentEditableDiv,
|
||||||
setPlainText
|
setPlainText
|
||||||
} from '../utils/domUtils.js'
|
} from '../utils/domUtils.js'
|
||||||
|
@ -51,6 +50,7 @@
|
||||||
|
|
||||||
let domKey
|
let domKey
|
||||||
let domValue
|
let domValue
|
||||||
|
let hovered = false
|
||||||
|
|
||||||
$: type = valueType (value)
|
$: type = valueType (value)
|
||||||
|
|
||||||
|
@ -224,11 +224,11 @@
|
||||||
}
|
}
|
||||||
|
|
||||||
// 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) || isChildOfNodeName(event.target, 'BUTTON')) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (isBeforeNodeSelector(event.target)) {
|
if (isChildOfAttribute(event.target, 'data-type', 'before-node-selector')) {
|
||||||
singleton.mousedown = true
|
singleton.mousedown = true
|
||||||
singleton.selectionAnchor = path
|
singleton.selectionAnchor = path
|
||||||
singleton.selectionFocus = null
|
singleton.selectionFocus = null
|
||||||
|
@ -236,7 +236,7 @@
|
||||||
onSelect({
|
onSelect({
|
||||||
beforePath: path
|
beforePath: path
|
||||||
})
|
})
|
||||||
} else if (isAppendNodeSelector(event.target)) {
|
} else if (isChildOfAttribute(event.target, 'data-type', 'append-node-selector')) {
|
||||||
singleton.mousedown = true
|
singleton.mousedown = true
|
||||||
singleton.selectionAnchor = path
|
singleton.selectionAnchor = path
|
||||||
singleton.selectionFocus = null
|
singleton.selectionFocus = null
|
||||||
|
@ -248,12 +248,15 @@
|
||||||
// initialize dragging a selection
|
// initialize dragging a selection
|
||||||
singleton.mousedown = true
|
singleton.mousedown = true
|
||||||
singleton.selectionAnchor = path
|
singleton.selectionAnchor = path
|
||||||
singleton.selectionFocus = path
|
singleton.selectionFocus = null
|
||||||
|
|
||||||
onSelect({
|
if (isChildOfAttribute(event.target, 'data-type', 'selectable-area')) {
|
||||||
anchorPath: singleton.selectionAnchor,
|
// select current node
|
||||||
focusPath: singleton.selectionFocus
|
onSelect({
|
||||||
})
|
anchorPath: path,
|
||||||
|
focusPath: path
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
|
@ -299,21 +302,20 @@
|
||||||
document.removeEventListener('mouseup', handleMouseUp)
|
document.removeEventListener('mouseup', handleMouseUp)
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSelectBefore (event) {
|
function handleMouseOver (event) {
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
|
|
||||||
onSelect({
|
if (
|
||||||
beforePath: path
|
isChildOfAttribute(event.target, 'data-type', 'selectable-area') &&
|
||||||
})
|
!isContentEditableDiv(event.target)
|
||||||
|
) {
|
||||||
|
hovered = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
function handleSelectAfter (event) {
|
function handleMouseOut (event) {
|
||||||
event.preventDefault()
|
|
||||||
event.stopPropagation()
|
event.stopPropagation()
|
||||||
|
hovered = false
|
||||||
onSelect({
|
|
||||||
appendPath: path
|
|
||||||
})
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// FIXME: this is not efficient. Create a nested object with the selection and pass that
|
// FIXME: this is not efficient. Create a nested object with the selection and pass that
|
||||||
|
@ -336,8 +338,11 @@
|
||||||
class='json-node'
|
class='json-node'
|
||||||
class:root={path.length === 0}
|
class:root={path.length === 0}
|
||||||
class:selected={selected}
|
class:selected={selected}
|
||||||
|
class:hovered={hovered}
|
||||||
on:mousedown={handleMouseDown}
|
on:mousedown={handleMouseDown}
|
||||||
on:mousemove={handleMouseMove}
|
on:mousemove={handleMouseMove}
|
||||||
|
on:mouseover={handleMouseOver}
|
||||||
|
on:mouseout={handleMouseOut}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
data-type="before-node-selector"
|
data-type="before-node-selector"
|
||||||
|
@ -348,7 +353,8 @@
|
||||||
<div class="selector"></div>
|
<div class="selector"></div>
|
||||||
</div>
|
</div>
|
||||||
{#if type === 'array'}
|
{#if type === 'array'}
|
||||||
<div class='header' style={indentationStyle}>
|
<div
|
||||||
|
data-type="selectable-area" class='header' style={indentationStyle} >
|
||||||
<button
|
<button
|
||||||
class='expand'
|
class='expand'
|
||||||
on:click={toggleExpand}
|
on:click={toggleExpand}
|
||||||
|
@ -422,12 +428,12 @@
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="footer" style={indentationStyle}>
|
<div data-type="selectable-area" class="footer" style={indentationStyle} >
|
||||||
<span class="delimiter">]</span>
|
<span class="delimiter">]</span>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{:else if type === 'object'}
|
{:else if type === 'object'}
|
||||||
<div class='header' style={indentationStyle}>
|
<div data-type="selectable-area" class="header" style={indentationStyle} >
|
||||||
<button
|
<button
|
||||||
class='expand'
|
class='expand'
|
||||||
on:click={toggleExpand}
|
on:click={toggleExpand}
|
||||||
|
@ -496,12 +502,12 @@
|
||||||
<div class="selector"></div>
|
<div class="selector"></div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="footer" style={indentationStyle}>
|
<div data-type="selectable-area" class="footer" style={indentationStyle} >
|
||||||
<span class="delimiter">}</span>
|
<span class="delimiter">}</span>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
{:else}
|
{:else}
|
||||||
<div class="contents" style={indentationStyle}>
|
<div data-type="selectable-area" class="contents" style={indentationStyle} >
|
||||||
{#if typeof key === 'string'}
|
{#if typeof key === 'string'}
|
||||||
<div
|
<div
|
||||||
class={keyClass}
|
class={keyClass}
|
||||||
|
|
|
@ -25,6 +25,7 @@ $gray: #9d9d9d;
|
||||||
$gray-icon: $gray;
|
$gray-icon: $gray;
|
||||||
$light-gray: #c0c0c0;
|
$light-gray: #c0c0c0;
|
||||||
$selection-background: #e0e0e0;
|
$selection-background: #e0e0e0;
|
||||||
|
$hovered-background: #f0f0f0;
|
||||||
$background-gray: #f5f5f5;
|
$background-gray: #f5f5f5;
|
||||||
|
|
||||||
$line-height: 18px;
|
$line-height: 18px;
|
||||||
|
|
|
@ -179,9 +179,12 @@ export function traverseInnerText (element, buffer) {
|
||||||
return ''
|
return ''
|
||||||
}
|
}
|
||||||
|
|
||||||
// test whether a DOM element is a child of a button
|
export function isChildOfNodeName (element, nodeName) {
|
||||||
export function isChildOfButton (element) {
|
return isChildOf(element, e => e.nodeName.toUpperCase() === nodeName.toUpperCase())
|
||||||
return isChildOf(element, e => e.nodeName === 'BUTTON')
|
}
|
||||||
|
|
||||||
|
export function isChildOfAttribute (element, name, value) {
|
||||||
|
return isChildOf(element, e => hasAttribute(e, name, value))
|
||||||
}
|
}
|
||||||
|
|
||||||
// test whether a DOM element is a content editable div
|
// test whether a DOM element is a content editable div
|
||||||
|
@ -189,18 +192,6 @@ 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) {
|
function hasAttribute(element, name, value) {
|
||||||
return typeof element.getAttribute === 'function' && element.getAttribute(name) === value
|
return typeof element.getAttribute === 'function' && element.getAttribute(name) === value
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue