Implemented selecting nodes

This commit is contained in:
jos 2017-09-29 10:06:14 +02:00
parent eee0b55636
commit 52ec02e3e1
7 changed files with 87 additions and 31 deletions

31
package-lock.json generated
View File

@ -3422,6 +3422,11 @@
"glogg": "1.0.0" "glogg": "1.0.0"
} }
}, },
"hammerjs": {
"version": "2.0.8",
"resolved": "https://registry.npmjs.org/hammerjs/-/hammerjs-2.0.8.tgz",
"integrity": "sha1-BO93hiz/K7edMPdpIJWTAiK/YPE="
},
"har-validator": { "har-validator": {
"version": "2.0.6", "version": "2.0.6",
"resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz", "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-2.0.6.tgz",
@ -6205,6 +6210,14 @@
"object-assign": "4.1.1" "object-assign": "4.1.1"
} }
}, },
"react-hammerjs": {
"version": "0.5.0",
"resolved": "https://registry.npmjs.org/react-hammerjs/-/react-hammerjs-0.5.0.tgz",
"integrity": "sha1-qiDlxfRNZg8+joftESgvEhc+d64=",
"requires": {
"hammerjs": "2.0.8"
}
},
"read-all-stream": { "read-all-stream": {
"version": "3.1.0", "version": "3.1.0",
"resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz", "resolved": "https://registry.npmjs.org/read-all-stream/-/read-all-stream-3.1.0.tgz",
@ -7050,15 +7063,6 @@
"integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=", "integrity": "sha1-J5siXfHVgrH1TmWt3UNS4Y+qBxM=",
"dev": true "dev": true
}, },
"string_decoder": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"dev": true,
"requires": {
"safe-buffer": "5.1.1"
}
},
"string-width": { "string-width": {
"version": "1.0.2", "version": "1.0.2",
"resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz",
@ -7070,6 +7074,15 @@
"strip-ansi": "3.0.1" "strip-ansi": "3.0.1"
} }
}, },
"string_decoder": {
"version": "1.0.3",
"resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.0.3.tgz",
"integrity": "sha512-4AH6Z5fzNNBcH+6XDMfA/BTt87skxqJlO0lAh3Dker5zThcAxG6mKz+iGu308UKoPPQ8Dcqx/4JhujzltRa+hQ==",
"dev": true,
"requires": {
"safe-buffer": "5.1.1"
}
},
"stringifier": { "stringifier": {
"version": "1.3.0", "version": "1.3.0",
"resolved": "https://registry.npmjs.org/stringifier/-/stringifier-1.3.0.tgz", "resolved": "https://registry.npmjs.org/stringifier/-/stringifier-1.3.0.tgz",

View File

@ -29,7 +29,8 @@
"brace": "0.9.1", "brace": "0.9.1",
"javascript-natural-sort": "0.7.1", "javascript-natural-sort": "0.7.1",
"lodash": "4.17.4", "lodash": "4.17.4",
"prop-types": "15.5.10" "prop-types": "15.5.10",
"react-hammerjs": "0.5.0"
}, },
"devDependencies": { "devDependencies": {
"ava": "0.17.0", "ava": "0.17.0",

View File

@ -145,7 +145,7 @@ export default class JSONNode extends Component {
*/ */
renderAppend (text) { renderAppend (text) {
return h('div', { return h('div', {
'data-path': compileJSONPointer(this.props.path) + '/#', 'data-path': compileJSONPointer(this.props.path) + '/-',
className: 'jsoneditor-node', className: 'jsoneditor-node',
onKeyDown: this.handleKeyDownAppend onKeyDown: this.handleKeyDownAppend
}, [ }, [

View File

@ -1,6 +1,8 @@
// @flow weak // @flow weak
import { createElement as h, Component } from 'react' import { createElement as h, Component } from 'react'
import isEqual from 'lodash/isEqual'
import Hammer from 'react-hammerjs'
import jump from '../assets/jump.js/src/jump' import jump from '../assets/jump.js/src/jump'
import Ajv from 'ajv' import Ajv from 'ajv'
@ -13,7 +15,7 @@ import {
expand, expandPath, addErrors, expand, expandPath, addErrors,
search, applySearchResults, nextSearchResult, previousSearchResult, search, applySearchResults, nextSearchResult, previousSearchResult,
applySelection, applySelection,
compileJSONPointer compileJSONPointer, parseJSONPointer
} from '../eson' } from '../eson'
import { patchEson } from '../patchEson' import { patchEson } from '../patchEson'
import { import {
@ -32,7 +34,7 @@ import {
import { createFindKeyBinding } from '../utils/keyBindings' import { createFindKeyBinding } from '../utils/keyBindings'
import { KEY_BINDINGS } from '../constants' import { KEY_BINDINGS } from '../constants'
import type { ESON, ESONPatch } from '../types' import type { ESON, ESONPatch, JSONPath } from '../types'
const AJV_OPTIONS = { const AJV_OPTIONS = {
allErrors: true, allErrors: true,
@ -182,19 +184,26 @@ export default class TreeMode extends Component {
this.renderMenu(searchResults), this.renderMenu(searchResults),
h('div', { h('div', {
key: 'contents', key: 'contents',
ref: 'contents', ref: 'contents',
className: 'jsoneditor-contents jsoneditor-tree-contents', className: 'jsoneditor-contents jsoneditor-tree-contents'
id: this.id
}, },
h('ul', {className: 'jsoneditor-list jsoneditor-root' + (data.selected ? ' jsoneditor-selected' : '')}, h(Hammer, {
h(Node, { id: this.id,
data, direction: 'DIRECTION_VERTICAL',
events: state.events, onTap: this.handleTap,
options: props, onPanStart: this.handlePanStart,
path: [], onPan: this.handlePan
prop: null },
}) h('ul', {className: 'jsoneditor-list jsoneditor-root' + (data.selected ? ' jsoneditor-selected' : '')},
h(Node, {
data,
events: state.events,
options: props,
path: [],
prop: null
})
)
) )
) )
]) ])
@ -494,6 +503,42 @@ export default class TreeMode extends Component {
this.emitOnChange (actions, result.revert, result.data) this.emitOnChange (actions, result.revert, result.data)
} }
handleTap = (event) => {
if (this.state.selection) {
this.setState({ selection: null })
}
}
handlePanStart = (event) => {
const path = this.findDataPathFromElement(event.target.firstChild)
if (path) {
this.setState({
selection: {
start: {path},
end: {path}
}
})
}
}
handlePan = (event) => {
const path = this.findDataPathFromElement(event.target.firstChild)
if (path && this.state.selection && !isEqual(path, this.state.selection.end.path)) {
this.setState({
selection: {
start: this.state.selection.start,
end: {path}
}
})
}
}
findDataPathFromElement (element: Element) : JSONPath | null {
// The .replace is to change paths like `/myarray/-` into `/myarray`
const attr = element && element.getAttribute && element.getAttribute('data-path').replace(/\/-$/, '')
return attr ? parseJSONPointer(attr) : null
}
/** /**
* Scroll the window vertically to the node with given path * Scroll the window vertically to the node with given path
* @param {Path} path * @param {Path} path

View File

@ -12,6 +12,7 @@ div.jsoneditor-search {
form.jsoneditor-search-box { form.jsoneditor-search-box {
display: inline-flex; display: inline-flex;
position: relative; position: relative;
max-width: 100%;
background-color: white; background-color: white;
border: 2px solid @theme-color; border: 2px solid @theme-color;

View File

@ -442,6 +442,7 @@ div.jsoneditor-menu-separator {
div.jsoneditor-menu-panel-right { div.jsoneditor-menu-panel-right {
float: right; float: right;
max-width: 100%;
} }
button.jsoneditor-remove span.jsoneditor-icon { button.jsoneditor-remove span.jsoneditor-icon {

View File

@ -8,11 +8,6 @@ import {
applySelection applySelection
} from '../src/eson' } from '../src/eson'
// TODO: move all JSON documents in separate json files to keep the test readable?
// TODO: instead of all slightly different copies of ESON, built them up via setIn, updateIn based on ESON
const JSON1 = loadJSON('./resources/json1.json') const JSON1 = loadJSON('./resources/json1.json')
const ESON1 = loadJSON('./resources/eson1.json') const ESON1 = loadJSON('./resources/eson1.json')
const ESON2 = loadJSON('./resources/eson2.json') const ESON2 = loadJSON('./resources/eson2.json')