From d9babab497e96ebb4a3531577cd173c1a030ee14 Mon Sep 17 00:00:00 2001 From: jos Date: Mon, 21 May 2018 20:35:49 +0200 Subject: [PATCH] Limit search results to max 1000 matches --- HISTORY.md | 1 + src/js/Node.js | 25 +++++++++++++++---------- src/js/SearchBox.js | 19 +++++++++++++++---- 3 files changed, 31 insertions(+), 14 deletions(-) diff --git a/HISTORY.md b/HISTORY.md index 16d77e5..42f3ca1 100644 --- a/HISTORY.md +++ b/HISTORY.md @@ -8,6 +8,7 @@ https://github.com/josdejong/jsoneditor - Better handling of large JSON documents: - Only displays the first 100 items of large arrays, with buttons "show more" and "show all" to render more items. + - Search results are now limited to max 1000 matches. - Search does no longer expand the paths to all matches, instead it only expands the path of the current search result. - Fixed index numbers of Array items not being updated after sorting. diff --git a/src/js/Node.js b/src/js/Node.js index b3b5884..58de60e 100644 --- a/src/js/Node.js +++ b/src/js/Node.js @@ -40,6 +40,9 @@ function Node (editor, params) { // debounce interval for keyboard input in milliseconds Node.prototype.DEBOUNCE_INTERVAL = 150; +// search will stop iterating as soon as the max is reached +Node.prototype.MAX_SEARCH_RESULTS = 999; + // number of visible childs rendered initially in large arrays/objects (with a "show more" button to show more) Node.prototype.MAX_VISIBLE_CHILDS = 100; @@ -826,10 +829,14 @@ Node.prototype.insertAfter = function(node, afterNode) { * Search in this node * Searches are case insensitive. * @param {String} text + * @param {Node[]} [results] Array where search results will be added + * used to count and limit the results whilst iterating * @return {Node[]} results Array with nodes containing the search text */ -Node.prototype.search = function(text) { - var results = []; +Node.prototype.search = function(text, results) { + if (!Array.isArray(results)) { + results = []; + } var index; var search = text ? text.toLowerCase() : undefined; @@ -838,7 +845,7 @@ Node.prototype.search = function(text) { delete this.searchValue; // search in field - if (this.field !== undefined) { + if (this.field !== undefined && results.length <= this.MAX_SEARCH_RESULTS) { var field = String(this.field).toLowerCase(); index = field.indexOf(search); if (index !== -1) { @@ -859,16 +866,14 @@ Node.prototype.search = function(text) { // search the nodes childs if (this.childs) { - var childResults = []; this.childs.forEach(function (child) { - childResults = childResults.concat(child.search(text)); + child.search(text, results); }); - results = results.concat(childResults); } } else { // string, auto - if (this.value !== undefined ) { + if (this.value !== undefined && results.length <= this.MAX_SEARCH_RESULTS) { var value = String(this.value).toLowerCase(); index = value.indexOf(search); if (index !== -1) { @@ -878,10 +883,10 @@ Node.prototype.search = function(text) { 'elem': 'value' }); } - } - // update dom - this._updateDomValue(); + // update dom + this._updateDomValue(); + } } return results; diff --git a/src/js/SearchBox.js b/src/js/SearchBox.js index 192c3a7..928f916 100644 --- a/src/js/SearchBox.js +++ b/src/js/SearchBox.js @@ -230,15 +230,26 @@ SearchBox.prototype._onSearch = function (forceSearch) { // only search again when changed this.lastText = text; this.results = this.editor.search(text); + var MAX_SEARCH_RESULTS = this.results[0] + ? this.results[0].node.MAX_SEARCH_RESULTS + : Infinity; + this._setActiveResult(0, false); // display search results if (text !== undefined) { var resultCount = this.results.length; - switch (resultCount) { - case 0: this.dom.results.innerHTML = 'no results'; break; - case 1: this.dom.results.innerHTML = '1 result'; break; - default: this.dom.results.innerHTML = resultCount + ' results'; break; + if (resultCount === 0) { + this.dom.results.innerHTML = 'no results'; + } + else if (resultCount === 1) { + this.dom.results.innerHTML = '1 result'; + } + else if (resultCount > MAX_SEARCH_RESULTS) { + this.dom.results.innerHTML = MAX_SEARCH_RESULTS + '+ results'; + } + else { + this.dom.results.innerHTML = resultCount + ' results'; } } else {