diff --git a/HISTORY.md b/HISTORY.md index cbeb500..b684f31 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -15,6 +15,7 @@ https://github.com/josdejong/jsoneditor - Renamed options `change`, `editable`, `error` to respectively `onChange`, `onEditable`, and `onError`. Old options are still working and give a deprecation warning. +- Colors of values are now customizable using CSS. - JSONEditor new throws a warning in the console in case of unknown options. - Fixed #93 and #227: html codes like `&` not escaped. - Fixed #149: Memory leak when switching mode from/to `code` mode, web worker diff --git a/examples/06_custom_styling.html b/examples/06_custom_styling.html new file mode 100644 index 0000000..bc17075 --- /dev/null +++ b/examples/06_custom_styling.html @@ -0,0 +1,51 @@ + + + + JSONEditor | Custom styling + + + + + + + + + + +

+ This example demonstrates how to customize the look of JSONEditor, + the editor below has a dark theme. Note that the example isn't worked + out for the mode code. To do that, you can load and configure + a custom theme for the Ace editor. +

+ +
+ + + + diff --git a/examples/css/darktheme.css b/examples/css/darktheme.css new file mode 100644 index 0000000..3919fcd --- /dev/null +++ b/examples/css/darktheme.css @@ -0,0 +1,75 @@ +/* dark styling of the editor */ +.jsoneditor, +.jsoneditor div.menu { + border-color: #4b4b4b; +} +.jsoneditor div.menu { + background-color: #4b4b4b; +} +.jsoneditor div.tree, +.jsoneditor textarea.text { + background-color: #666666; + color: #ffffff; +} +.jsoneditor .field, +.jsoneditor .value { + color: #ffffff; +} +.jsoneditor .search .frame { + background: #808080; +} + +.jsoneditor tr.highlight { + background-color: #808080; +} + +.jsoneditor .field[contenteditable=true]:focus, +.jsoneditor .field[contenteditable=true]:hover, +.jsoneditor .value[contenteditable=true]:focus, +.jsoneditor .value[contenteditable=true]:hover, +.jsoneditor .field.highlight, +.jsoneditor .value.highlight { + background-color: #808080; + border-color: #808080; +} + +.jsoneditor .field.highlight-active, +.jsoneditor .field.highlight-active:focus, +.jsoneditor .field.highlight-active:hover, +.jsoneditor .value.highlight-active, +.jsoneditor .value.highlight-active:focus, +.jsoneditor .value.highlight-active:hover { + background-color: #b1b1b1; + border-color: #b1b1b1; +} + +.jsoneditor div.tree button:focus { + background-color: #868686; +} + +/* coloring of JSON in tree mode */ +.jsoneditor .readonly { + color: #acacac; +} +.jsoneditor .separator { + color: #acacac; +} +.jsoneditor .value.string { + color: #00ff88; +} +.jsoneditor .value.object, +.jsoneditor .value.array { + color: #bababa; +} +.jsoneditor .value.number { + color: #ff4040; +} +.jsoneditor .value.boolean { + color: #ff8048; +} +.jsoneditor .value.null { + color: #49a7fc; +} +.jsoneditor .value.invalid { + color: white; +} diff --git a/src/css/jsoneditor.css b/src/css/jsoneditor.css index 4b0a916..ac6fdb2 100644 --- a/src/css/jsoneditor.css +++ b/src/css/jsoneditor.css @@ -54,7 +54,7 @@ .jsoneditor a.value.url:hover, .jsoneditor a.value.url:focus { - color: red; + color: #ee422e; } .jsoneditor .separator { @@ -85,6 +85,34 @@ border-radius: 2px; } +.jsoneditor .value.string { + color: #008000; +} + +.jsoneditor .value.object, +.jsoneditor .value.array { + min-width: 16px; + color: #808080; +} + +.jsoneditor .value.number { + color: #ee422e; +} + +.jsoneditor .value.boolean { + color: #ff8c00; +} + +.jsoneditor .value.null { + color: #004ED0; +} + +.jsoneditor .value.invalid { + color: #000000; +} + + + .jsoneditor div.tree button { width: 24px; height: 24px; @@ -188,6 +216,7 @@ -webkit-box-sizing: border-box; box-sizing: border-box; + outline-width: 0; border: none; background-color: white; resize: none; diff --git a/src/css/searchbox.css b/src/css/searchbox.css index 9c70be1..a2f5ec5 100644 --- a/src/css/searchbox.css +++ b/src/css/searchbox.css @@ -29,6 +29,7 @@ border: none; outline: none; margin: 1px; + line-height: 20px; } .jsoneditor .search .results { diff --git a/src/js/Node.js b/src/js/Node.js index e05bb8f..4cac286 100644 --- a/src/js/Node.js +++ b/src/js/Node.js @@ -1023,79 +1023,44 @@ Node.prototype._getDomValue = function(silent) { Node.prototype._updateDomValue = function () { var domValue = this.dom.value; if (domValue) { - // set text color depending on value type - // TODO: put colors in css - var v = this.value; - var t = (this.type == 'auto') ? util.type(v) : this.type; - var isUrl = (t == 'string' && util.isUrl(v)); - var color = ''; - if (isUrl && !this.editable.value) { // TODO: when to apply this? - color = ''; - } - else if (t == 'string') { - color = 'green'; - } - else if (t == 'number') { - color = 'red'; - } - else if (t == 'boolean') { - color = 'darkorange'; - } - else if (this._hasChilds()) { - color = ''; - } - else if (v === null) { - color = '#004ED0'; // blue - } - else { - // invalid value - color = 'black'; - } - domValue.style.color = color; + var classNames = ['value']; - // make background color light-gray when empty + + // 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(type); + if (isUrl) { + classNames.push('url'); + } + + // visual styling when empty var isEmpty = (String(this.value) == '' && this.type != 'array' && this.type != 'object'); if (isEmpty) { - util.addClassName(domValue, 'empty'); - } - else { - util.removeClassName(domValue, 'empty'); - } - - // underline url - if (isUrl) { - util.addClassName(domValue, 'url'); - } - else { - util.removeClassName(domValue, 'url'); - } - - // update title - if (t == 'array' || t == 'object') { - var count = this.childs ? this.childs.length : 0; - domValue.title = this.type + ' containing ' + count + ' items'; - } - else if (t == 'string' && util.isUrl(v)) { - if (this.editable.value) { - domValue.title = 'Ctrl+Click or Ctrl+Enter to open url in new window'; - } - } - else { - domValue.title = ''; + classNames.push('empty'); } // highlight when there is a search result if (this.searchValueActive) { - util.addClassName(domValue, 'highlight-active'); - } - else { - util.removeClassName(domValue, 'highlight-active'); + classNames.push('highlight-active'); } if (this.searchValue) { - util.addClassName(domValue, 'highlight'); + classNames.push('highlight'); + } + + domValue.className = classNames.join(' '); + + // update title + if (type == 'array' || type == 'object') { + var count = this.childs ? this.childs.length : 0; + domValue.title = this.type + ' containing ' + count + ' items'; + } + else if (isUrl && this.editable.value) { + domValue.title = 'Ctrl+Click or Ctrl+Enter to open url in new window'; } else { - util.removeClassName(domValue, 'highlight'); + domValue.title = ''; } // strip formatting from the contents of the editable div @@ -1653,19 +1618,16 @@ Node.prototype._createDomValue = function () { if (this.type == 'array') { domValue = document.createElement('div'); - domValue.className = 'readonly'; domValue.innerHTML = '[...]'; } else if (this.type == 'object') { domValue = document.createElement('div'); - domValue.className = 'readonly'; domValue.innerHTML = '{...}'; } else { if (!this.editable.value && util.isUrl(this.value)) { // create a link in case of read-only editor and value containing an url domValue = document.createElement('a'); - domValue.className = 'value'; domValue.href = this.value; domValue.target = '_blank'; domValue.innerHTML = this._escapeHTML(this.value); @@ -1675,7 +1637,6 @@ Node.prototype._createDomValue = function () { domValue = document.createElement('div'); domValue.contentEditable = this.editable.value; domValue.spellcheck = false; - domValue.className = 'value'; domValue.innerHTML = this._escapeHTML(this.value); } } diff --git a/test/test_build.html b/test/test_build.html index 99738b6..c3aacd6 100644 --- a/test/test_build.html +++ b/test/test_build.html @@ -59,7 +59,8 @@ "null": null, "number": 123, "object": {"a": "b", "c": "d"}, - "string": "Hello World" + "string": "Hello World", + "url": "http://jsoneditoronline.org" }; editor = new JSONEditor(container, options, json);