diff --git a/examples/14_json_value_display_mode.html b/examples/14_json_value_display_mode.html new file mode 100644 index 000000000..1d68c1da9 --- /dev/null +++ b/examples/14_json_value_display_mode.html @@ -0,0 +1,129 @@ + + + + JSONEditor | JSON schema validation + + + + + + + +

Value display mode

+

+ This example demonstrates the different value display modes: + + + + + + + + + + + + + +
valuedisplays the value of a node
schemadisplays the schema type of a node
schema-if-nulldisplays the schema type of a node if its value is null
+

+ +

Value

+
+

Schema

+
+

Schema if null

+
+ + + + diff --git a/src/css/jsoneditor.css b/src/css/jsoneditor.css index 5d5f89888..b68f651d7 100644 --- a/src/css/jsoneditor.css +++ b/src/css/jsoneditor.css @@ -118,6 +118,20 @@ div.jsoneditor-value.jsoneditor-null { color: #004ED0; } +div.jsoneditor-value.jsoneditor-null.jsoneditor-expected-number, +div.jsoneditor-value.jsoneditor-null.jsoneditor-expected-string, +div.jsoneditor-value.jsoneditor-null.jsoneditor-expected-integer { + color: #ee422e; + font-style: italic; +} + +div.jsoneditor-value.jsoneditor-expected-number, +div.jsoneditor-value.jsoneditor-expected-string, +div.jsoneditor-value.jsoneditor-expected-integer { + color: #008000; + font-style: italic; +} + div.jsoneditor-value.jsoneditor-invalid { color: #000000; } diff --git a/src/js/JSONEditor.js b/src/js/JSONEditor.js index 9b0a33156..3820b94d3 100644 --- a/src/js/JSONEditor.js +++ b/src/js/JSONEditor.js @@ -44,6 +44,9 @@ var util = require('./util'); * {boolean} sortObjectKeys If true, object keys are * sorted before display. * false by default. + * {string} valueDisplayMode Value display type. Available values: + * 'value' (default), 'schema', + * 'schema-if-null' * @param {Object | undefined} json JSON object */ function JSONEditor (container, options, json) { @@ -81,8 +84,9 @@ function JSONEditor (container, options, json) { var VALID_OPTIONS = [ 'ajv', 'schema', 'schemaRefs','templates', 'ace', 'theme','autocomplete', - 'onChange', 'onEditable', 'onError', 'onModeChange', - 'escapeUnicode', 'history', 'search', 'mode', 'modes', 'name', 'indentation', 'sortObjectKeys' + 'onChange', 'onEditable', 'onError', 'onModeChange', 'onValueDisplayModeChange', + 'escapeUnicode', 'history', 'search', 'mode', 'modes', 'name', 'indentation', 'sortObjectKeys', + 'valueDisplayMode' ]; Object.keys(options).forEach(function (option) { @@ -132,6 +136,9 @@ JSONEditor.prototype._create = function (container, options, json) { var mode = this.options.mode || (this.options.modes && this.options.modes[0]) || 'tree'; this.setMode(mode); + + var valueDisplayMode = this.options.valueDisplayMode || 'value'; + this.setValueDisplayMode(valueDisplayMode); }; /** @@ -254,6 +261,57 @@ JSONEditor.prototype.getMode = function () { return this.options.mode; }; +/** + * Change the value display mode of the editor. + * JSONEditor will be extended with all methods needed for the chosen mode. + * @param {String} mode Available modes: 'value' (default), 'schema', 'schema-if-null'. + */ +JSONEditor.prototype.setValueDisplayMode = function (valueDisplayMode) { + var container = this.container; + var options = util.extend({}, this.options); + var oldMode = options.valueDisplayMode; + var data; + var name; + + options.valueDisplayMode = valueDisplayMode; + var config = JSONEditor.modes[this.options.mode]; + if (config) { + try { + if (typeof config.load === 'function') { + try { + config.load.call(this); + } + catch (err) { + console.error(err); + } + } + + if (typeof options.onValueDisplayModeChange === 'function' && valueDisplayMode !== oldMode) { + try { + options.onValueDisplayModeChange(valueDisplayMode, oldMode); + } + catch (err) { + console.error(err); + } + } + } + catch (err) { + this._onError(err); + } + } + else { + throw new Error('Unknown value display mode "' + options.valueDisplayMode + '"'); + } +}; + +/** + * Get the current value display mode + * @return {string} + */ +JSONEditor.prototype.getValueDisplayMode = function () { + return this.options.valueDisplayMode; +}; + /** * Throw an error. If an error callback is configured in options.error, this * callback will be invoked. Else, a regular error is thrown. diff --git a/src/js/Node.js b/src/js/Node.js index f7a077ac6..af8845ae4 100644 --- a/src/js/Node.js +++ b/src/js/Node.js @@ -1205,6 +1205,36 @@ Node.prototype._onChangeField = function () { this.previousField = this.field; }; +/** + * Find schema reference in the editor options (recursively if necessary) + * @private + * @param {string} [reference] schema ref for which we're looking for the type + * @return {string} Returns the schema type for the schema ref + */ +Node.prototype._findSchemaRef = function (reference) { + var ref = this.editor.options.schemaRefs[reference]; + if (ref) { + if (!ref.type && ref.$ref) { + return this._findSchemaRef(ref.$ref); + } + if (ref.type === 'object') { + if (ref.properties && ref.properties[this.field]) { + if (ref.properties[this.field].type) { + return ref.properties[this.field].type; + } + if (ref.properties[this.field].$ref) { + return this._findSchemaRef(ref.properties[this.field].$ref); + } + } + // console.warn('Could not find schema ref', reference); + return undefined; + } + return ref.type; + } + console.warn('Schema ref %s undefined', reference); + return undefined; +}; + /** * Update dom value: * - the text color of the value, depending on the type of the value @@ -1217,12 +1247,23 @@ Node.prototype._updateDomValue = function () { if (domValue) { var classNames = ['jsoneditor-value']; - // set text color depending on value type var value = this.value; var type = (this.type == 'auto') ? util.type(value) : this.type; var isUrl = type == 'string' && util.isUrl(value); classNames.push('jsoneditor-' + type); + if (this.schema && (this.editor.options.valueDisplayMode === 'schema' || this.editor.options.valueDisplayMode === 'schema-if-null')) { + if (type === 'null' || this.editor.options.valueDisplayMode === 'schema') { + var schemaType = this.schema.type; + if (!schemaType && this.schema.$ref) { + schemaType = this._findSchemaRef(this.schema.$ref); + } + if (schemaType) { + classNames.push('jsoneditor-expected-' + schemaType); + domValue.textContent = schemaType; + } + } + } if (isUrl) { classNames.push('jsoneditor-url'); }