From 37ae2111ee9c1bc3680ab16656edc527b0d0ddd0 Mon Sep 17 00:00:00 2001 From: jos Date: Sat, 16 Jul 2016 13:48:20 +0200 Subject: [PATCH] Created context menu button. Some refactoring --- package.json | 1 + src/ContextMenu.js | 11 +++++++++ src/JSONNode.js | 59 +++++++++++++++++++++++++++++----------------- src/Main.js | 33 ++++++++++++++++---------- src/jsoneditor.css | 24 ++++++++++++++++++- src/typedef.js | 1 + 6 files changed, 95 insertions(+), 34 deletions(-) create mode 100644 src/ContextMenu.js diff --git a/package.json b/package.json index 1214e13..60c0198 100644 --- a/package.json +++ b/package.json @@ -38,6 +38,7 @@ "gulp-shell": "0.5.2", "gulp-util": "3.0.7", "json-loader": "0.5.4", + "json-pointer": "0.5.0", "mithril": "0.2.5", "mkdirp": "0.5.1", "mocha": "2.4.5", diff --git a/src/ContextMenu.js b/src/ContextMenu.js new file mode 100644 index 0000000..ae9e4d7 --- /dev/null +++ b/src/ContextMenu.js @@ -0,0 +1,11 @@ +import { h, Component } from 'preact' + +export default class ContextMenu extends Component { + constructor(props) { + super(props) + } + + render () { + return h('div', {class: 'jsoneditor-contextmenu'}, 'context menu...') + } +} diff --git a/src/JSONNode.js b/src/JSONNode.js index ffa252f..0081251 100644 --- a/src/JSONNode.js +++ b/src/JSONNode.js @@ -1,4 +1,6 @@ import { h, Component } from 'preact' + +import ContextMenu from './ContextMenu' import { escapeHTML, unescapeHTML } from './utils/stringUtils' import { getInnerText } from './utils/domUtils' import {stringConvert, valueType, isUrl} from './utils/typeUtils' @@ -13,6 +15,7 @@ export default class JSONNode extends Component { this.handleClickValue = this.handleClickValue.bind(this) this.handleKeyDownValue = this.handleKeyDownValue.bind(this) this.handleExpand = this.handleExpand.bind(this) + this.handleContextMenu = this.handleContextMenu.bind(this) } render (props) { @@ -27,13 +30,14 @@ export default class JSONNode extends Component { } } - renderJSONObject ({data, index, options, onChangeValue, onChangeProperty, onExpand}) { + renderJSONObject ({data, index, options, events}) { const childCount = data.childs.length const contents = [ h('div', {class: 'jsoneditor-node jsoneditor-object'}, [ this.renderExpandButton(), + this.renderContextMenuButton(), this.renderProperty(data, index, options), - this.renderSeparator(), + this.renderSeparator(), // TODO: remove separator for Object and Array (gives an issue in Preact) this.renderReadonly(`{${childCount}}`, `Array containing ${childCount} items`) ]) ] @@ -43,9 +47,7 @@ export default class JSONNode extends Component { return h(JSONNode, { data: child, options, - onChangeValue, - onChangeProperty, - onExpand + events }) }) @@ -55,13 +57,14 @@ export default class JSONNode extends Component { return h('li', {}, contents) } - renderJSONArray ({data, index, options, onChangeValue, onChangeProperty, onExpand}) { + renderJSONArray ({data, index, options, events}) { const childCount = data.childs.length const contents = [ h('div', {class: 'jsoneditor-node jsoneditor-array'}, [ this.renderExpandButton(), + this.renderContextMenuButton(), this.renderProperty(data, index, options), - this.renderSeparator(), + this.renderSeparator(), // TODO: remove separator for Object and Array (gives an issue in Preact) this.renderReadonly(`[${childCount}]`, `Array containing ${childCount} items`) ]) ] @@ -72,9 +75,7 @@ export default class JSONNode extends Component { data: child, index, options, - onChangeValue, - onChangeProperty, - onExpand + events }) }) @@ -88,6 +89,7 @@ export default class JSONNode extends Component { return h('li', {}, [ h('div', {class: 'jsoneditor-node'}, [ h('div', {class: 'jsoneditor-button-placeholder'}), + this.renderContextMenuButton(), this.renderProperty(data, index, options), this.renderSeparator(), this.renderValue(data.value) @@ -116,14 +118,6 @@ export default class JSONNode extends Component { }, content) } - static _rootName (data, options) { - return typeof options.name === 'string' - ? options.name - : (data.type === 'object' || data.type === 'array') - ? data.type - : valueType(data.value) - } - renderSeparator() { return h('div', {class: 'jsoneditor-separator'}, ':') } @@ -151,22 +145,41 @@ export default class JSONNode extends Component { ) } + renderContextMenuButton () { + const childs = this.props.data.menu ? [ + h(ContextMenu) + ] : null + + const className = `jsoneditor-button jsoneditor-contextmenu` + return h('div', {class: 'jsoneditor-button-container'}, + h('button', {class: className, onClick: this.handleContextMenu}, childs) + ) + } + shouldComponentUpdate(nextProps, nextState) { return Object.keys(nextProps).some(prop => this.props[prop] !== nextProps[prop]) } + static _rootName (data, options) { + return typeof options.name === 'string' + ? options.name + : (data.type === 'object' || data.type === 'array') + ? data.type + : valueType(data.value) + } + handleChangeProperty (event) { const property = unescapeHTML(getInnerText(event.target)) const oldPath = this.props.data.path const newPath = oldPath.slice(0, oldPath.length - 1).concat(property) - this.props.onChangeProperty(oldPath, newPath) + this.props.events.onChangeProperty(oldPath, newPath) } handleChangeValue (event) { const value = this._getValueFromEvent(event) - this.props.onChangeValue(this.props.data.path, value) + this.props.events.onChangeValue(this.props.data.path, value) } handleClickValue (event) { @@ -182,7 +195,11 @@ export default class JSONNode extends Component { } handleExpand (event) { - this.props.onExpand(this.props.data.path, !this.props.data.expanded) + this.props.events.onExpand(this.props.data.path, !this.props.data.expanded) + } + + handleContextMenu (event) { + this.props.events.onContextMenu(this.props.data.path, !this.props.data.menu) } _openLinkIfUrl (event) { diff --git a/src/Main.js b/src/Main.js index 972f022..44aa4fa 100644 --- a/src/Main.js +++ b/src/Main.js @@ -20,24 +20,25 @@ export default class Main extends Component { expanded: true, path: [], childs: [] - } - } + }, - this._onExpand = this._onExpand.bind(this) - this._onChangeValue = this._onChangeValue.bind(this) - this._onChangeProperty = this._onChangeProperty.bind(this) + events: { + onChangeProperty: this._onChangeProperty.bind(this), + onChangeValue: this._onChangeValue.bind(this), + onExpand: this._onExpand.bind(this), + onContextMenu: this._onContextMenu.bind(this) + }, + + menu: null, + + search: null + } } render() { return h('div', {class: 'jsoneditor'}, [ h('ul', {class: 'jsoneditor-list'}, [ - h(JSONNode, { - data: this.state.data, - options: this.state.options, - onChangeProperty: this._onChangeProperty, - onChangeValue: this._onChangeValue, - onExpand: this._onExpand - }) + h(JSONNode, this.state) ]) ]) } @@ -70,6 +71,14 @@ export default class Main extends Component { }) } + _onContextMenu(path, visible) { + const modelPath = Main._pathToModelPath(this.state.data, path).concat('menu') + + this.setState({ + data: setIn(this.state.data, modelPath, visible) + }) + } + // TODO: comment get () { return Main._modelToJson(this.state.data) diff --git a/src/jsoneditor.css b/src/jsoneditor.css index cb4c1cd..e8a0f9e 100644 --- a/src/jsoneditor.css +++ b/src/jsoneditor.css @@ -21,7 +21,7 @@ ul.jsoneditor-list { list-style-type: none; - padding-left: 24px; + padding-left: 20px; margin: 0; font-size: 0; } @@ -128,6 +128,7 @@ div.jsoneditor-value.jsoneditor-url { } button.jsoneditor-button { + position: relative; width: 20px; height: 20px; padding: 0; @@ -155,3 +156,24 @@ button.jsoneditor-button.jsoneditor-collapsed { button.jsoneditor-button.jsoneditor-expanded { background-position: -2px -74px; } + +button.jsoneditor-button.jsoneditor-contextmenu { + background-position: -50px -74px; +} + +button.jsoneditor-button.jsoneditor-contextmenu:hover, +button.jsoneditor-button.jsoneditor-contextmenu:focus, +button.jsoneditor-button.jsoneditor-contextmenu.jsoneditor-selected { + background-position: -50px -50px; +} + +div.jsoneditor-contextmenu { + position: absolute; + top: 20px; + left: 0; + + z-index: 1; + background: white; + padding: 5px; + border: 1px solid gray; +} diff --git a/src/typedef.js b/src/typedef.js index e07329d..444ce00 100644 --- a/src/typedef.js +++ b/src/typedef.js @@ -3,6 +3,7 @@ * @typedef {{ * type: string, * expanded: boolean?, + * menu: boolean?, * path: Array., * value: *?, * childs: Model[]?