Implemented `findSelectionPointerFromEvent`

This commit is contained in:
jos 2018-09-26 11:32:40 +02:00
parent 6c17d6256c
commit aaa498b4ec
5 changed files with 108 additions and 39 deletions

View File

@ -2,6 +2,9 @@ body, input, select {
font-family: sans-serif;
font-size: 11pt; }
body {
height: 2000px; }
.demo .menu {
margin: 20px 0; }
.demo .menu button, .demo .menu label {

View File

@ -4,6 +4,10 @@ body, input, select {
font-size: 11pt;
}
body {
height: 2000px;
}
.demo {
.menu {
margin: 20px 0;

View File

@ -89,10 +89,11 @@ export default class JSONNode extends PureComponent {
const jsonPropsCount = jsonProps.length
const nodeStart = h('div', {
key: 'node',
onKeyDown: this.handleKeyDown,
className: 'jsoneditor-node jsoneditor-object'
}, [
key: 'node',
onKeyDown: this.handleKeyDown,
'data-selection-area': 'contents',
className: 'jsoneditor-node jsoneditor-object'
}, [
this.renderExpandButton(),
// this.renderDelimiter('\u2610'),
this.renderProperty(),
@ -121,24 +122,39 @@ export default class JSONNode extends PureComponent {
options: this.props.options
}))
childs = h('div', {key: 'childs', className: 'jsoneditor-list'}, propsChilds)
childs = h('div', {
key: 'childs',
'data-selection-area': 'left',
className: 'jsoneditor-list'
}, propsChilds)
}
else {
childs = h('div', {key: 'childs', className: 'jsoneditor-list', 'data-area': 'emptyBefore'},
this.renderAppend('(empty object)')
childs = h('div', {
key: 'childs',
className: 'jsoneditor-list',
'data-area': 'emptyBefore', // TODO: remove
'data-selection-area': 'left'
},
this.renderEmpty('(empty object)')
)
}
}
const nodeEnd = this.props.eson[EXPANDED]
? h('div', {key: 'node-end', className: 'jsoneditor-node-end', 'data-area': 'empty'}, [
this.renderDelimiter('}', 'jsoneditor-delimiter-end')
? h('div', {
key: 'node-end',
className: 'jsoneditor-node-end',
'data-selection-area': 'right',
'data-area': 'empty', // TODO: remove
}, [
this.renderDelimiter('}', 'jsoneditor-delimiter-end', 'left')
])
: null
return h('div', {
'data-path': compileJSONPointer(this.state.path),
'data-area': 'empty',
'data-area': 'empty', // TODO: remove
'data-selection-area': 'right',
className: this.getContainerClassName(this.props.eson[SELECTION], this.state.hover),
// onMouseOver: this.handleMouseOver,
// onMouseLeave: this.handleMouseLeave
@ -151,6 +167,7 @@ export default class JSONNode extends PureComponent {
const nodeStart = h('div', {
key: 'node',
onKeyDown: this.handleKeyDown,
'data-selection-area': 'contents',
className: 'jsoneditor-node jsoneditor-array'
}, [
this.renderExpandButton(),
@ -180,24 +197,34 @@ export default class JSONNode extends PureComponent {
findKeyBinding: this.props.findKeyBinding
}))
childs = h('div', {key: 'childs', className: 'jsoneditor-list'}, items)
childs = h('div', {
key: 'childs',
'data-selection-area': 'left',
className: 'jsoneditor-list'
}, items)
}
else {
childs = h('div', {key: 'childs', className: 'jsoneditor-list', 'data-area': 'emptyBefore'},
this.renderAppend('(empty array)')
childs = h('div', {
key: 'childs',
className: 'jsoneditor-list',
'data-selection-area': 'left',
'data-area': 'emptyBefore' // TODO: remove data-area
},
this.renderEmpty('(empty array)')
)
}
}
const nodeEnd = this.props.eson[EXPANDED]
? h('div', {key: 'node-end', className: 'jsoneditor-node-end', 'data-area': 'empty'}, [
this.renderDelimiter(']', 'jsoneditor-delimiter-end')
? h('div', {key: 'node-end', className: 'jsoneditor-node-end', 'data-area': 'empty'}, [ // TODO: remove data-area
this.renderDelimiter(']', 'jsoneditor-delimiter-end', 'left')
])
: null
return h('div', {
'data-path': compileJSONPointer(this.state.path),
'data-area': 'empty',
'data-area': 'empty', // TODO: remove data-area
'data-selection-area': 'right',
className: this.getContainerClassName(this.props.eson[SELECTION], this.state.hover),
// onMouseOver: this.handleMouseOver,
// onMouseLeave: this.handleMouseLeave
@ -208,6 +235,7 @@ export default class JSONNode extends PureComponent {
const node = h('div', {
key: 'node',
onKeyDown: this.handleKeyDown,
'data-selection-area': 'contents',
className: 'jsoneditor-node'
}, [
this.renderPlaceholder(),
@ -221,7 +249,8 @@ export default class JSONNode extends PureComponent {
return h('div', {
'data-path': compileJSONPointer(this.state.path),
'data-area': 'empty',
'data-area': 'empty', // TODO: remove
'data-selection-area': 'right',
className: this.getContainerClassName(this.props.eson[SELECTION], this.state.hover),
// onMouseOver: this.handleMouseOver,
// onMouseLeave: this.handleMouseLeave
@ -233,22 +262,27 @@ export default class JSONNode extends PureComponent {
* @param {string} text
* @return {*}
*/
renderAppend (text) {
renderEmpty (text) {
return h('div', {
'data-path': compileJSONPointer(this.state.path) + '/-',
'data-area': 'empty',
className: 'jsoneditor-node',
onKeyDown: this.handleKeyDownAppend
}, [
this.renderPlaceholder('inside'),
'data-path': compileJSONPointer(this.state.path) + '/-',
'data-area': 'empty', // TODO: remove
'data-selection-area': 'right',
className: 'jsoneditor-node-container'
}, h('div', {
className: 'jsoneditor-node',
'data-selection-area': 'contents',
onKeyDown: this.handleKeyDownAppend
}, [
this.renderPlaceholder(),
this.renderReadonly(text)
])
]))
}
renderPlaceholder (dataArea = 'value') {
renderPlaceholder () {
return h('div', {
key: 'placeholder',
'data-area': dataArea,
// 'data-area': dataArea, // TODO: remove
'data-selection-area': 'left',
className: 'jsoneditor-button-placeholder'
})
}
@ -256,7 +290,7 @@ export default class JSONNode extends PureComponent {
renderReadonly (text, title = null, dataArea = 'inside') {
return h('div', {
key: 'readonly',
'data-area': dataArea,
'data-area': dataArea, // TODO: remove
className: 'jsoneditor-readonly',
title
}, text)
@ -320,14 +354,15 @@ export default class JSONNode extends PureComponent {
return h('div', {
key: 'separator',
className: 'jsoneditor-delimiter',
'data-area': 'value'
'data-area': 'value' // TODO: remove
}, ':')
}
renderDelimiter (text, className = '') {
renderDelimiter (text, className = '', dataArea) {
return h('div', {
key: text,
'data-area': 'value',
'data-area': 'value', // TODO: remove
'data-selection-area': dataArea,
className: 'jsoneditor-delimiter ' + className
}, text)
}
@ -520,6 +555,7 @@ export default class JSONNode extends PureComponent {
return h('div', {key: 'expand', className: 'jsoneditor-button-container'},
h('button', {
'data-selection-area': 'left',
className: className,
onClick: this.handleExpand,
title:
@ -561,12 +597,6 @@ export default class JSONNode extends PureComponent {
this.setState({hover: null})
}
static getRootName (value, options) {
return typeof options.name === 'string'
? options.name
: value[TYPE]
}
/** @private */
handleChangeProperty = (event) => {
const parentPath = initial(this.state.path)

View File

@ -57,10 +57,12 @@ import {
pathsFromSelection,
previousSearchResult,
search,
SELECTION,
syncEson
} from '../eson'
import TreeModeMenu from './menu/TreeModeMenu'
import Search from './menu/Search'
import { findParentWithAttribute } from '../utils/domUtils'
const AJV_OPTIONS = {
allErrors: true,
@ -254,9 +256,9 @@ export default class TreeMode extends PureComponent {
onMouseDown: this.handleTouchStart,
onTouchStart: this.handleTouchStart,
className: 'jsoneditor-list jsoneditor-root' +
(/*eson[META].selected*/ false ? ' jsoneditor-selected' : '')}, // FIXME
(eson[SELECTION] !== false ? ' jsoneditor-selected' : '')},
h(Node, {
path: [],
parentPath: null,
eson,
emit: this.emitter.emit,
findKeyBinding: this.findKeyBinding,
@ -781,6 +783,10 @@ export default class TreeMode extends PureComponent {
return
}
const selectionPointer = this.findSelectionPointerFromEvent(event)
console.log('touchStart selectionPointer=', selectionPointer)
const pointer = this.findJSONPointerFromElement(event.target)
const clickedOnEmptySpace = (event.target.nodeName === 'DIV') &&
(event.target.contentEditable !== 'true') &&
@ -856,6 +862,25 @@ export default class TreeMode extends PureComponent {
return path ? { path, area } : null
}
/**
* Find JSON pointer from an HTML element
* @param {Event} event
* @return {SelectionPointer | null}
*/
findSelectionPointerFromEvent (event) {
const areaParent = findParentWithAttribute(event.target, 'data-selection-area')
const area = areaParent ? areaParent.getAttribute('data-selection-area') : undefined
const base = (area === 'left')
? document.elementFromPoint(event.target.getBoundingClientRect().right - 1, event.clientY)
: event.target
const pathParent = findParentWithAttribute(base, 'data-path')
const path = pathParent ? pathParent.getAttribute('data-path') : undefined
return (area !== undefined && path !== undefined) ? { area, path } : null
}
/**
* Get selection from an JSONPointer
* @param {ESONPointer} pointer

View File

@ -37,6 +37,13 @@
* }} Selection
*/
/**
* @typedef {{
* area: 'left' | 'contents' | 'after',
* path: Path
* }} SelectionPointer
*/
/**
* @typedef {{matches: ESONPointer[], active: ESONPointer, text: String}} SearchResult
*/