From b56eb7b66952169c6d68a1d1d780a3e67e5c0f2a Mon Sep 17 00:00:00 2001 From: Matthias Jentsch Date: Wed, 4 Feb 2015 17:57:31 +0100 Subject: [PATCH] Fix keyboard navigation Store current focus position before reload and apply it after rendering. fixes #8350 --- public/js/icinga/events.js | 3 -- public/js/icinga/loader.js | 9 ++++-- public/js/icinga/utils.js | 62 ++++++++++++++++++++++++++++++++++++++ 3 files changed, 68 insertions(+), 6 deletions(-) diff --git a/public/js/icinga/events.js b/public/js/icinga/events.js index 9ae61148b..7bcbc8e3b 100644 --- a/public/js/icinga/events.js +++ b/public/js/icinga/events.js @@ -74,9 +74,6 @@ } }); - if (document.activeElement === document.body) { - $('input.autofocus', el).focus(); - } var searchField = $('#menu input.search', el); // Remember initial search field value if any if (searchField.length && searchField.val().length) { diff --git a/public/js/icinga/loader.js b/public/js/icinga/loader.js index d71c1d19f..6a82a6ee5 100644 --- a/public/js/icinga/loader.js +++ b/public/js/icinga/loader.js @@ -672,7 +672,7 @@ // Container update happens here var scrollPos = false; var self = this; - var origFocus = document.activeElement; + var origFocus = self.icinga.utils.getDomPath(document.activeElement); var containerId = $container.attr('id'); if (typeof containerId !== 'undefined') { if (autorefresh) { @@ -737,8 +737,11 @@ } this.icinga.ui.assignUniqueContainerIds(); - if (origFocus) { - $(origFocus).focus(); + console.log(origFocus); + if (origFocus.length == origFocus[0] !== '') { + setTimeout(function() { + $(self.icinga.utils.getElementByDomPath(origFocus)).focus(); + }, 0); } // TODO: this.icinga.events.refreshContainer(container); diff --git a/public/js/icinga/utils.js b/public/js/icinga/utils.js index bdde78ada..bd64e586e 100644 --- a/public/js/icinga/utils.js +++ b/public/js/icinga/utils.js @@ -233,6 +233,68 @@ return !(at > (bt + bh) || bt > (at + ah)) && !(bl > (al + aw) || al > (bl + bw)); }, + /** + * Create a selector that can be used to fetch the element the same position in the DOM-Tree + * + * Create the path to the given element in the DOM-Tree, comparable to an X-Path. Climb the + * DOM tree upwards until an element with an unique ID is found, this id is used as the anchor, + * all other elements will be addressed by their position in the parent. + * + * @param {HTMLElement} el The element to extract the path for. + * + * @returns {Array} The path of the element, that can be passed to getElementByPath + */ + getDomPath: function (el) { + if (! el) { + return []; + } + if (el.id !== '') { + return ['#' + el.id]; + } + if (el === document.body) { + return ['body']; + } + + var siblings = el.parentNode.childNodes; + var index = 0; + for (var i = 0; i < siblings.length; i ++) { + if (siblings[i].nodeType === 1) { + index ++; + } + + if (siblings[i] === el) { + var p = this.getDomPath(el.parentNode); + p.push(':nth-child(' + (index) + ')'); + return p; + } + } + }, + + /** + * Climbs up the given dom path and returns the element + * + * This is the counterpart + * + * @param path {Array} The selector + * @returns {HTMLElement} The corresponding element + */ + getElementByDomPath: function (path) { + var $element; + $.each(path, function (i, selector) { + if (! $element) { + $element = $(selector); + } else { + console.log(selector); + $element = $element.children(selector).first(); + if (! $element[0]) { + console.log("element not existing stopping..."); + return false; + } + } + }); + return $element[0]; + }, + /** * Cleanup */