Implemented `isValueEditable` and `isPropertyEditable`

This commit is contained in:
jos 2016-10-28 13:24:51 +02:00
parent 4a12eed14f
commit 8f6ddf91bc
6 changed files with 79 additions and 69 deletions

View File

@ -1,7 +1,7 @@
<!DOCTYPE HTML> <!DOCTYPE HTML>
<html> <html>
<head> <head>
<title>Custom editable fields | JSONEditor</title> <title>Read-only properties and values | JSONEditor</title>
<script src="../dist/jsoneditor.js"></script> <script src="../dist/jsoneditor.js"></script>
@ -27,26 +27,22 @@
var container = document.getElementById('jsoneditor'); var container = document.getElementById('jsoneditor');
var options = { var options = {
onEditable: function (node) { // all properties are editable except '_id' and 'name'
// node is an object like: isPropertyEditable: function (path) {
// { if (path.length === 1 && path[0] === '_id' || path[0] === 'name') {
// field: 'FIELD', return false
// value: 'VALUE',
// path: ['PATH', 'TO', 'NODE']
// }
switch (node.field) {
case '_id':
return false;
case 'name':
return {
field: false,
value: true
}
default:
return true;
} }
return true
},
// all values are editable except '_id'
isValueEditable: function (path) {
if (path.length === 1 && path[0] === '_id') {
return false
}
return true
} }
} }
@ -56,7 +52,8 @@
age: 32 age: 32
} }
var editor = jsoneditor(container, options, json) var editor = jsoneditor(container, options)
editor.set(json)
</script> </script>
</body> </body>
</html> </html>

View File

@ -114,7 +114,7 @@ export default class JSONNode extends Component {
this.renderActionMenuButton(), this.renderActionMenuButton(),
this.renderProperty(prop, data, options), this.renderProperty(prop, data, options),
this.renderSeparator(), this.renderSeparator(),
this.renderValue(data.value) this.renderValue(data.value, options)
]) ])
]) ])
} }
@ -143,35 +143,35 @@ export default class JSONNode extends Component {
} }
renderProperty (prop, data, options) { renderProperty (prop, data, options) {
if (prop !== null) { if (prop === null) {
const isIndex = typeof prop === 'number' // FIXME: pass an explicit prop isIndex
if (isIndex) { // array item
return h('div', {
class: 'jsoneditor-property jsoneditor-readonly',
spellCheck: 'false'
}, prop)
}
else { // object property
const escapedProp = escapeHTML(prop)
return h('div', {
class: 'jsoneditor-property' + (prop.length === 0 ? ' jsoneditor-empty' : ''),
contentEditable: 'true',
spellCheck: 'false',
onBlur: this.handleChangeProperty
}, escapedProp)
}
}
else {
// root node // root node
const content = JSONNode.getRootName(data, options) const rootName = JSONNode.getRootName(data, options)
return h('div', { return h('div', {
class: 'jsoneditor-property jsoneditor-readonly', class: 'jsoneditor-property jsoneditor-readonly',
spellCheck: 'false', spellCheck: 'false',
onBlur: this.handleChangeProperty onBlur: this.handleChangeProperty
}, content) }, rootName)
}
const isIndex = typeof prop === 'number' // FIXME: pass an explicit prop isIndex or editable
const editable = !isIndex && (!options.isPropertyEditable || options.isPropertyEditable(this.getPath()))
if (editable) {
const escapedProp = escapeHTML(prop)
return h('div', {
class: 'jsoneditor-property' + (prop.length === 0 ? ' jsoneditor-empty' : ''),
contentEditable: 'true',
spellCheck: 'false',
onBlur: this.handleChangeProperty
}, escapedProp)
}
else {
return h('div', {
class: 'jsoneditor-property jsoneditor-readonly',
spellCheck: 'false'
}, prop)
} }
} }
@ -179,22 +179,31 @@ export default class JSONNode extends Component {
return h('div', {class: 'jsoneditor-separator'}, ':') return h('div', {class: 'jsoneditor-separator'}, ':')
} }
renderValue (value) { renderValue (value, options) {
const escapedValue = escapeHTML(value) const escapedValue = escapeHTML(value)
const type = valueType (value) const type = valueType (value)
const itsAnUrl = isUrl(value) const itsAnUrl = isUrl(value)
const isEmpty = escapedValue.length === 0 const isEmpty = escapedValue.length === 0
return h('div', { const editable = !options.isValueEditable || options.isValueEditable(this.getPath())
class: JSONNode.getValueClass(type, itsAnUrl, isEmpty), if (editable) {
contentEditable: 'true', return h('div', {
spellCheck: 'false', class: JSONNode.getValueClass(type, itsAnUrl, isEmpty),
onBlur: this.handleChangeValue, contentEditable: 'true',
onInput: this.updateValueStyling, spellCheck: 'false',
onClick: this.handleClickValue, onBlur: this.handleChangeValue,
onKeyDown: this.handleKeyDownValue, onInput: this.updateValueStyling,
title: itsAnUrl ? JSONNode.URL_TITLE : null onClick: this.handleClickValue,
}, escapedValue) onKeyDown: this.handleKeyDownValue,
title: itsAnUrl ? JSONNode.URL_TITLE : null
}, escapedValue)
}
else {
return h('div', {
class: 'jsoneditor-readonly',
title: itsAnUrl ? JSONNode.URL_TITLE : null
}, escapedValue)
}
} }
/** /**
@ -431,6 +440,10 @@ export default class JSONNode extends Component {
return path return path
} }
isFieldEditable () {
}
/** /**
* Get the value of the target of an event, and convert it to it's type * Get the value of the target of an event, and convert it to it's type
* @param event * @param event

View File

@ -21,10 +21,6 @@ export default class TreeMode extends Component {
const data = jsonToData(this.props.data || {}, expand, []) const data = jsonToData(this.props.data || {}, expand, [])
this.state = { this.state = {
nodeOptions: {
name: null
},
data, data,
history: [data], history: [data],
@ -65,7 +61,7 @@ export default class TreeMode extends Component {
h(Node, { h(Node, {
data: state.data, data: state.data,
events: state.events, events: state.events,
options: state.nodeOptions, options: props.options,
parent: null, parent: null,
prop: null prop: null
}) })
@ -322,13 +318,9 @@ export default class TreeMode extends Component {
* @param {SetOptions} [options] * @param {SetOptions} [options]
*/ */
set (json, options = {}) { set (json, options = {}) {
const name = options && options.name || null // the root name
const data = jsonToData(json, options.expand || TreeMode.expand, [])
this.setState({ this.setState({
nodeOptions: setIn(this.state.nodeOptions, ['name'], name), data: jsonToData(json, options.expand || TreeMode.expand, []),
data,
// TODO: do we want to keep history when .set(json) is called? // TODO: do we want to keep history when .set(json) is called?
history: [], history: [],
historyIndex: 0 historyIndex: 0

View File

@ -41,6 +41,7 @@
const mode = document.getElementById('mode').value const mode = document.getElementById('mode').value
const container = document.getElementById('container') const container = document.getElementById('container')
const options = { const options = {
name: 'myObject',
onChange: function (patch, revert) { onChange: function (patch, revert) {
console.log('onChange patch=', patch, ', revert=', revert) console.log('onChange patch=', patch, ', revert=', revert)
window.patch = patch window.patch = patch
@ -74,7 +75,6 @@
'url': 'http://jsoneditoronline.org' 'url': 'http://jsoneditoronline.org'
} }
editor.set(json, { editor.set(json, {
name: 'myObject',
expand: function (path) { expand: function (path) {
return true return true
} }

View File

@ -2,6 +2,7 @@ import { h, render } from 'preact'
import CodeMode from './CodeMode' import CodeMode from './CodeMode'
import TextMode from './TextMode' import TextMode from './TextMode'
import TreeMode from './TreeMode' import TreeMode from './TreeMode'
import { compileJSONPointer, parseJSONPointer } from './jsonData'
import '!style!css!less!./jsoneditor.less' import '!style!css!less!./jsoneditor.less'
@ -29,6 +30,11 @@ function jsoneditor (container, options = {}) {
const editor = { const editor = {
isJSONEditor: true, isJSONEditor: true,
utils: {
compileJSONPointer,
parseJSONPointer
},
_container: container, _container: container,
_options: options, _options: options,
_modes: modes, _modes: modes,

View File

@ -31,17 +31,19 @@
* }} JSONPatchResult * }} JSONPatchResult
* *
* @typedef {{ * @typedef {{
* name: string?,
* mode?: 'code' | 'form' | 'text' | 'tree' | 'view', * mode?: 'code' | 'form' | 'text' | 'tree' | 'view',
* modes?: string[], * modes?: string[],
* indentation?: number | string, * indentation?: number | string,
* onChange?: function (patch: JSONPatch, revert: JSONPatch), * onChange?: function (patch: JSONPatch, revert: JSONPatch),
* onChangeText?: function (), * onChangeText?: function (),
* onChangeMode?: function (mode: string, prevMode: string), * onChangeMode?: function (mode: string, prevMode: string),
* onError?: function (err: Error) * onError?: function (err: Error),
* isPropertyEditable?: function (Path) : boolean
* isValueEditable?: function (Path) : boolean
* }} Options * }} Options
* *
* @typedef {{ * @typedef {{
* name: string?,
* expand: function (path: Path)? * expand: function (path: Path)?
* }} SetOptions * }} SetOptions
*/ */