diff --git a/examples/20_custom_css_style_for_nodes.html b/examples/20_custom_css_style_for_nodes.html
new file mode 100644
index 000000000..99a5a90fd
--- /dev/null
+++ b/examples/20_custom_css_style_for_nodes.html
@@ -0,0 +1,175 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+ JSON Diff
+
+
+
+
+
+
diff --git a/src/js/JSONEditor.js b/src/js/JSONEditor.js
index da763df47..8072d6925 100644
--- a/src/js/JSONEditor.js
+++ b/src/js/JSONEditor.js
@@ -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.
@@ -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',
diff --git a/src/js/Node.js b/src/js/Node.js
index 1a1109690..4d4405f68 100644
--- a/src/js/Node.js
+++ b/src/js/Node.js
@@ -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) {
@@ -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
@@ -1649,7 +1673,7 @@ Node.prototype._updateDomValue = function () {
}
if (this.searchValue) {
classNames.push('jsoneditor-highlight');
- }
+ }
domValue.className = classNames.join(' ');
@@ -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) {
@@ -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) {
diff --git a/src/js/treemode.js b/src/js/treemode.js
index 17a12b0b7..12bccf6de 100644
--- a/src/js/treemode.js
+++ b/src/js/treemode.js
@@ -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);
- }
+ }
}
};
diff --git a/src/js/util.js b/src/js/util.js
index b85237728..5d5fc42d3 100644
--- a/src/js/util.js
+++ b/src/js/util.js
@@ -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