/**
* @file
* Alpha menu js.
*/
var alphaMenu = alphaMenu || {};
/**
* Register Alpha menu behavior so it can act on DOM.
*/
Drupal.behaviors.alphaMenu = {
attach: function (context, settings) {
alphaMenu.init(context, settings);
}
}; // Drupal.behaviors.alphaMenu
(function ($, Drupal) {
/**
* Global menu dom element
*/
alphaMenu.menuDom = null;
/**
* Global variable to check if current device is touchable based on class generated by modernizr.js
*/
alphaMenu.tuouchDevice = $('html').hasClass('touchevents');
/**
* Global timer to detect if user left menu
*/
alphaMenu.timerBackToMenu = null;
/**
* Global variable to detect last touched menu item
*/
alphaMenu.lastTouched = null;
/**
* Global breakpoints for different device types
* Keep this up-to-date with src/scss/utils/variables/_breakpoints.scss
*/
alphaMenu.breakpoints = {
bp1: 1367,
bp2: 992,
bp3: 544
};
/**
* Media queries required for enquire.js library
*/
alphaMenu.mediaQueries = {
// Breakpoint 1 (XL): 1367+
q1: '(min-width: ' + (alphaMenu.breakpoints.bp1) + 'px)',
// Breakpoint 2 (L): 992-1366
q2: '(min-width: ' + alphaMenu.breakpoints.bp2 + 'px) and (max-width: ' + (alphaMenu.breakpoints.bp1 - 1) + 'px)',
// Breakpoint 3 (M): 544-991
q3: '(min-width: ' + alphaMenu.breakpoints.bp3 + 'px) and (max-width: ' + (alphaMenu.breakpoints.bp2 - 1) + 'px)',
// Breakpoint 4 (S): <544
q4: '(max-width: ' + (alphaMenu.breakpoints.bp3 - 1) + 'px)'
};
/**
* Attach handler.
* Will be called on any DOM changes triggered by Drupal system.
*/
alphaMenu.init = function (context, settings) {
alphaMenu.menuDom = $('.block-alpha-menu-block', context);
var $firstMenuLevel = $('> ul > li', alphaMenu.menuDom),
$secondMenuLevel = $('.second-level > ul > li', $firstMenuLevel);
alphaMenu.mobileMenuInit(context);
alphaMenu.enquiresInit(context);
alphaMenu.menuButtonsInit(context);
alphaMenu.addIndexes([$firstMenuLevel, $secondMenuLevel]);
if (alphaMenu.tuouchDevice) {
alphaMenu.applyTouchEvent();
alphaMenu.hideMenuTouch();
}
else {
alphaMenu.applyHoverLevel($firstMenuLevel);
alphaMenu.applyHoverLevel($secondMenuLevel);
alphaMenu.hideMenuHover();
}
}; // alphaMenu.init
/**
* Initialize enquires - see enquire.js library
*/
alphaMenu.enquiresInit = function (context) {
$(context).find('html').once('alpha-menu-enquire').each(function() {
enquire.register(alphaMenu.mediaQueries.q3, {match: alphaMenu.implementQ3});
enquire.register(alphaMenu.mediaQueries.q4, {match: alphaMenu.implementQ4});
});
}; // alphaMenu.enquiresInit
/**
* Implementation of media query 3
*/
alphaMenu.implementQ3 = function () {
// Hide active block in hidden section
$('.alpha-menu-buttons-list li').not('.search-button').find('.active').trigger('click');
window.setTimeout(alphaMenu.mobileMenuApplyMargin, 250);
};
/**
* Implementation of media query 4
*/
alphaMenu.implementQ4 = function () {
window.setTimeout(alphaMenu.mobileMenuApplyMargin, 250);
};
/**
* Add top margin to make header visible
*/
alphaMenu.mobileMenuApplyMargin = function () {
var height = $('#toolbar-bar').height() +
$('#header').height();
$('#mobile-menu').css({'margin-top' : height + 'px', 'height' : 'calc(100% - ' + height + 'px)'});
}; // alphaMenu.enquiresInit
/**
* Set all the menu buttons.
*/
alphaMenu.getMenuButtons = function (context) {
var $menuButtons = $('.alpha-menu-buttons-list', context),
$hiddenSection = $('#hidden-section', context);
return {
'locale': {
btn: $('.locale-button a', $menuButtons),
block: $('.block-locale-switcher-block', $hiddenSection)
},
'login': {
btn : $('.login-button a', $menuButtons),
block : $('.block-alpha-menu-login-block', $hiddenSection)
},
'search': {
btn : $('.search-button a', $menuButtons),
block : $('.block-gse-search', $hiddenSection)
}
};
}; // alphaMenu.getMenuButtons
/**
* Initialize menu buttons and block sections
*/
alphaMenu.menuButtonsInit = function (context) {
var menuButtons = alphaMenu.getMenuButtons(context);
$.each(menuButtons, function(type, el) {
el.block.prepend('<a href="#" class="close">' + Drupal.t('Close') + '</a>');
// Show block if button initially active
if (el.btn.hasClass('active')) {
el.block.show().addClass('expanded');
}
$('.close', el.block).add(el.btn).on('click', function (e) {
if (el.block.hasClass('expanded')) {
alphaMenu.sectionAnimate('slideUp', el.block, el.btn);
}
else {
alphaMenu.sectionAnimate('slideDown', el.block, el.btn);
// Close mobile menu so that only one item was opened.
if (type == 'search') {
if ($('html').hasClass('mm-opened')) {
$('#mobile-menu').data('mmenu').close();
$('.mobile-menu-toggle', context).removeClass('opened');
}
}
// Check if there is another opened block, if so - close it.
$.each(menuButtons, function(name, item) {
if (item.block.hasClass('expanded')) {
alphaMenu.sectionAnimate('slideUp', item.block, item.btn);
}
});
}
e.preventDefault();
});
});
}; // alphaMenu.menuButtonsInit
/**
* Animate hidden blocks
*/
alphaMenu.sectionAnimate = function (slide, block, btn) {
var classApply = (slide == 'slideDown') ? 'addClass' : 'removeClass';
var opacity = (slide == 'slideDown') ? 1 : 0;
block.animate({'opacity' : opacity}, 100);
block[slide](200, function () {
btn[classApply]('active');
block[classApply]('expanded');
});
}; // alphaMenu.sectionAnimate
/**
* Add indexes for all menu items and save classes "collapsed"
*/
alphaMenu.addIndexes = function (menuLevels) {
menuLevels.forEach(function (level) {
$(level).each(function(index, element) {
$(element).data('id', index);
if ($(element).hasClass('collapsed')) {
$(element).attr('data-collapsed', 'collapsed');
}
});
});
}; // alphaMenu.addIndexes
/**
* Remove all "collapsed" classes from menu
*/
alphaMenu.removeAllCollapsed = function (currentElement) {
if ($(currentElement).closest('.collapsed').length == 0) {
$('li.collapsed', alphaMenu.menuDom).removeClass('collapsed');
}
}; // alphaMenu.removeAllCollapsed
/**
* Hide menu if user left it and restore all collapsed items
*/
alphaMenu.hideMenuHover = function () {
alphaMenu.menuDom.on("mouseleave", function(e) {
alphaMenu.timerBackToMenu = setTimeout(function() {
$('li.active-trail', alphaMenu.menuDom).removeClass('active-trail');
$('li[data-collapsed]', alphaMenu.menuDom).addClass('collapsed');
}, 500);
});
}; // alphaMenu.hideMenuHover
/**
* Hide menu if user left it and restore all collapsed items
*/
alphaMenu.hideMenuTouch = function () {
$('html').on('touchstart', function(e) {
if ($(e.target).closest('ul.menu').length == 0) {
alphaMenu.lastTouched = null;
$('li.active-trail', alphaMenu.menuDom).removeClass('active-trail');
$('li[data-collapsed]', alphaMenu.menuDom).addClass('collapsed');
}
});
}; // alphaMenu.hideMenuTouch
/**
* Processing desktop menu levels for touch devices
*/
alphaMenu.applyTouchEvent = function () {
$('li.drop-down', alphaMenu.menuDom).find('> a, .nolink').on("touchstart", function (e) {
var $link = $(this),
$linkParent = $link.parent();
if (alphaMenu.lastTouched == null) {
alphaMenu.lastTouched = $linkParent;
alphaMenu.lastTouched.addClass('active-trail');
alphaMenu.removeAllCollapsed(e.currentTarget);
e.preventDefault();
return false; //extra, and to make sure the function has consistent return points
}
else if ($link.is('.nolink') && $link.closest('li.active-trail').length != 0) {
$linkParent.addClass('active-trail');
$linkParent.siblings().removeClass("active-trail");
}
else if ($linkParent.data('id') !== alphaMenu.lastTouched.data('id')) {
var $previousItem = alphaMenu.lastTouched;
alphaMenu.lastTouched = $linkParent;
alphaMenu.removeAllCollapsed(e.currentTarget);
alphaMenu.lastTouched.addClass('active-trail');
$previousItem.find('li.active-trail').andSelf().removeClass('active-trail');
e.preventDefault();
return false; //extra, and to make sure the function has consistent return points
}
else if (alphaMenu.lastTouched.hasClass('active-trail')) {
return true;
}
});
};// alphaMenu.applyTouchEvent
/**
* Processing desktop menu levels.
*/
alphaMenu.applyHoverLevel = function (selector) {
var $previousItem = null,
$currentItem = null,
delayHappened = false,
timer;
alphaMenu.menuDom.on("mouseleave", function(e) {
delayHappened = false;
});
$(selector).hover(
function(e) {
// Don't hide the menu if user got back to it
if (alphaMenu.timerBackToMenu) {
clearTimeout(alphaMenu.timerBackToMenu);
}
// First time we are over an item
if (delayHappened === false) {
timer = setTimeout(function() {
// Remove all collapsed classes
alphaMenu.removeAllCollapsed(e.currentTarget);
// Update delay and current item
delayHappened = true;
$currentItem = $(e.currentTarget);
$currentItem.addClass('active-trail');
}, 200);
}
else {
// Changing between items
timer = setTimeout(function() {
if ($(e.currentTarget).data('id') !== $currentItem.data('id')) {
// Update current and previous items
$previousItem = $currentItem;
$currentItem = $(e.currentTarget);
$currentItem.addClass('active-trail');
// Remove all collapsed classes
alphaMenu.removeAllCollapsed(e.currentTarget);
// Remove classes from previous item and all internal
$previousItem.find('li.active-trail').andSelf().removeClass('active-trail');
}
}, 300);
}
},
function() {
clearTimeout(timer);
}
);
}; // alphaMenu.applyHoverLevel
/**
* Initialize mobile menu
*/
alphaMenu.mobileMenuInit = function (context) {
var $mobileMenu = alphaMenu.prepareMobileMenuTree(context);
if ($mobileMenu == null) return;
$mobileMenu.mmenu({
extensions: ['fullscreen', 'multiline', 'popup'],
counters: false,
navbar: {
title: Drupal.t('Menu'),
titleLink: 'anchor'
}
});
var mobileMenuApi = $mobileMenu.data('mmenu');
alphaMenu.mobileMenuButton(context, mobileMenuApi);
}; // alphaMenu.mobileMenuInit
/**
* Prepare tree for mobile menu
*/
alphaMenu.prepareMobileMenuTree = function (context) {
var $mobileMenu = null,
linkTitle = Drupal.t('Overview'),
$menuList = $('> ul.menu', alphaMenu.menuDom).clone(),
$listItemSeparator = $('<li class="separator"></li>');
var $hiddenSection = $('#hidden-section', context),
$switcherList = $('.locale-switcher-list', $hiddenSection).clone(),
$loginList = $('.alpha-menu-login-list', $hiddenSection).clone();
var $menuButtons = $('.alpha-menu-buttons-list', context),
$localeBtn = $('.locale-button', $menuButtons).clone(),
$loginBtn = $('.login-button', $menuButtons).clone();
var $localeBtnLink = $('a', $localeBtn),
$loginBtnLink = $('a', $loginBtn);
var localeBtnTitle = $localeBtnLink.text(),
loginBtnTitle = $loginBtnLink.text();
alphaMenu.mobileMenuReplaceLink($localeBtnLink, localeBtnTitle);
alphaMenu.mobileMenuReplaceLink($loginBtnLink, loginBtnTitle);
$localeBtn.append($switcherList);
$loginBtn.append($loginList);
if ($menuList.length) {
$menuList.append($listItemSeparator).append($loginBtn).append($localeBtn);
$mobileMenu = $('<nav id="mobile-menu"></nav>').html($menuList);
$('li.drop-down', $mobileMenu).each(function() {
var $levelWrapper = $('> div', this),
$listItem = $('<li class="overview-link menu-item"></li>');
if ($levelWrapper.hasClass('second-level')) {
var $sectionLink = $('> a', this),
$sectionLinkClone = $sectionLink.clone().text(linkTitle),
title = $sectionLink.text();
$listItem.prepend($sectionLinkClone);
$('> ul', $levelWrapper).prepend($listItem);
alphaMenu.mobileMenuReplaceLink($sectionLink, title);
}
if ($levelWrapper.hasClass('third-level')) {
var $titleLink = $('.title-link', $levelWrapper).text(linkTitle);
$listItem.prepend($titleLink);
$('ul', $levelWrapper).prepend($listItem);
}
});
}
return $mobileMenu;
}; // alphaMenu.prepareMobileMenuTree
/**
* Replaces link to span in order to fix mobile menu behaviour
*/
alphaMenu.mobileMenuReplaceLink = function (obj, title) {
obj.replaceWith('<span class="nolink">' + title + '</span>');
}; // alphaMenu.mobileMenuReplaceLink
/**
* Mobile menu toggle button events.
*/
alphaMenu.mobileMenuButton = function (context, mobileMenuApi) {
var $toggleListItem = $('.mobile-menu-toggle', context),
menuButtons = alphaMenu.getMenuButtons(context);
$('a', $toggleListItem).click(function (e) {
alphaMenu.mobileMenuApplyMargin();
if ($('html').hasClass('mm-opened')) {
mobileMenuApi.close();
$toggleListItem.removeClass('opened');
}
else {
mobileMenuApi.open();
$toggleListItem.addClass('opened');
alphaMenu.sectionAnimate('slideUp', menuButtons.search.block, menuButtons.search.btn);
}
e.preventDefault();
});
$(window).resize(function () {
if ($(window).width() >= alphaMenu.breakpoints.bp2) {
mobileMenuApi.close();
$toggleListItem.removeClass('opened');
}
});
}; // alphaMenu.mobileMenuButton
})(jQuery, Drupal);