Created context menu button. Some refactoring

This commit is contained in:
jos 2016-07-16 13:48:20 +02:00
parent fda4f94655
commit 37ae2111ee
6 changed files with 95 additions and 34 deletions

View File

@ -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",

11
src/ContextMenu.js Normal file
View File

@ -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...')
}
}

View File

@ -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) {

View File

@ -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)

View File

@ -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;
}

View File

@ -3,6 +3,7 @@
* @typedef {{
* type: string,
* expanded: boolean?,
* menu: boolean?,
* path: Array.<string | number>,
* value: *?,
* childs: Model[]?