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