From 55521bf880126fc346f7b36d39fe26a799462c3b Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Fri, 28 Aug 2015 14:16:27 +0200 Subject: [PATCH 1/3] Add support for anchors in the main url refs #9844 --- public/js/icinga/history.js | 41 +++++++++++++++++++++++++++++++++++-- 1 file changed, 39 insertions(+), 2 deletions(-) diff --git a/public/js/icinga/history.js b/public/js/icinga/history.js index 9af58980f..4599ea9c9 100644 --- a/public/js/icinga/history.js +++ b/public/js/icinga/history.js @@ -187,9 +187,13 @@ ).addToHistory = false; } - if (document.location.hash && document.location.hash.match(/^#!/)) { + if (this.getPaneAnchor(0)) { + $('#col1').data('icingaUrl', $('#col1').data('icingaUrl') + '#' + this.getPaneAnchor(0)); + } - parts = document.location.hash.split(/#!/); + var hash = this.getPaneFragment(); + if (hash && hash.match(/^#!/)) { + parts = hash.split(/#!/); if ($('#layout > #login').length) { // We are on the login page @@ -215,6 +219,39 @@ } }, + /** + * Get the state of the selected pane + * + * @param col {int} The column index 0 or 1 + * + * @returns {String} The string representing the state + */ + getPaneAnchor: function (col) { + if (col !== 1 && col !== 0) { + throw 'Trying to get anchor for non-existing column: ' + col; + } + var panes = document.location.toString().split('#!')[col]; + return panes && panes.split('#')[1]; + }, + + /** + * Get the side-pane state fragment after (and including) the #! + * + * @returns {String} The pane url containing the '#!' + */ + getPaneFragment: function () { + var hash = document.location.hash; + if (hash) { + if (hash.match(/^#[^!]/)) { + var hashs = hash.split('#'); + hashs.shift(); + hashs.shift(); + hash = '#' + hashs.join('#'); + } + } + return hash; + }, + /** * Cleanup */ From 8e554684af6043b6a584d308894f3ac0ac38f051 Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Thu, 10 Sep 2015 16:49:18 +0200 Subject: [PATCH 2/3] Fix multi-selection in combination with anchors refs #9844 --- public/js/icinga/behavior/actiontable.js | 11 +++++------ public/js/icinga/history.js | 24 ++++++++++++++++++------ 2 files changed, 23 insertions(+), 12 deletions(-) diff --git a/public/js/icinga/behavior/actiontable.js b/public/js/icinga/behavior/actiontable.js index 48d214836..3fde04732 100644 --- a/public/js/icinga/behavior/actiontable.js +++ b/public/js/icinga/behavior/actiontable.js @@ -261,10 +261,10 @@ */ refresh: function() { this.clear(); - var hash = this.icinga.utils.parseUrl(window.location.href).hash; + var hash = icinga.history.getCol2State().replace(/^#!/, ''); if (this.hasMultiselection()) { var query = parseSelectionQuery(hash); - if (query.length > 1 && this.getMultiselectionUrl() === this.icinga.utils.parseUrl(hash.substr(1)).path) { + if (query.length > 1 && this.getMultiselectionUrl() === this.icinga.utils.parseUrl(hash).path) { // select all rows with matching filters var self = this; $.each(query, function(i, selection) { @@ -275,7 +275,7 @@ return; } } - this.selectUrl(hash.substr(1)); + this.selectUrl(hash); } }; @@ -348,13 +348,12 @@ } // update history - var url = self.icinga.utils.parseUrl(window.location.href.split('#')[0]); + var state = icinga.history.getCol1State(); var count = table.selections().length; - var state = url.path + url.query; if (count > 0) { var query = table.toQuery(); self.icinga.loader.loadUrl(query, self.icinga.events.getLinkTargetFor($tr)); - state += '#!' + query; + state += '#!' + query; } else { if (self.icinga.events.getLinkTargetFor($tr).attr('id') === 'col2') { self.icinga.ui.layout1col(); diff --git a/public/js/icinga/history.js b/public/js/icinga/history.js index 4599ea9c9..cefbccf56 100644 --- a/public/js/icinga/history.js +++ b/public/js/icinga/history.js @@ -191,7 +191,7 @@ $('#col1').data('icingaUrl', $('#col1').data('icingaUrl') + '#' + this.getPaneAnchor(0)); } - var hash = this.getPaneFragment(); + var hash = this.getCol2State(); if (hash && hash.match(/^#!/)) { parts = hash.split(/#!/); @@ -231,15 +231,15 @@ throw 'Trying to get anchor for non-existing column: ' + col; } var panes = document.location.toString().split('#!')[col]; - return panes && panes.split('#')[1]; + return panes && panes.split('#')[1] || ''; }, /** - * Get the side-pane state fragment after (and including) the #! + * Get the side pane state after (and including) the #! * - * @returns {String} The pane url containing the '#!' + * @returns {string} The pane url */ - getPaneFragment: function () { + getCol2State: function () { var hash = document.location.hash; if (hash) { if (hash.match(/^#[^!]/)) { @@ -249,7 +249,19 @@ hash = '#' + hashs.join('#'); } } - return hash; + return hash || ''; + }, + + /** + * Return the main pane state fragment + * + * @returns {string} The main url including anchors, without #! + */ + getCol1State: function () { + var anchor = this.getPaneAnchor(0); + var hash = window.location.pathname + window.location.search + + (anchor.length ? ('#' + anchor) : ''); + return hash || ''; }, /** From a93481c3620fee591b679f1dd4cd8709eccda35a Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Thu, 10 Sep 2015 16:53:54 +0200 Subject: [PATCH 3/3] Add missing documentation --- public/js/icinga/history.js | 20 ++++++++++++++++++++ public/js/icinga/logger.js | 2 +- 2 files changed, 21 insertions(+), 1 deletion(-) diff --git a/public/js/icinga/history.js b/public/js/icinga/history.js index cefbccf56..47f11566d 100644 --- a/public/js/icinga/history.js +++ b/public/js/icinga/history.js @@ -94,6 +94,11 @@ } }, + /** + * Push the given url as the new history state, unless the history is disabled + * + * @param {string} url The full url path, including anchor + */ pushUrl: function (url) { // No history API, no action if (!this.enabled) { @@ -102,6 +107,13 @@ this.push(url); }, + /** + * Execute the history state, preserving the current state of behaviors + * + * Used internally by the history and should not be called externally, instead use {@link pushUrl}. + * + * @param {string} url + */ push: function (url) { url = url.replace(/[\?&]?_(render|reload)=[a-z0-9]+/g, ''); if (this.lastPushUrl === url) { @@ -169,6 +181,14 @@ }); }, + /** + * Update the application containers to match the current url + * + * Read the pane url from the current URL and load the corresponding panes into containers to + * match the current history state. + * + * @param {Boolean|Null} onload Set to true when the main pane should not be updated, defaults to false + */ applyLocationBar: function (onload) { var icinga = this.icinga, main, diff --git a/public/js/icinga/logger.js b/public/js/icinga/logger.js index 1898bf2a4..8583b9f7f 100644 --- a/public/js/icinga/logger.js +++ b/public/js/icinga/logger.js @@ -100,7 +100,7 @@ }, /** - * Return the numeric identifier fot a given log level + * Return the numeric identifier for a given log level */ numericLevel: function (level) { var ret = this.logLevels[level];