Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Enable displaying a node schema type instead of its value #445

Open
wants to merge 2 commits into
base: develop
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
129 changes: 129 additions & 0 deletions examples/14_json_value_display_mode.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
<!DOCTYPE HTML>
<html>
<head>
<title>JSONEditor | JSON schema validation</title>

<link href="../dist/jsoneditor.css" rel="stylesheet" type="text/css">
<script src="../dist/jsoneditor.js"></script>

<style type="text/css">
body {
width: 600px;
font: 11pt sans-serif;
}
.jsoneditor {
width: 100%;
height: 250px;
}

table tr th {
text-align: left;
}
</style>
</head>
<body>
<h1>Value display mode</h1>
<p>
This example demonstrates the different value display modes:
<table>
<tr>
<th>value</th>
<td>displays the value of a node</td>
</tr>
<tr>
<th>schema</th>
<td>displays the schema type of a node</td>
</tr>
<tr>
<th>schema-if-null</th>
<td>displays the schema type of a node if its value is null</td>
</tr>
</table>
</p>

<h2>Value</h2>
<div class="jsoneditor" id="jsoneditor-value"></div>
<h2>Schema</h2>
<div class="jsoneditor" id="jsoneditor-schema"></div>
<h2>Schema if null</h2>
<div class="jsoneditor" id="jsoneditor-schema-if-null"></div>

<script>
var schema = {
"title": "Example Schema",
"type": "object",
"properties": {
"firstName": {
"type": "string"
},
"lastName": {
"type": "string"
},
"gender": {
"enum": ["male", "female"]
},
"age": {
"description": "Age in years",
"type": "integer",
"minimum": 0
},
"job": {
"$ref": "job"
}
},
"required": ["firstName", "lastName"]
};

var job = {
"title": "Job description",
"type": "object",
"properties": {
"company": {
"$ref": "company"
},
"role": {
"type": "string"
}
}
};
var company = {
"title": "Company description",
"$ref": "companyType"
};
var companyType = {
"title": "Company type description",
"type": "string"
};

var json = {
firstName: 'John',
lastName: null,
gender: null,
age: null,
job: {
company: null,
role: 'developer'
}
};

var options = {
schema: schema,
schemaRefs: {"job": job, "company": company, "companyType": companyType},
valueDisplayMode: 'value',
onValueDisplayModeChange: function(mode) {
console.log("onValueDisplayModeChange:", "'"+mode+"'");
},
modes: ['tree', 'view']
};

// create the editor
var editor = new JSONEditor(document.getElementById('jsoneditor-value'), options, json);

options.valueDisplayMode = 'schema';
var editor2 = new JSONEditor(document.getElementById('jsoneditor-schema'), options, json);

options.valueDisplayMode = 'schema-if-null';
var editor3 = new JSONEditor(document.getElementById('jsoneditor-schema-if-null'), options, json);
</script>
</body>
</html>
14 changes: 14 additions & 0 deletions src/css/jsoneditor.css
Original file line number Diff line number Diff line change
Expand Up @@ -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;
}
Expand Down
62 changes: 60 additions & 2 deletions src/js/JSONEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -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) {
Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);
};

/**
Expand Down Expand Up @@ -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.
Expand Down
43 changes: 42 additions & 1 deletion src/js/Node.js
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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');
}
Expand Down