Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
175 changes: 175 additions & 0 deletions examples/20_custom_css_style_for_nodes.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,175 @@
<!DOCTYPE HTML>
<html>
<head>
<meta http-equiv="Content-Type" content="text/html;charset=utf-8">

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

<style type="text/css">
body {
font: 10.5pt arial;
color: #4d4d4d;
line-height: 150%;
width: 500px;
padding-left: 40px;
}

code {
background-color: #f5f5f5;
}

#containerLeft {
width: 500px;
height: 500px;
float: left;
}
#containerRight {
width: 500px;
height: 500px;
float: right;
}
#wrapper {
width: 1000px;
}
#containerRight .different_element {
background-color: greenyellow !important;
}
#containerLeft .different_element {
background-color: violet !important;
}
</style>
</head>
<body>

<p>
JSON Diff
</p>
<div id="wrapper">
<div id="containerLeft"></div>
<div id="containerRight"></div>
</div>

<script>
var containerLeft, containerRight, options, json;

containerLeft = document.getElementById('containerLeft');
containerRight = document.getElementById('containerRight');

function findNodeInJson(json, path){
if(!json || path.length ===0) {
return {field: undefined, value: undefined}
}
var first = path[0];
var remainingPath = path.slice(1);

if(remainingPath.length === 0) {
return {field: (typeof json[first] !== undefined ? first : undefined), value: json[first]};
} else {
return findNodeInJson(json[first], remainingPath)
}

}

optionsLeft = {
mode: 'tree',
modes: ['code', 'form', 'text', 'tree', 'view'], // allowed modes
onError: function (err) {
alert(err.toString());
},
onClassName: function({ path, field, value }) {
var thisNode = findNodeInJson(jsonLeft, path);
var oppositeNode = findNodeInJson(jsonRight, path);

// this is not a proper way of comparing objects/values but's it's good enough for this example
var isValueEqual = thisNode.value == oppositeNode.value;

if(Array.isArray(thisNode.value) && Array.isArray(oppositeNode.value)) {
isValueEqual = thisNode.value.every(function (e) {
return oppositeNode.value.includes(e);
})
}

if (thisNode.field === oppositeNode.field && isValueEqual) {
return 'the_same_element';
} else {
return 'different_element'
}
},
onChangeJSON: function (j) {
jsonLeft = j;
window.editorRight.refresh()
}
};

optionsRight = {
mode: 'tree',
modes: ['code', 'form', 'text', 'tree', 'view'], // allowed modes
// name: "jsonContent",
onError: function (err) {
alert(err.toString());
},
onClassName: function({ path, field, value }) {

var thisNode = findNodeInJson(jsonRight, path);
var oppositeNode = findNodeInJson(jsonLeft, path);

// this is not a proper way of comparing objects/values but's it's good enough for this example
var isValueEqual = thisNode.value == oppositeNode.value;

if(Array.isArray(thisNode.value) && Array.isArray(oppositeNode.value)) {
isValueEqual = thisNode.value.every(function (e) {
return oppositeNode.value.includes(e);
})
}

if (thisNode.field === oppositeNode.field && isValueEqual) {
return 'the_same_element';
} else {
return 'different_element'
}
},
onChangeJSON: function (j) {
jsonRight = j;
window.editorLeft.refresh();
}
};

jsonLeft = {
"arrayOfArrays": [1, 2, 999, [3,4,5]],
"someField": true,
"boolean": true,
"htmlcode": '&quot;',
"escaped_unicode": '\\u20b9',
"unicode": '\u20b9,\uD83D\uDCA9',
"return": '\n',
"null": null,
"thisObjectDoesntExistOnTheRight" : {key: "value"},
"number": 123,
"object": {"a": "b","new":4, "c": "d", "e": [1, 2, 3]},
"string": "Hello World",
"url": "http://jsoneditoronline.org",
"[0]": "zero"
};

jsonRight = {
"arrayOfArrays": [1, 2, [3,4,5]],
"boolean": true,
"htmlcode": '&quot;',
"escaped_unicode": '\\u20b9',
"thisFieldDoesntExistOnTheLeft": 'foobar',
"unicode": '\u20b9,\uD83D\uDCA9',
"return": '\n',
"null": null,
"number": 123,
"object": {"a": "b", "c": "d", "e": [1, 2, 3]},
"string": "Hello World",
"url": "http://jsoneditoronline.org",
"[0]": "zero"
};

window.editorLeft = new JSONEditor(containerLeft, optionsLeft, jsonLeft);
window.editorRight = new JSONEditor(containerRight, optionsRight, jsonRight);
</script>
</body>
</html>
8 changes: 7 additions & 1 deletion src/js/JSONEditor.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,12 @@ if (typeof Promise === 'undefined') {
* Only applicable for
* modes 'form', 'tree' and
* 'view'
* {function} onClassName Callback method, triggered
* when a Node DOM is rendered. Function returns
* a css class name to be set on a node.
* Only applicable for
* modes 'form', 'tree' and
* 'view'
* {Number} maxVisibleChilds Number of children allowed for a node
* in 'tree', 'view', or 'form' mode before
* the "show more/show all" buttons appear.
Expand Down Expand Up @@ -168,7 +174,7 @@ JSONEditor.VALID_OPTIONS = [
'ace', 'theme', 'autocomplete',
'onChange', 'onChangeJSON', 'onChangeText',
'onEditable', 'onError', 'onEvent', 'onModeChange', 'onNodeName', 'onValidate',
'onSelectionChange', 'onTextSelectionChange',
'onSelectionChange', 'onTextSelectionChange', 'onClassName',
'colorPicker', 'onColorPicker',
'timestampTag',
'escapeUnicode', 'history', 'search', 'mode', 'modes', 'name', 'indentation',
Expand Down
32 changes: 29 additions & 3 deletions src/js/Node.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ function Node (editor, params) {
this.editor = editor;
this.dom = {};
this.expanded = false;

if(params && (params instanceof Object)) {
this.setField(params.field, params.fieldEditable);
if ('value' in params) {
Expand Down Expand Up @@ -913,7 +913,31 @@ Node.prototype.hideChilds = function(options) {
delete this.visibleChilds;
}
};
/**
* set custom css classes on a node
*/
Node.prototype._updateCssClassName = function () {

if(this.dom.field
&& this.editor
&& this.editor.options
&& typeof this.editor.options.onClassName ==='function'
&& this.dom.tree){
util.removeAllClassNames(this.dom.tree);
const addClasses = this.editor.options.onClassName({ path: this.getPath(), field: this.field, value: this.value }) || "";
util.addClassName(this.dom.tree, "jsoneditor-values " + addClasses);
}
}

Node.prototype.recursivelyUpdateCssClassesOnNodes = function () {
this._updateCssClassName();
if (this.childs !== 'undefined') {
var i;
for (i in this.childs) {
this.childs[i].recursivelyUpdateCssClassesOnNodes();
}
}
}

/**
* Goes through the path from the node to the root and ensures that it is expanded
Expand Down Expand Up @@ -1649,7 +1673,7 @@ Node.prototype._updateDomValue = function () {
}
if (this.searchValue) {
classNames.push('jsoneditor-highlight');
}
}

domValue.className = classNames.join(' ');

Expand Down Expand Up @@ -1820,7 +1844,7 @@ Node.prototype._deleteDomColor = function () {
*/
Node.prototype._updateDomField = function () {
var domField = this.dom.field;
if (domField) {
if (domField) {
// make backgound color lightgray when empty
var isEmpty = (String(this.field) == '' && this.parent.type != 'array');
if (isEmpty) {
Expand Down Expand Up @@ -2484,6 +2508,8 @@ Node.prototype.updateDom = function (options) {
// update field and value
this._updateDomField();
this._updateDomValue();

this._updateCssClassName();

// update childs indexes
if (options && options.updateIndexes === true) {
Expand Down
7 changes: 6 additions & 1 deletion src/js/treemode.js
Original file line number Diff line number Diff line change
Expand Up @@ -550,13 +550,18 @@ treemode._onChange = function () {
}
}

// trigger the onClassName callback
if(this.options.onClassName) {
this.node.recursivelyUpdateCssClassesOnNodes();
}

// trigger the onNodeName callback
if (this.options.onNodeName && this.node.childs) {
try {
this.node.recursivelyUpdateNodeName();
} catch (err) {
console.error("Error in onNodeName callback: ", err);
}
}
}
};

Expand Down
8 changes: 8 additions & 0 deletions src/js/util.js
Original file line number Diff line number Diff line change
Expand Up @@ -361,6 +361,14 @@ exports.addClassName = function addClassName(elem, className) {
}
};

/**
* remove all classes from the given elements style
* @param {Element} elem
*/
exports.removeAllClassNames = function removeAllClassNames(elem) {
elem.className = "";
};

/**
* add a className to the given elements style
* @param {Element} elem
Expand Down