From 8bc84a5f9e9173094a133f4339f2628eede44381 Mon Sep 17 00:00:00 2001 From: Johannes Meyer Date: Thu, 16 Jan 2020 13:45:10 +0100 Subject: [PATCH] js: Teach the url parsing a final lesson about query strings `utils.parseParams()` now returns an array instead of an object. This may require some changes in modules using this directly or by `utils.parseUrl().params` refs #4056 --- public/js/icinga/behavior/actiontable.js | 7 +- public/js/icinga/loader.js | 2 +- public/js/icinga/utils.js | 111 ++++++++++++++++------- 3 files changed, 82 insertions(+), 38 deletions(-) diff --git a/public/js/icinga/behavior/actiontable.js b/public/js/icinga/behavior/actiontable.js index c7d62ee32..f17e74a80 100644 --- a/public/js/icinga/behavior/actiontable.js +++ b/public/js/icinga/behavior/actiontable.js @@ -161,8 +161,11 @@ var keys = this.getMultiselectionKeys(); for (var i = 0; i < keys.length; i++) { var key = keys[i]; - if (params[key] || params[key] === null) { - tuple[key] = params[key]; + for (var j = 0; j < params.length; j++) { + if (params[j].key === key && (params[j].value || params[j].value === null)) { + tuple[key] = params[j].value; + break; + } } } return tuple; diff --git a/public/js/icinga/loader.js b/public/js/icinga/loader.js index 6b6ddb81a..35dfc5463 100644 --- a/public/js/icinga/loader.js +++ b/public/js/icinga/loader.js @@ -738,7 +738,7 @@ if (referrer.method === 'POST') { var newUrl = this.icinga.utils.parseUrl(req.url); var currentUrl = this.icinga.utils.parseUrl(req.$target.data('icingaUrl')); - if (newUrl.path === currentUrl.path && this.icinga.utils.objectsEqual(newUrl.params, currentUrl.params)) { + if (newUrl.path === currentUrl.path && this.icinga.utils.arraysEqual(newUrl.params, currentUrl.params)) { autoSubmit = true; } } diff --git a/public/js/icinga/utils.js b/public/js/icinga/utils.js index 97dd6ed92..6d5c02c6d 100644 --- a/public/js/icinga/utils.js +++ b/public/js/icinga/utils.js @@ -131,26 +131,27 @@ result = parts.path, newparams = parts.params; + // We overwrite existing params $.each(params, function (key, value) { - // We overwrite existing params - newparams[encodeURIComponent(key)] = typeof value === 'string' - ? encodeURIComponent(value) - : null; + key = encodeURIComponent(key); + value = typeof value !== 'string' || !! value ? encodeURIComponent(value) : null; + + var found = false; + for (var i = 0; i < newparams.length; i++) { + if (newparams[i].key === key) { + newparams[i].value = value; + found = true; + break; + } + } + + if (! found) { + newparams.push({ key: key, value: value }); + } }); - if (Object.keys(newparams).length) { - var queryString = '?'; - $.each(newparams, function (key, value) { - if (queryString !== '?') { - queryString += '&'; - } - - queryString += key; - if (value !== null) { - queryString += '=' + value; - } - }); - result += queryString; + if (newparams.length) { + result += '?' + this.buildQuery(newparams); } if (parts.hash.length) { @@ -166,23 +167,19 @@ result = parts.path, newparams = parts.params; - $.each(params, function (idx, key) { - delete newparams[encodeURIComponent(key)]; + $.each(params, function (_, key) { + key = encodeURIComponent(key); + + for (var i = 0; i < newparams.length; i++) { + if (typeof newparams[i].key === key) { + delete newparams[i]; + return; + } + } }); - if (Object.keys(newparams).length) { - var queryString = '?'; - $.each(newparams, function (key, value) { - if (queryString !== '?') { - queryString += '&'; - } - - queryString += key; - if (value !== null) { - queryString += '=' + value; - } - }); - result += queryString; + if (newparams.length) { + result += '?' + this.buildQuery(newparams); } if (parts.hash.length) { @@ -192,15 +189,37 @@ return result; }, + /** + * Return a query string for the given params + * + * @param {Array} params + * @return {string} + */ + buildQuery: function (params) { + var query = ''; + + for (var i = 0; i < params.length; i++) { + if (!! query) { + query += '&'; + } + + query += params[i].key; + if (params[i].value !== null) { + query += '=' + params[i].value; + } + } + + return query; + }, + /** * Parse url params */ parseParams: function (a) { - var params = {}, + var params = [], segment = a.search.replace(/^\?/,'').split('&'), len = segment.length, i = 0, - s, key, value, equalPos; @@ -219,7 +238,7 @@ value = null; } - params[key] = value; + params.push({ key: key, value: value }); } return params; @@ -416,6 +435,28 @@ }); }, + arraysEqual: function (array1, array2) { + if (array1.length !== array2.length) { + return false; + } + + var value1, value2; + for (var i = 0; i < array1.length; i++) { + value1 = array1[i]; + value2 = array2[i]; + + if (typeof value1 === 'object') { + if (typeof value2 !== 'object' || ! this.objectsEqual(value1, value2)) { + return false; + } + } else if (value1 !== value2) { + return false; + } + } + + return true; + }, + /** * Cleanup */