2015-02-04 10:46:36 +01:00
|
|
|
/*! Icinga Web 2 | (c) 2013-2015 Icinga Development Team | GPLv2+ */
|
2014-09-10 10:45:34 +02:00
|
|
|
|
|
|
|
(function(Icinga, $) {
|
|
|
|
|
|
|
|
"use strict";
|
|
|
|
|
|
|
|
var activeMenuId;
|
|
|
|
|
|
|
|
Icinga.Behaviors = Icinga.Behaviors || {};
|
|
|
|
|
|
|
|
var Navigation = function (icinga) {
|
2014-09-12 09:09:21 +02:00
|
|
|
Icinga.EventListener.call(this, icinga);
|
|
|
|
this.on('click', '#menu a', this.linkClicked, this);
|
|
|
|
this.on('click', '#menu tr[href]', this.linkClicked, this);
|
|
|
|
this.on('mouseenter', 'li.dropdown', this.dropdownHover, this);
|
|
|
|
this.on('mouseleave', 'li.dropdown', this.dropdownLeave, this);
|
2015-03-13 15:01:47 +01:00
|
|
|
this.on('mouseenter', '#menu > nav > ul > li', this.menuTitleHovered, this);
|
2014-09-12 09:09:21 +02:00
|
|
|
this.on('mouseleave', '#sidebar', this.leaveSidebar, this);
|
2015-08-17 16:54:03 +02:00
|
|
|
this.on('rendered', this.onRendered, this);
|
2014-09-10 10:45:34 +02:00
|
|
|
};
|
2014-09-12 09:09:21 +02:00
|
|
|
Navigation.prototype = new Icinga.EventListener();
|
2014-09-10 10:45:34 +02:00
|
|
|
|
2014-09-12 09:09:21 +02:00
|
|
|
Navigation.prototype.onRendered = function(evt) {
|
2015-08-17 16:54:03 +02:00
|
|
|
var self = evt.data.self;
|
2014-09-12 09:09:21 +02:00
|
|
|
// get original source element of the rendered-event
|
|
|
|
var el = evt.target;
|
2014-09-10 10:45:34 +02:00
|
|
|
if (activeMenuId) {
|
2014-10-01 16:48:38 +02:00
|
|
|
// restore old menu state
|
2014-11-14 11:58:29 +01:00
|
|
|
$('#menu li.active', el).removeClass('active');
|
2014-09-12 15:01:25 +02:00
|
|
|
var $selectedMenu = $('#' + activeMenuId).addClass('active');
|
2014-09-10 10:45:34 +02:00
|
|
|
var $outerMenu = $selectedMenu.parent().closest('li');
|
|
|
|
if ($outerMenu.size()) {
|
2014-09-10 16:25:47 +02:00
|
|
|
$outerMenu.addClass('active');
|
2014-09-10 10:45:34 +02:00
|
|
|
}
|
2014-12-29 16:14:12 +01:00
|
|
|
|
|
|
|
/*
|
|
|
|
Recreate the html content of the menu item to force the browser to update the layout, or else
|
|
|
|
the link would only be visible as active after another click or page reload in Gecko and WebKit.
|
2015-02-03 16:27:59 +01:00
|
|
|
|
2014-12-29 16:14:12 +01:00
|
|
|
fixes #7897
|
|
|
|
*/
|
|
|
|
$selectedMenu.html($selectedMenu.html());
|
|
|
|
|
2014-09-10 10:45:34 +02:00
|
|
|
} else {
|
|
|
|
// store menu state
|
2014-11-14 11:58:29 +01:00
|
|
|
var $menus = $('#menu li.active', el);
|
2014-09-10 10:45:34 +02:00
|
|
|
if ($menus.size()) {
|
|
|
|
activeMenuId = $menus[0].id;
|
2014-10-01 16:49:30 +02:00
|
|
|
$menus.find('li.active').first().each(function () {
|
|
|
|
activeMenuId = this.id;
|
|
|
|
});
|
2014-09-10 10:45:34 +02:00
|
|
|
}
|
|
|
|
}
|
2015-08-17 16:54:03 +02:00
|
|
|
// restore hovered menu after auto-reload
|
|
|
|
if (self.hovered) {
|
|
|
|
var hovered = self.icinga.utils.getElementByDomPath(self.hovered);
|
|
|
|
if (hovered) {
|
|
|
|
self.hoverElement($(hovered));
|
|
|
|
}
|
|
|
|
}
|
2014-09-10 10:45:34 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Navigation.prototype.linkClicked = function(event) {
|
|
|
|
var $a = $(this);
|
|
|
|
var href = $a.attr('href');
|
|
|
|
var $li;
|
2015-08-17 16:54:03 +02:00
|
|
|
var self = event.data.self;
|
|
|
|
var icinga = self.icinga;
|
2014-09-10 10:45:34 +02:00
|
|
|
|
2015-08-17 16:54:03 +02:00
|
|
|
self.hovered = null;
|
2014-09-10 10:45:34 +02:00
|
|
|
if (href.match(/#/)) {
|
2014-09-10 14:21:15 +02:00
|
|
|
// ...it may be a menu section without a dedicated link.
|
|
|
|
// Switch the active menu item:
|
2014-09-10 16:25:47 +02:00
|
|
|
$li = $a.closest('li');
|
|
|
|
$('#menu .active').removeClass('active');
|
|
|
|
$li.addClass('active');
|
|
|
|
activeMenuId = $($li).attr('id');
|
|
|
|
if ($li.hasClass('hover')) {
|
|
|
|
$li.removeClass('hover');
|
2014-09-10 14:21:15 +02:00
|
|
|
}
|
|
|
|
if (href === '#') {
|
|
|
|
// Allow to access dropdown menu by keyboard
|
|
|
|
if ($a.hasClass('dropdown-toggle')) {
|
|
|
|
$a.closest('li').toggleClass('hover');
|
|
|
|
}
|
2014-09-10 16:25:47 +02:00
|
|
|
return;
|
2014-09-10 10:45:34 +02:00
|
|
|
}
|
|
|
|
} else {
|
2014-09-10 16:25:47 +02:00
|
|
|
activeMenuId = $(event.target).closest('li').attr('id');
|
2014-09-10 10:45:34 +02:00
|
|
|
}
|
2014-09-10 16:25:47 +02:00
|
|
|
// update target url of the menu container to the clicked link
|
|
|
|
var $menu = $('#menu');
|
|
|
|
var menuDataUrl = icinga.utils.parseUrl($menu.data('icinga-url'));
|
|
|
|
menuDataUrl = icinga.utils.addUrlParams(menuDataUrl.path, { url: href });
|
|
|
|
$menu.data('icinga-url', menuDataUrl);
|
2014-09-10 10:45:34 +02:00
|
|
|
};
|
|
|
|
|
2015-02-03 16:45:01 +01:00
|
|
|
Navigation.prototype.setActiveByUrl = function(url) {
|
2014-10-01 17:47:21 +02:00
|
|
|
this.resetActive();
|
|
|
|
this.setActive($('#menu [href="' + url + '"]'));
|
2015-08-17 16:54:03 +02:00
|
|
|
};
|
2014-10-01 17:47:21 +02:00
|
|
|
|
2014-09-12 15:01:25 +02:00
|
|
|
/**
|
|
|
|
* Change the active menu element
|
|
|
|
*
|
|
|
|
* @param $el {jQuery} A selector pointing to the active element
|
|
|
|
*/
|
|
|
|
Navigation.prototype.setActive = function($el) {
|
|
|
|
$el.closest('li').addClass('active');
|
|
|
|
$el.parents('li').addClass('active');
|
|
|
|
activeMenuId = $el.closest('li').attr('id');
|
|
|
|
};
|
|
|
|
|
|
|
|
Navigation.prototype.resetActive = function() {
|
|
|
|
$('#menu .active').removeClass('active');
|
|
|
|
activeMenuId = null;
|
|
|
|
};
|
|
|
|
|
2014-09-10 14:21:15 +02:00
|
|
|
Navigation.prototype.menuTitleHovered = function(event) {
|
|
|
|
var $li = $(this),
|
|
|
|
delay = 800,
|
|
|
|
self = event.data.self;
|
|
|
|
|
2015-08-17 16:54:03 +02:00
|
|
|
self.hovered = null;
|
2014-09-10 14:21:15 +02:00
|
|
|
if ($li.hasClass('active')) {
|
|
|
|
$li.siblings().removeClass('hover');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ($li.children('ul').children('li').length === 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ($('#menu').scrollTop() > 0) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ($('#layout').hasClass('hoveredmenu')) {
|
|
|
|
delay = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
setTimeout(function () {
|
2015-01-28 13:19:49 +01:00
|
|
|
try {
|
|
|
|
if (!$li.is('li:hover')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if ($li.hasClass('active')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} catch(e) { /* Bypass because if IE8 */ }
|
2014-09-10 14:21:15 +02:00
|
|
|
|
|
|
|
$li.siblings().each(function () {
|
|
|
|
var $sibling = $(this);
|
2015-01-28 13:19:49 +01:00
|
|
|
try {
|
|
|
|
if ($sibling.is('li:hover')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} catch(e) { /* Bypass because if IE8 */ };
|
2014-09-10 14:21:15 +02:00
|
|
|
if ($sibling.hasClass('hover')) {
|
|
|
|
$sibling.removeClass('hover');
|
|
|
|
}
|
|
|
|
});
|
|
|
|
self.hoverElement($li);
|
|
|
|
}, delay);
|
|
|
|
};
|
|
|
|
|
|
|
|
Navigation.prototype.leaveSidebar = function (event) {
|
|
|
|
var $sidebar = $(this),
|
|
|
|
$li = $sidebar.find('li.hover'),
|
|
|
|
self = event.data.self;
|
|
|
|
if (! $li.length) {
|
|
|
|
$('#layout').removeClass('hoveredmenu');
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
setTimeout(function () {
|
2015-01-28 13:19:49 +01:00
|
|
|
try {
|
|
|
|
if ($li.is('li:hover') || $sidebar.is('sidebar:hover')) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} catch(e) { /* Bypass because if IE8 */ };
|
2014-09-10 14:21:15 +02:00
|
|
|
$li.removeClass('hover');
|
|
|
|
$('#layout').removeClass('hoveredmenu');
|
|
|
|
}, 500);
|
2015-08-17 16:54:03 +02:00
|
|
|
self.hovered = null;
|
2014-09-10 14:21:15 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Navigation.prototype.hoverElement = function ($li) {
|
|
|
|
$('#layout').addClass('hoveredmenu');
|
|
|
|
$li.addClass('hover');
|
2015-08-17 16:54:03 +02:00
|
|
|
if ($li[0]) {
|
|
|
|
this.hovered = this.icinga.utils.getDomPath($li[0]);
|
|
|
|
} else {
|
|
|
|
this.hovered = null;
|
|
|
|
}
|
2014-09-10 14:21:15 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
Navigation.prototype.dropdownHover = function () {
|
|
|
|
$(this).addClass('hover');
|
|
|
|
};
|
|
|
|
|
|
|
|
Navigation.prototype.dropdownLeave = function (event) {
|
|
|
|
var $li = $(this),
|
|
|
|
self = event.data.self;
|
|
|
|
setTimeout(function () {
|
|
|
|
// TODO: make this behave well together with keyboard navigation
|
2015-01-28 13:19:49 +01:00
|
|
|
try {
|
|
|
|
if (!$li.is('li:hover') /*&& ! $li.find('a:focus')*/) {
|
|
|
|
$li.removeClass('hover');
|
|
|
|
}
|
|
|
|
} catch(e) { /* Bypass because if IE8 */ }
|
2014-09-10 14:21:15 +02:00
|
|
|
}, 300);
|
2015-08-17 16:54:03 +02:00
|
|
|
self.hovered = null;
|
2014-09-10 14:21:15 +02:00
|
|
|
};
|
2014-09-10 10:45:34 +02:00
|
|
|
Icinga.Behaviors.Navigation = Navigation;
|
|
|
|
|
|
|
|
}) (Icinga, jQuery);
|