166 lines
6.3 KiB
JavaScript
166 lines
6.3 KiB
JavaScript
|
|
/**
|
|
* Generic menu drilldown plugin for standard Drupal menu tree markup.
|
|
* The plugin should be inited against a DOM element that *contains*
|
|
* a Drupal ul.menu tree. Example:
|
|
*
|
|
* $('div.block-menu').drilldown('init', params);
|
|
*
|
|
* You must provide the following parameters as settings:
|
|
*
|
|
* var params = {
|
|
* activePath : A drupal menu path that is currently active including the basePath e.g. "/mysite/node"
|
|
* trail : A jquery selector to the DOM element that should act as the trail container, e.g. "div.my-menu-breadcrumb-trail"
|
|
* rootTitle : The title to use for the root menu item if the menu does not already possess one. Optional.
|
|
* }
|
|
*
|
|
*/
|
|
(function($) {
|
|
$.fn.drilldown = function(method, settings) {
|
|
var menu = this;
|
|
var activePath;
|
|
var rootTitle = settings.rootTitle || 'Home';
|
|
|
|
switch (method) {
|
|
case 'goTo':
|
|
// If the passed link refers to the current page, don't follow through
|
|
// the link.
|
|
if (this.activePath && this.activePath === $(settings.activeLink).attr('href')) {
|
|
return false;
|
|
}
|
|
return true;
|
|
case 'setActive':
|
|
var breadcrumb = [];
|
|
var activeMenu;
|
|
|
|
$(settings.activeLink).each(function() {
|
|
// Traverse backwards through menu parents and build breadcrumb array.
|
|
$(this).parents('ul.menu').each(function() {
|
|
if ($(this).parents('ul.menu').size() > 0) {
|
|
$(this).siblings('a').each(function() {
|
|
breadcrumb.unshift($(this));
|
|
});
|
|
}
|
|
// If this is a root menu with no root link to accompany it,
|
|
// generate one such that the breadcrumb may reference it.
|
|
else if ($(this).children('li').size() > 1) {
|
|
var root;
|
|
if ($(this).siblings('a.drilldown-root').size() > 0) {
|
|
root = $(this).siblings('a.drilldown-root');
|
|
}
|
|
else {
|
|
root = $('<a href="#" class="drilldown-root" style="display:none">'+rootTitle+'</a>');
|
|
$(this).before(root);
|
|
}
|
|
breadcrumb.unshift(root);
|
|
}
|
|
});
|
|
|
|
// If we have a child menu (actually a sibling in the DOM), use it
|
|
// as the active menu. Otherwise treat our direct parent as the
|
|
// active menu.
|
|
if ($(this).next().is('ul.menu')) {
|
|
activeMenu = $(this).next();
|
|
breadcrumb.push($(this));
|
|
}
|
|
else {
|
|
activeMenu = $(this).parents('ul.menu').eq(0);
|
|
}
|
|
if (activeMenu) {
|
|
$('.drilldown-active-trail', menu).removeClass('drilldown-active-trail');
|
|
$('ul.menu', menu).removeClass('drilldown-active-menu').removeClass('clearfix');
|
|
$(activeMenu)
|
|
.addClass('drilldown-active-menu').addClass('clearfix')
|
|
.parents('li').addClass('drilldown-active-trail').show();
|
|
}
|
|
});
|
|
|
|
// Render the breadcrumb to the target DOM object
|
|
if (breadcrumb.length > 0) {
|
|
var trail = $(settings.trail);
|
|
trail.empty();
|
|
for (var key in breadcrumb) {
|
|
if (breadcrumb[key]) {
|
|
// We don't use the $().clone() method here because of an
|
|
// IE & jQuery 1.2 bug.
|
|
var clone = $('<a></a>')
|
|
.attr('href', $(breadcrumb[key]).attr('href'))
|
|
.attr('class', $(breadcrumb[key]).attr('class'))
|
|
.html($(breadcrumb[key]).html())
|
|
.addClass('depth-'+key)
|
|
.appendTo(trail);
|
|
|
|
// We add a reference to the original link and a click handler
|
|
// that traces back to that instance to set as the active link.
|
|
$('a.depth-'+key, trail)
|
|
.data('original', $(breadcrumb[key]))
|
|
.click(function() {
|
|
settings.activeLink = $(this).data('original');
|
|
// If the clicked link does not reference the current
|
|
// active menu, set it to be active.
|
|
if (settings.activeLink.siblings('ul.drilldown-active-menu').size() === 0) {
|
|
menu.drilldown('setActive', settings);
|
|
return false;
|
|
}
|
|
// Otherwise, pass-through and allow the link to be clicked.
|
|
return menu.drilldown('goTo', settings);
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
// Event in case others need to update themselves when a new active
|
|
// link is set.
|
|
$(menu).trigger('refresh.drilldown');
|
|
break;
|
|
case 'init':
|
|
if ($('ul.menu ul.menu', menu).size() > 0) {
|
|
$(menu).addClass('drilldown');
|
|
$(settings.trail).addClass('drilldown-trail');
|
|
|
|
// Set initial active menu state.
|
|
var activeLink;
|
|
$('ul.menu a', menu).removeClass('active');
|
|
if (settings.activePath && $('ul.menu a[href="'+settings.activePath+'"]', menu).size() > 0) {
|
|
this.activePath = settings.activePath;
|
|
activeLink = $('ul.menu a[href="'+settings.activePath+'"]', menu).addClass('active');
|
|
}
|
|
if (!activeLink) {
|
|
activeLink = $('ul.menu a.active', menu).size() ? $('ul.menu a.active', menu) : $('ul.menu > li > a', menu);
|
|
}
|
|
if (activeLink) {
|
|
menu.drilldown('setActive', {
|
|
activeLink: $(activeLink[0]),
|
|
trail: settings.trail,
|
|
rootTitle: rootTitle
|
|
});
|
|
}
|
|
|
|
// Attach click handlers to menu items
|
|
$('ul.menu li:has(ul.menu)', this).click(function() {
|
|
if ($(this).parent().is('.drilldown-active-menu')) {
|
|
if (menu.data('disableMenu')) {
|
|
return true;
|
|
}
|
|
else {
|
|
var url = $(this).children('a').attr('href');
|
|
var activeLink = $('ul.menu a[href="'+url+'"]', menu);
|
|
menu.drilldown('setActive', {
|
|
activeLink: activeLink,
|
|
trail: settings.trail,
|
|
rootTitle: rootTitle
|
|
});
|
|
return false;
|
|
}
|
|
}
|
|
});
|
|
$('ul.menu li:has(ul.menu) a', menu).click(function() {
|
|
menu.data('disableMenu', true);
|
|
});
|
|
}
|
|
break;
|
|
}
|
|
return this;
|
|
};
|
|
})(jQuery);
|