https://www.gresb.com/wp-content/themes/framework/assets/js/components/_2_menu-bar.js?ver=1790268989
1// File#: _2_menu-bar 2// Usage: codyhouse.co/license 3(function() { 4 var MenuBar = function(element) { 5 this.element = element; 6 this.items = Util.getChildrenByClassName(this.element, 'menu-bar__item'); 7 this.mobHideItems = this.element.getElementsByClassName('menu-bar__item--hide'); 8 this.moreItemsTrigger = this.element.getElementsByClassName('js-menu-bar__trigger'); 9 initMenuBar(this); 10 }; 11 12 function initMenuBar(menu) { 13 setMenuTabIndex(menu); // set correct tabindexes for menu item 14 initMenuBarMarkup(menu); // create additional markup 15 checkMenuLayout(menu); // set menu layout 16 Util.addClass(menu.element, 'menu-bar--loaded'); // reveal menu 17 18 // custom event emitted when window is resized 19 menu.element.addEventListener('update-menu-bar', function(event){ 20 checkMenuLayout(menu); 21 if(menu.menuInstance) menu.menuInstance.toggleMenu(false, false); // close dropdown 22 }); 23 24 // keyboard events 25 // open dropdown when pressing Enter on trigger element 26 if(menu.moreItemsTrigger.length > 0) { 27 menu.moreItemsTrigger[0].addEventListener('keydown', function(event) { 28 if( (event.keyCode && event.keyCode == 13) || (event.key && event.key.toLowerCase() == 'enter') ) { 29 if(!menu.menuInstance) return; 30 menu.menuInstance.selectedTrigger = menu.moreItemsTrigger[0]; 31 menu.menuInstance.toggleMenu(!Util.hasClass(menu.subMenu, 'menu--is-visible'), true); 32 } 33 }); 34 35 // close dropdown on esc 36 menu.subMenu.addEventListener('keydown', function(event) { 37 if((event.keyCode && event.keyCode == 27) || (event.key && event.key.toLowerCase() == 'escape')) { // close submenu on esc 38 if(menu.menuInstance) menu.menuInstance.toggleMenu(false, true); 39 } 40 }); 41 } 42 43 // navigate menu items using left/right arrows 44 menu.element.addEventListener('keydown', function(event) { 45 if( (event.keyCode && event.keyCode == 39) || (event.key && event.key.toLowerCase() == 'arrowright') ) { 46 navigateItems(menu.items, event, 'next'); 47 } else if( (event.keyCode && event.keyCode == 37) || (event.key && event.key.toLowerCase() == 'arrowleft') ) { 48 navigateItems(menu.items, event, 'prev'); 49 } 50 }); 51 }; 52 53 function setMenuTabIndex(menu) { // set tabindexes for the menu items to allow keyboard navigation 54 var nextItem = false; 55 for(var i = 0; i < menu.items.length; i++ ) { 56 if(i == 0 || nextItem) menu.items[i].setAttribute('tabindex', '0'); 57 else menu.items[i].setAttribute('tabindex', '-1'); 58 if(i == 0 && menu.moreItemsTrigger.length > 0) nextItem = true; 59 else nextItem = false; 60 } 61 }; 62 63 function initMenuBarMarkup(menu) { 64 if(menu.mobHideItems.length == 0 ) { // no items to hide on mobile - remove trigger 65 if(menu.moreItemsTrigger.length > 0) menu.element.removeChild(menu.moreItemsTrigger[0]); 66 return; 67 } 68 69 if(menu.moreItemsTrigger.length == 0) return; 70 71 // create the markup for the Menu element 72 var content = ''; 73 menu.menuControlId = 'submenu-bar-'+Date.now(); 74 for(var i = 0; i < menu.mobHideItems.length; i++) { 75 var item = menu.mobHideItems[i].cloneNode(true), 76 svg = item.getElementsByTagName('svg')[0], 77 label = item.getElementsByClassName('menu-bar__label')[0]; 78 79 svg.setAttribute('class', 'icon menu__icon'); 80 content = content + '<li role="menuitem"><span class="menu__content js-menu__content">'+svg.outerHTML+'<span>'+label.innerHTML+'</span></span></li>'; 81 } 82 83 Util.setAttributes(menu.moreItemsTrigger[0], {'role': 'button', 'aria-expanded': 'false', 'aria-controls': menu.menuControlId, 'aria-haspopup': 'true'}); 84 85 var subMenu = document.createElement('menu'), 86 customClass = menu.element.getAttribute('data-menu-class'); 87 Util.setAttributes(subMenu, {'id': menu.menuControlId, 'class': 'menu js-menu '+customClass}); 88 subMenu.innerHTML = content; 89 document.body.appendChild(subMenu); 90 91 menu.subMenu = subMenu; 92 menu.subItems = subMenu.getElementsByTagName('li'); 93 94 menu.menuInstance = new Menu(menu.subMenu); // this will handle the dropdown behaviour 95 }; 96 97 function checkMenuLayout(menu) { // switch from compressed to expanded layout and viceversa 98 var layout = getComputedStyle(menu.element, ':before').getPropertyValue('content').replace(/\'|"/g, ''); 99 Util.toggleClass(menu.element, 'menu-bar--collapsed', layout == 'collapsed'); 100 }; 101 102 function navigateItems(list, event, direction, prevIndex) { // keyboard navigation among menu items 103 event.preventDefault(); 104 var index = (typeof prevIndex !== 'undefined') ? prevIndex : Util.getIndexInArray(list, event.target), 105 nextIndex = direction == 'next' ? index + 1 : index - 1; 106 if(nextIndex < 0) nextIndex = list.length - 1; 107 if(nextIndex > list.length - 1) nextIndex = 0; 108 // check if element is visible before moving focus 109 (list[nextIndex].offsetParent === null) ? navigateItems(list, event, direction, nextIndex) : Util.moveFocus(list[nextIndex]); 110 }; 111 112 function checkMenuClick(menu, target) { // close dropdown when clicking outside the menu element 113 if(menu.menuInstance && !menu.moreItemsTrigger[0].contains(target) && !menu.subMenu.contains(target)) menu.menuInstance.toggleMenu(false, false); 114 }; 115 116 // init MenuBars objects 117 var menuBars = document.getElementsByClassName('js-menu-bar'); 118 if( menuBars.length > 0 ) { 119 var j = 0, 120 menuBarArray = []; 121 for( var i = 0; i < menuBars.length; i++) { 122 var beforeContent = getComputedStyle(menuBars[i], ':before').getPropertyValue('content'); 123 if(beforeContent && beforeContent !='' && beforeContent !='none') { 124 (function(i){menuBarArray.push(new MenuBar(menuBars[i]));})(i); 125 j = j + 1; 126 } 127 } 128 129 if(j > 0) { 130 var resizingId = false, 131 customEvent = new CustomEvent('update-menu-bar'); 132 // update Menu Bar layout on resize 133 window.addEventListener('resize', function(event){ 134 clearTimeout(resizingId); 135 resizingId = setTimeout(doneResizing, 150); 136 }); 137 138 // close menu when clicking outside it 139 window.addEventListener('click', function(event){ 140 menuBarArray.forEach(function(element){ 141 checkMenuClick(element, event.target); 142 }); 143 }); 144 145 function doneResizing() { 146 for( var i = 0; i < menuBars.length; i++) { 147 (function(i){menuBars[i].dispatchEvent(customEvent)})(i); 148 }; 149 }; 150 } 151 } 152}());
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.