diff --git a/src/css/statusbar.css b/src/css/statusbar.css index 57ea374..c7bce4f 100644 --- a/src/css/statusbar.css +++ b/src/css/statusbar.css @@ -29,10 +29,12 @@ div.jsoneditor-statusbar > .jsoneditor-validation-error-icon { padding: 0; margin-top: 1px; background: url("img/jsoneditor-icons.svg") -168px -48px; + cursor: pointer; } div.jsoneditor-statusbar > .jsoneditor-validation-error-count { float: right; margin: 0 4px 0 0; + cursor: pointer; } div.jsoneditor-statusbar > .jsoneditor-parse-error-icon { float: right; diff --git a/src/js/textmode.js b/src/js/textmode.js index 59eb583..e9ba2f0 100644 --- a/src/js/textmode.js +++ b/src/js/textmode.js @@ -95,6 +95,11 @@ textmode.create = function (container, options) { this.validateSchema = null; this.validationSequence = 0; this.annotations = []; + /** + * Visibility of validation error table + * @type {Boolean|undefined} undefined means default behavior for mode + */ + this.errorTableVisible = undefined; // create a debounced validate function this._debouncedValidate = util.debounce(this.validate.bind(this), this.DEBOUNCE_INTERVAL); @@ -794,7 +799,7 @@ textmode.validate = function () { } } else { - this._renderErrors(parseErrors || []); + this._renderErrors(parseErrors || [], true); } }; @@ -847,11 +852,13 @@ textmode._validateCustom = function (json) { return Promise.resolve(null); }; -textmode._renderErrors = function(errors) { +textmode._renderErrors = function(errors, noValidation) { // clear all current errors var me = this; var validationErrorsCount = 0; + this.errorTableVisible = (typeof this.errorTableVisible === 'undefined') ? !this.aceEditor : this.errorTableVisible; + if (this.dom.validationErrors) { this.dom.validationErrors.parentNode.removeChild(this.dom.validationErrors); this.dom.validationErrors = null; @@ -891,8 +898,11 @@ textmode._renderErrors = function(errors) { }); this._refreshAnnotations(); - } else { - var validationErrors = document.createElement('div'); + } + + // keep default behavior for parse errors + if (noValidation ? !this.aceEditor : this.errorTableVisible) { + var validationErrors = document.createElement('div'); validationErrors.innerHTML = '
'; var tbody = validationErrors.getElementsByTagName('tbody')[0]; @@ -955,7 +965,10 @@ textmode._renderErrors = function(errors) { var height = this.dom.validationErrorsContainer.clientHeight + (this.dom.statusBar ? this.dom.statusBar.clientHeight : 0); this.content.style.marginBottom = (-height) + 'px'; this.content.style.paddingBottom = height + 'px'; + } else { + validationErrorsCount = errors.reduce(function (acc, curr) {return (curr.type === 'validation' ? ++acc: acc)}, 0); } + } else { if (this.aceEditor) { this.annotations = []; @@ -971,6 +984,7 @@ textmode._renderErrors = function(errors) { if (showIndication) { this.validationErrorIndication.validationErrorCount.innerText = validationErrorsCount; this.validationErrorIndication.validationErrorIcon.title = validationErrorsCount + ' schema validation error(s) found'; + this.validationErrorIndication.validationErrorCount.onclick = this.validationErrorIndication.validationErrorIcon.onclick = this._toggleErrorTableVisibility.bind(this); } } @@ -981,6 +995,11 @@ textmode._renderErrors = function(errors) { } }; +textmode._toggleErrorTableVisibility = function () { + this.errorTableVisible = !this.errorTableVisible; + this.validate(); +}; + /** * Get the selection details * @returns {{start:{row:Number, column:Number},end:{row:Number, column:Number},text:String}} @@ -1085,6 +1104,7 @@ textmode.setTextSelection = function (startPos, endPos) { } }; this.aceEditor.selection.setRange(range); + this.aceEditor.scrollToLine(startPos.row - 1, true); } };