1// CLASSIE class helper 2(function (window) { 3 "use strict"; 4 5 function classReg(className) { 6 return new RegExp("(^|\\s+)" + className + "(\\s+|$)"); 7 } 8 9 // classList support for class management 10 // altho to be fair, the api sucks because it won't accept multiple classes at once 11 var hasClass, addClass, removeClass; 12 13 if ("classList" in document.documentElement) { 14 hasClass = function (elem, c) { 15 return elem.classList.contains(c); 16 }; 17 addClass = function (elem, c) { 18 elem.classList.add(c); 19 }; 20 removeClass = function (elem, c) { 21 elem.classList.remove(c); 22 }; 23 } else { 24 hasClass = function (elem, c) { 25 return classReg(c).test(elem.className); 26 }; 27 addClass = function (elem, c) { 28 if (!hasClass(elem, c)) { 29 elem.className = elem.className + " " + c; 30 } 31 }; 32 removeClass = function (elem, c) { 33 elem.className = elem.className.replace(classReg(c), " "); 34 }; 35 } 36 37 function toggleClass(elem, c) { 38 var fn = hasClass(elem, c) ? removeClass : addClass; 39 fn(elem, c); 40 } 41 42 var classie = { 43 // full names 44 hasClass: hasClass, 45 addClass: addClass, 46 removeClass: removeClass, 47 toggleClass: toggleClass, 48 // short names 49 has: hasClass, 50 add: addClass, 51 remove: removeClass, 52 toggle: toggleClass, 53 }; 54 55 // transport 56 if (typeof define === "function" && define.amd) { 57 // AMD 58 define(classie); 59 } else if (typeof exports === "object") { 60 // CommonJS 61 module.exports = classie; 62 } else { 63 // browser global 64 window.classie = classie; 65 } 66})(window); 67 68if ("NodeList" in window && !NodeList.prototype.forEach) { 69 console.info("forEach polyfill for IE11"); 70 NodeList.prototype.forEach = function (callback, thisArg) { 71 thisArg = thisArg || window; 72 for (var i = 0; i < this.length; i++) { 73 callback.call(thisArg, this[i], i, this); 74 } 75 }; 76} 77 78//////// MENU JS 79(function (window) { 80 "use strict"; 81 82 var support = { animations: true }, 83 animEndEventNames = { 84 WebkitAnimation: "webkitAnimationEnd", 85 OAnimation: "oAnimationEnd", 86 msAnimation: "MSAnimationEnd", 87 animation: "animationend", 88 }, 89 animEndEventName = "animationend", //animEndEventNames[Modernizr.prefixed("animation")], 90 onEndAnimation = function (el, callback) { 91 var onEndCallbackFn = function (ev) { 92 if (support.animations) { 93 if (ev.target != this) return; 94 this.removeEventListener(animEndEventName, onEndCallbackFn); 95 } 96 if (callback && typeof callback === "function") { 97 callback.call(); 98 } 99 }; 100 if (support.animations) { 101 el.addEventListener(animEndEventName, onEndCallbackFn); 102 } else { 103 onEndCallbackFn(); 104 } 105 }; 106 107 function extend(a, b) { 108 for (var key in b) { 109 if (b.hasOwnProperty(key)) { 110 a[key] = b[key]; 111 } 112 } 113 return a; 114 } 115 116 function MLMenu(el, options) { 117 this.el = el; 118 this.options = extend({}, this.options); 119 extend(this.options, options); 120 121 // the menus (<ul>´s) 122 this.menus = [].slice.call(this.el.querySelectorAll(".AG__menu__level")); 123 124 // index of current menu 125 // Each level is actually a different menu so 0 is root, 1 is sub-1, 2 sub-2, etc. 126 this.current_menu = 0; 127 128 /* Determine what current menu actually is */ 129 var current_menu; 130 this.menus.forEach(function (menuEl, pos) { 131 var items = menuEl.querySelectorAll(".AG__menu__item"); 132 var _items = [].slice.call(items); 133 _items.forEach(function (itemEl, iPos) { 134 var currentLink = itemEl.querySelector(".AG__menu__link--current"); 135 if (currentLink) { 136 // This is the actual menu__level that should have current 137 current_menu = pos; 138 } 139 }); 140 }); 141 142 if (current_menu) { 143 this.current_menu = current_menu; 144 } 145 146 this._init(); 147 } 148 149 MLMenu.prototype.options = { 150 // show breadcrumbs 151 breadcrumbsCtrl: true, 152 // initial breadcrumb text 153 initialBreadcrumb: "all", 154 // show back button 155 backCtrl: true, 156 // delay between each menu item sliding animation 157 itemsDelayInterval: 60, 158 // direction 159 direction: "r2l", 160 // callback: item that doesn´t have a submenu gets clicked 161 // onItemClick([event], [inner HTML of the clicked item]) 162 onItemClick: function (ev, itemName) { 163 return false;
164 }, 165 }; 166 167 MLMenu.prototype._init = function () { 168 // iterate the existing menus and create an array of menus, 169 // more specifically an array of objects where each one holds the info of each menu element and its menu items 170 this.menusArr = []; 171 this.breadCrumbs = false; 172 var self = this; 173 var submenus = []; 174 175 /* Loops over root level menu items */ 176 177 this.menus.forEach(function (menuEl, pos) { 178 var menu = { 179 menuEl: menuEl, 180 menuItems: [].slice.call(menuEl.querySelectorAll(".AG__menu__item")), 181 }; 182 183 self.menusArr.push(menu); 184 185 // set current menu class 186 if (pos === self.current_menu) { 187 classie.add(menuEl, "AG__menu__level--current"); 188 } 189 190 var menu_x = menuEl.getAttribute("data-menu"); 191 var links = menuEl.querySelectorAll(".AG__menu__link"); 192 var _links = [].slice.call(links); 193 _links.forEach(function (linkEl, lPos) { 194 var _submenu = linkEl.getAttribute("data-submenu"); 195 var _name = linkEl.getAttribute("data-name"); 196 if (_submenu) { 197 var pushMe = { menu: _submenu, name: _name }; 198 if (submenus[pos]) { 199 submenus[pos].push(pushMe); 200 } else { 201 submenus[pos] = []; 202 submenus[pos].push(pushMe); 203 } 204 } 205 }); 206 }); 207 208 /* For each MENU, find their parent MENU */ 209 210 this.menus.forEach(function (menuEl, pos) { 211 var menu_x = menuEl.getAttribute("data-menu"); 212 submenus.forEach(function (subMenuEl, menu_root) { 213 subMenuEl.forEach(function (subMenuItem, subPos) { 214 if (subMenuItem.menu == menu_x) { 215 self.menusArr[pos].backIdx = menu_root; 216 self.menusArr[pos].name = subMenuItem.name; 217 } 218 }); 219 }); 220 }); 221 222 // create breadcrumbs 223 if (self.options.breadcrumbsCtrl) { 224 this.breadcrumbsCtrl = document.createElement("nav"); 225 this.breadcrumbsCtrl.className = "AG__menu__breadcrumbs"; 226 this.breadcrumbsCtrl.setAttribute("aria-label", "You are here"); 227 this.el.insertBefore(this.breadcrumbsCtrl, this.el.firstChild); 228 // add initial breadcrumb 229 this._addBreadcrumb(0); 230 231 // Need to add breadcrumbs for all parents of current submenu 232 if ( 233 self.menusArr[self.current_menu].backIdx != 0 && 234 self.current_menu != 0 235 ) { 236 this._crawlCrumbs( 237 self.menusArr[self.current_menu].backIdx, 238 self.menusArr 239 ); 240 this.breadCrumbs = true; 241 } 242 243 // Create current submenu breadcrumb 244 if (self.current_menu != 0) { 245 this._addBreadcrumb(self.current_menu); 246 this.breadCrumbs = true; 247 } 248 } 249 250 // create back button 251 if (this.options.backCtrl) { 252 this.backCtrl = document.createElement("button"); 253 if (this.breadCrumbs) { 254 this.backCtrl.className = "AG__menu__back"; 255 } else { 256 this.backCtrl.className = "AG__menu__back AG__menu__back--hidden"; 257 } 258 this.backCtrl.setAttribute("aria-label", "Go back"); 259 this.backCtrl.innerHTML = 260 '<svg xmlns="http://www.w3.org/2000/svg" width="9" height="15"><path fill="#f56853" fill-rule="evenodd" d="M5.389 7.51L0 13.166 1.892 15 9 7.51 1.892 0 0 1.834z"/></svg><span>Back</span>'; 261 262 this.el.insertBefore(this.backCtrl, this.el.firstChild); 263 } 264 265 // event binding 266 this._initEvents(); 267 }; 268 269 MLMenu.prototype._initEvents = function () { 270 var self = this; 271 272 for (var i = 0, len = this.menusArr.length; i < len; ++i) { 273 this.menusArr[i].menuItems.forEach(function (item, pos) { 274 var itemsClick = item.querySelectorAll(".AG__menu__link"); 275 var _itemsClick = [].slice.call(itemsClick); 276 _itemsClick.forEach(function (item) { 277 item.addEventListener("click", function (ev) { 278 var submenu = ev.target.getAttribute("data-submenu"), 279 itemName = ev.target.getAttribute("data-name"), 280 subMenuEl = self.el.querySelector( 281 'ul[data-menu="' + submenu + '"]' 282 ); 283 284 // check if there's a sub menu for this item 285 if (submenu && subMenuEl) { 286 ev.preventDefault(); 287 // open it 288 self._openSubMenu(subMenuEl, pos, itemName); 289 } else { 290 // add class current 291 var currentlink = self.el.querySelector( 292 ".AG__menu__link--current" 293 ); 294 if (currentlink) { 295 classie.remove( 296 self.el.querySelector(".AG__menu__link--current"), 297 "AG__menu__link--current" 298 ); 299 } 300 classie.add(ev.target, "AG__menu__link--current"); 301 302 // callback 303 self.options.onItemClick(ev, itemName); 304 } 305 }); 306 }); 307 }); 308 } 309 310 // back navigation 311 if (this.options.backCtrl) { 312 this.backCtrl.addEventListener("click", function () { 313 self._back(); 314 }); 315 } 316 }; 317 318 MLMenu.prototype._openSubMenu = function ( 319 subMenuEl, 320 clickPosition, 321 subMenuName 322 ) { 323 if (this.isAnimating) { 324 return false;
325 } 326 this.isAnimating = true; 327 328 // save "parent" menu index for back navigation 329 this.menusArr[this.menus.indexOf(subMenuEl)].backIdx = this.current_menu; 330 // save "parent" menu´s name 331 this.menusArr[this.menus.indexOf(subMenuEl)].name = subMenuName; 332 // current menu slides out 333 this._menuOut(clickPosition); 334 // next menu (submenu) slides in 335 this._menuIn(subMenuEl, clickPosition); 336 }; 337 338 MLMenu.prototype._back = function () { 339 if (this.isAnimating) { 340 return false; 341 } 342 this.isAnimating = true; 343 344 // current menu slides out 345 this._menuOut(); 346 // next menu (previous menu) slides in 347 var backMenu = 348 this.menusArr[this.menusArr[this.current_menu].backIdx].menuEl; 349 this._menuIn(backMenu); 350 351 // remove last breadcrumb 352 if (this.options.breadcrumbsCtrl) { 353 this.breadcrumbsCtrl.removeChild(this.breadcrumbsCtrl.lastElementChild); 354 } 355 }; 356 357 MLMenu.prototype._menuOut = function (clickPosition) { 358 // the current menu 359 var self = this, 360 currentMenu = this.menusArr[this.current_menu].menuEl, 361 isBackNavigation = typeof clickPosition == "undefined" ? true : false; 362 363 // slide out current menu items - first, set the delays for the items 364 this.menusArr[this.current_menu].menuItems.forEach(function (item, pos) { 365 item.style.WebkitAnimationDelay = item.style.animationDelay = 366 isBackNavigation 367 ? parseInt(pos * self.options.itemsDelayInterval) + "ms"
368 : parseInt( 369 Math.abs(clickPosition - pos) * self.options.itemsDelayInterval 370 ) + "ms"; 371 }); 372 // animation class 373 if (this.options.direction === "r2l") { 374 classie.add( 375 currentMenu, 376 !isBackNavigation ? "animate-outToLeft" : "animate-outToRight" 377 ); 378 } else { 379 classie.add( 380 currentMenu, 381 isBackNavigation ? "animate-outToLeft" : "animate-outToRight" 382 ); 383 } 384 }; 385 386 MLMenu.prototype._menuIn = function (nextMenuEl, clickPosition) { 387 var self = this, 388 // the current menu 389 currentMenu = this.menusArr[this.current_menu].menuEl, 390 isBackNavigation = typeof clickPosition == "undefined" ? true : false, 391 // index of the nextMenuEl 392 nextMenuIdx = this.menus.indexOf(nextMenuEl), 393 nextMenu = this.menusArr[nextMenuIdx], 394 nextMenuEl = nextMenu.menuEl, 395 nextMenuItems = nextMenu.menuItems, 396 nextMenuItemsTotal = nextMenuItems.length; 397 398 // slide in next menu items - first, set the delays for the items 399 nextMenuItems.forEach(function (item, pos) { 400 item.style.WebkitAnimationDelay = item.style.animationDelay = 401 isBackNavigation 402 ? parseInt(pos * self.options.itemsDelayInterval) + "ms"
403 : parseInt( 404 Math.abs(clickPosition - pos) * self.options.itemsDelayInterval 405 ) + "ms"; 406 407 // we need to reset the classes once the last item animates in 408 // the "last item" is the farthest from the clicked item 409 // let's calculate the index of the farthest item 410 var farthestIdx = 411 clickPosition <= nextMenuItemsTotal / 2 || isBackNavigation 412 ? nextMenuItemsTotal - 1 413 : 0; 414 415 if (pos === farthestIdx) { 416 onEndAnimation(item, function () { 417 // reset classes 418 if (self.options.direction === "r2l") { 419 classie.remove( 420 currentMenu, 421 !isBackNavigation ? "animate-outToLeft" : "animate-outToRight" 422 ); 423 classie.remove( 424 nextMenuEl, 425 !isBackNavigation ? "animate-inFromRight" : "animate-inFromLeft" 426 ); 427 } else { 428 classie.remove( 429 currentMenu, 430 isBackNavigation ? "animate-outToLeft" : "animate-outToRight" 431 ); 432 classie.remove( 433 nextMenuEl, 434 isBackNavigation ? "animate-inFromRight" : "animate-inFromLeft" 435 ); 436 } 437 classie.remove(currentMenu, "AG__menu__level--current"); 438 classie.add(nextMenuEl, "AG__menu__level--current"); 439 440 //reset current 441 self.current_menu = nextMenuIdx; 442 443 // control back button and breadcrumbs navigation elements 444 if (!isBackNavigation) { 445 // show back button 446 if (self.options.backCtrl) { 447 classie.remove(self.backCtrl, "AG__menu__back--hidden"); 448 } 449 450 // add breadcrumb 451 self._addBreadcrumb(nextMenuIdx); 452 } else if (self.current_menu === 0 && self.options.backCtrl) { 453 // hide back button 454 classie.add(self.backCtrl, "AG__menu__back--hidden"); 455 } 456 457 // we can navigate again.. 458 self.isAnimating = false; 459 460 // focus retention 461 nextMenuEl.focus(); 462 }); 463 } 464 }); 465 466 // animation class 467 if (this.options.direction === "r2l") { 468 classie.add( 469 nextMenuEl, 470 !isBackNavigation ? "animate-inFromRight" : "animate-inFromLeft" 471 ); 472 } else { 473 classie.add( 474 nextMenuEl, 475 isBackNavigation ? "animate-inFromRight" : "animate-inFromLeft" 476 ); 477 } 478 }; 479 480 MLMenu.prototype._addBreadcrumb = function (idx) { 481 if (!this.options.breadcrumbsCtrl) { 482 return false; 483 } 484 485 var bc = document.createElement("a"); 486 bc.href = "#"; // make it focusable 487 bc.innerHTML = idx 488 ? this.menusArr[idx].name 489 : this.options.initialBreadcrumb; 490 this.breadcrumbsCtrl.appendChild(bc); 491 492 var self = this; 493 bc.addEventListener("click", function (ev) { 494 ev.preventDefault(); 495 496 // do nothing if this breadcrumb is the last one in the list of breadcrumbs 497 if (!bc.nextSibling || self.isAnimating) { 498 return false; 499 } 500 self.isAnimating = true; 501 502 // current menu slides out 503 self._menuOut(); 504 // next menu slides in 505 var nextMenu = self.menusArr[idx].menuEl; 506 self._menuIn(nextMenu); 507 508 // remove breadcrumbs that are ahead 509 var siblingNode; 510 while ((siblingNode = bc.nextSibling)) { 511 self.breadcrumbsCtrl.removeChild(siblingNode); 512 } 513 }); 514 }; 515 516 MLMenu.prototype._crawlCrumbs = function (currentMenu, menuArray) { 517 if (menuArray[currentMenu].backIdx != 0) { 518 this._crawlCrumbs(menuArray[currentMenu].backIdx, menuArray); 519 } 520 // create breadcrumb 521 this._addBreadcrumb(currentMenu); 522 }; 523 524 window.MLMenu = MLMenu; 525})(window); 526 527/// Airgigs Small Menu 528var NavSmall = { 529 toggleGroove: function (){ 530 var groove = document.getElementById("grooveLoader"); 531 if (!groove) return; 532 533 if (groove.style.display === "none") { 534 groove.style.display = "inline-flex"; 535 } else { 536 groove.style.display = "none"; 537 } 538 }, 539 toggleMenu: function (elem) { 540 elem.classList.toggle("is-active"); 541 542 // Keep Helpy hidden on mobile unless hamburger menu is open. 543 // CSS listens to body.ag-menu-open. 544 if (document && document.body) { 545 document.body.classList.toggle("ag-menu-open", elem.classList.contains("is-active")); 546 } 547 548 NavSmall.toggleGroove(); 549 }, 550 lockScroll: function () {}, 551 init: function () { 552 console.log("init Nav Small"); 553 var menuEl = document.getElementById("AG__menu"); 554 555 var mlmenu = new MLMenu(menuEl, { 556 breadcrumbsCtrl: false, // show breadcrumbs 557 backCtrl: true, // show back button 558 itemsDelayInterval: 0, // delay between each menu item sliding animation 559 }); 560 561 // mobile menu toggle 562 var triggerMenuCtrl = document.getElementById("AG__menu--trigger"); 563 triggerMenuCtrl.addEventListener("click", function () { 564 this.classList.toggle("is-active"); 565 NavSmall.toggleMenu(menuEl); 566 }); 567 }, 568};
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.