'use strict'; var VSAPP = { // Define app vars currentMegaMenuButton: null, mapButtonOver: null, mapOver: null, previousMegaMenuButton: null, timerMegaMenu: null, timerMegaMenuLength: null, timerMegaMenuMap: null, mainSection: null, megamenuMap: null, megamenuMapPage: null, megaMenuButton: null, mobileMegamenuButtons: null, searchPanel: null, searchPanelCloseButton: null, searchPanelTrigger: null, sideMenuNavigation: null, sideMenuTrigger: null, sideMenuIconClosed: null, sideMenuIconMenu: null, // Define functions /** * Attach click for mobile mega menu * @param element */ attachClickMobileMegamenuButton: function(element) { element.addEventListener('click', function(event){ if (!document.body.classList.contains('lateral-menu-is-open')) { VSAPP.toggleMobileMegaMenu({ element: event.currentTarget.querySelector('ul'), className: 'show' }); } }); }, /** * Creates buttons for desktop megamenu * @param element */ createMegamenuButton: function(element) { element.addEventListener('mouseenter', function(event){ VSAPP.mapButtonOver = true; VSAPP.destroyTimerForButton(); VSAPP.updateState(event.currentTarget); VSAPP.updateMegamenu(event.currentTarget); }); element.addEventListener('mouseleave', function(event){ VSAPP.mapButtonOver = false; VSAPP.createTimerForButton(event.currentTarget); }); }, /** * Creates timer for megamenu button * @param element */ createTimerForButton: function(element) { var id = element.getAttribute('data-list-id'); VSAPP.timerMegaMenu = window.setTimeout(function(event){ if (!VSAPP.mapOver) { VSAPP.megamenuMap.classList.remove('show'); VSAPP.megamenuMapPage[id].classList.remove('show'); } }, VSAPP.timerMegaMenuLength); }, /** * Creates timer for passed element on megamenu map * @param element */ createTimerForMap: function(element) { VSAPP.timerMegaMenuMap = window.setTimeout(function(event){ if (!VSAPP.mapButtonOver) { element.classList.remove('show'); } }, VSAPP.timerMegaMenuLength); }, /** * Destroys timer assigned to megamenu buttons */ destroyTimerForButton: function() { window.clearTimeout(VSAPP.timerMegaMenu); }, /** * Destroys timer assigned to megamenu map */ destroyTimerForMap: function() { window.clearTimeout(VSAPP.timerMegaMenuMap); }, /** * For when side (mobile) menu is closed */ menuClosed: function() { window.removeEventListener('resize', VSAPP.menuClosed, false); VSAPP.sideMenuTrigger.removeEventListener('ontouchstart', function (e) { e.preventDefault(); }, false); VSAPP.sideMenuTrigger.removeEventListener('ontouchmove', function (e) { e.preventDefault(); }, false); VSAPP.sideMenuTrigger.addEventListener('click', VSAPP.menuOpen, false); VSAPP.mainSection.removeEventListener('click', VSAPP.menuClosed, false); VSAPP.sideMenuTrigger.classList.remove('is-clicked'); document.body.classList.remove('fixed', 'lateral-menu-is-open'); VSAPP.mainSection.classList.remove('lateral-menu-is-open'); VSAPP.mainSection.classList.add('lateral-menu-is-closed'); VSAPP.sideMenuNavigation.classList.remove('lateral-menu-is-open'); VSAPP.sideMenuNavigation.classList.add('lateral-menu-is-closed'); VSAPP.sideMenuIconClosed.classList.add('displayNone'); VSAPP.sideMenuIconMenu.classList.remove('displayNone'); }, /** * For when side (mobile) menu is opened */ menuOpen: function() { VSAPP.sideMenuTrigger.addEventListener('ontouchstart', function (e) { e.preventDefault() }, false); VSAPP.sideMenuTrigger.addEventListener('ontouchmove', function (e) { e.preventDefault() }, false); document.body.classList.add('fixed', 'lateral-menu-is-open'); VSAPP.sideMenuTrigger.classList.add('is-clicked'); VSAPP.mainSection.classList.add('lateral-menu-is-open'); VSAPP.mainSection.classList.remove('lateral-menu-is-closed'); VSAPP.sideMenuNavigation.classList.add('lateral-menu-is-open'); VSAPP.sideMenuNavigation.classList.remove('lateral-menu-is-closed'); VSAPP.sideMenuIconClosed.classList.remove('displayNone'); VSAPP.sideMenuIconMenu.classList.add('displayNone'); VSAPP.sideMenuTrigger.removeEventListener('click', VSAPP.menuOpen, false); VSAPP.sideMenuTrigger.addEventListener('click', VSAPP.menuClosed, false); window.addEventListener('resize', VSAPP.menuClosed, false); }, /** * css class changes for closing search panel */ searchPanelClose: function() { VSAPP.searchPanel.classList.remove('search-panel-open'); VSAPP.searchPanel.classList.add('search-panel-closed'); VSAPP.mainSection.classList.remove('search-panel-open'); }, /** * css class changes for opening search panel */ searchPanelOpen: function() { VSAPP.searchPanel.classList.remove('search-panel-closed'); VSAPP.searchPanel.classList.add('search-panel-open'); VSAPP.mainSection.classList.add('search-panel-open'); }, /** * Toggles mobile mega menu accordion * @param args */ toggleMobileMegaMenu: function(selected) { var selectedText = selected.element.parentNode.getElementsByTagName('span')[1].innerText; var openEl = document.querySelector('.static_home__mega_menu_mobile__list_sub.show'); if (openEl) { var openText = document.querySelector('.static_home__mega_menu_mobile__list_sub.show').parentNode.getElementsByTagName('span')[1].innerText; if (selectedText !== openText) { openEl.classList.toggle('show'); } } selected.element.classList.toggle('show'); }, /** * Switch mega menu pages depending on button that was rolled over. * @param element */ updateMegamenu: function(element){ if (VSAPP.previousMegaMenuButton) { VSAPP.megamenuMapPage[VSAPP.previousMegaMenuButton.getAttribute('data-list-id')].classList.remove('show'); } VSAPP.megamenuMapPage[element.getAttribute('data-list-id')].classList.add('show'); VSAPP.megamenuMap.classList.add('show'); }, /** * Update state of the mega menu * @param element */ updateState: function(element) { VSAPP.previousMegaMenuButton = VSAPP.currentMegaMenuButton; VSAPP.currentMegaMenuButton = element; }, /** * Search, build form action. */ search: function(id, formId) { var selectedIndex = document.getElementById(id).selectedIndex; var form = document.getElementById(formId); var action = form.getElementsByTagName('option')[selectedIndex].title; if (action !== '') { form.action = action; } form.submit(); }, /** * App bootstrapping */ home: { /** * Runs on content loaded but not page ready? * Left in for legacy reasons. */ init: function () {}, /** * Runs after page ready */ show: function () { // init vars VSAPP.mapButtonOver = false; VSAPP.mapOver = false; VSAPP.timerMegaMenuLength = 300; // Grab dom elements VSAPP.mainSection = document.querySelector('#static_home'); VSAPP.megamenuMap = document.querySelector('.static_home__mega_menu__map'); VSAPP.megamenuMapPage = document.querySelectorAll('.static_home__mega_menu__map__page'); VSAPP.megaMenuButton = document.querySelectorAll('.static_home__mega_menu__list__item'); VSAPP.mobileMegamenuButtons = document.querySelectorAll('.static_home__mega_menu_mobile__list__item'); VSAPP.searchPanel = document.querySelector('#static_home__search_panel'); VSAPP.searchPanelCloseButton = document.querySelector('#static_home__search_panel_trigger'); VSAPP.searchPanelTrigger = document.getElementById('search-opener'); VSAPP.sideMenuNavigation = document.getElementById('side_menu__navigation'); VSAPP.sideMenuTrigger = document.getElementById('static_home__header__content__menu_trigger'); VSAPP.sideMenuIconClosed = document.querySelector('.static_home__header__content__menu_trigger__icon_closed'); VSAPP.sideMenuIconMenu = document.querySelector('.static_home__header__content__menu_trigger__icon_menu'); // Initiliase mega menu on desktop for (var i = 0; i < VSAPP.megaMenuButton.length; i++) { VSAPP.createMegamenuButton(VSAPP.megaMenuButton[i]); } // Initiliase mega menu on mobile for (var i = 0; i < VSAPP.mobileMegamenuButtons.length; i++) { VSAPP.attachClickMobileMegamenuButton(VSAPP.mobileMegamenuButtons[i]); } // Attach click handlers, conditional as not all countries will need this. if (VSAPP.searchPanelTrigger && VSAPP.searchPanelCloseButton) { VSAPP.searchPanelTrigger.addEventListener('click', VSAPP.searchPanelOpen, false); VSAPP.searchPanelCloseButton.addEventListener('click', VSAPP.searchPanelClose, false); } VSAPP.sideMenuTrigger.addEventListener('click', VSAPP.menuOpen, false); VSAPP.sideMenuTrigger.removeEventListener('click', VSAPP.menuClosed, false); // Attach rollover handlers for desktop megamenu. It utilises a timer to improve user // experience if they roll outside the megamenu while a sub menu is visible. VSAPP.megamenuMap.addEventListener('mouseenter', function() { VSAPP.mapOver = true; VSAPP.destroyTimerForMap(); }); VSAPP.megamenuMap.addEventListener('mouseleave', function(event) { VSAPP.mapOver = false; VSAPP.createTimerForMap(event.currentTarget); }); } } }; /** * Legacy code from kiwii pattern, not sure if the home page needs to follow this currently. * Left unchanged for historical purposes until a fuller rewrite of home pages are done. */ var UTIL = { exec: function (controller, action) { var ns = VSAPP, action = (action === undefined) ? 'init' : action; if (controller !== '' && ns[controller] && typeof ns[controller][action] == 'function') { ns[controller][action](); } }, init: function () { var body = document.body, controller = body.getAttribute('data-controller'), action = body.getAttribute('data-action'); UTIL.exec('common'); UTIL.exec(controller); UTIL.exec(controller, action); } }; document.addEventListener('DOMContentLoaded', function () { UTIL.init(); }, false);