1 2/** 3 * what-input - A global utility for tracking the current input method (mouse, keyboard or touch). 4 * @version v4.0.6 5 * @link https://github.com/ten1seven/what-input 6 * @license MIT 7 */ 8!function(e,t){"object"==typeof exports&&"object"==typeof module?module.exports=t():"function"==typeof define&&define.amd?define("whatInput",[],t):"object"==typeof exports?exports.whatInput=t():e.whatInput=t()}(this,function(){return function(e){function t(o){if(n[o])return n[o].exports;var i=n[o]={exports:{},id:o,loaded:!1};return e[o].call(i.exports,i,i.exports,t),i.loaded=!0,i.exports}var n={};return t.m=e,t.c=n,t.p="",t(0)}([function(e,t){e.exports=function(){var e=document.documentElement,t="initial",n=null,o=["input","select","textarea"],i=[16,17,18,91,93],r={keyup:"keyboard",mousedown:"mouse",mousemove:"mouse",MSPointerDown:"pointer",MSPointerMove:"pointer",pointerdown:"pointer",pointermove:"pointer",touchstart:"touch"},u=[],d=!1,a={2:"touch",3:"touch",4:"mouse"},p=null,s=function(){r[h()]="mouse",c(),m()},c=function(){window.PointerEvent?(e.addEventListener("pointerdown",f),e.addEventListener("pointermove",w)):window.MSPointerEvent?(e.addEventListener("MSPointerDown",f),e.addEventListener("MSPointerMove",w)):(e.addEventListener("mousedown",f),e.addEventListener("mousemove",w),"ontouchstart"in window&&e.addEventListener("touchstart",v)),e.addEventListener(h(),w),e.addEventListener("keydown",f),e.addEventListener("keyup",f)},f=function(e){if(!d){var u=e.which,a=r[e.type];if("pointer"===a&&(a=l(e)),t!==a||n!==a){var p=document.activeElement,s=!(!p||!p.nodeName||o.indexOf(p.nodeName.toLowerCase())!==-1);("touch"===a||"mouse"===a&&i.indexOf(u)===-1||"keyboard"===a&&s)&&(t=n=a,m())}}},m=function(){e.setAttribute("data-whatinput",t),e.setAttribute("data-whatintent",t),u.indexOf(t)===-1&&(u.push(t),e.className+=" whatinput-types-"+t)},w=function(t){if(!d){var o=r[t.type];"pointer"===o&&(o=l(t)),n!==o&&(n=o,e.setAttribute("data-whatintent",n))}},v=function(e){window.clearTimeout(p),f(e),d=!0,p=window.setTimeout(function(){d=!1},200)},l=function(e){return"number"==typeof e.pointerType?a[e.pointerType]:"pen"===e.pointerType?"touch":e.pointerType},h=function(){return"onwheel"in document.createElement("div")?"wheel":void 0!==document.onmousewheel?"mousewheel":"DOMMouseScroll"};return"addEventListener"in window&&Array.prototype.indexOf&&s(),{ask:function(e){return"loose"===e?n:t},types:function(){return u}}}()}])}); 9!function ($) { 10 11 "use strict"; 12 13 var FOUNDATION_VERSION = '6.3.1'; 14 15 // Global Foundation object 16 // This is attached to the window, or used as a module for AMD/Browserify 17 var Foundation = { 18 version: FOUNDATION_VERSION, 19 20 /** 21 * Stores initialized plugins. 22 */ 23 _plugins: {}, 24 25 /** 26 * Stores generated unique ids for plugin instances 27 */ 28 _uuids: [], 29 30 /** 31 * Returns a boolean for RTL support 32 */ 33 rtl: function () { 34 return $('html').attr('dir') === 'rtl'; 35 }, 36 /** 37 * Defines a Foundation plugin, adding it to the `Foundation` namespace and the list of plugins to initialize when reflowing. 38 * @param {Object} plugin - The constructor of the plugin. 39 */ 40 plugin: function (plugin, name) { 41 // Object key to use when adding to global Foundation object 42 // Examples: Foundation.Reveal, Foundation.OffCanvas 43 var className = name || functionName(plugin); 44 // Object key to use when storing the plugin, also used to create the identifying data attribute for the plugin 45 // Examples: data-reveal, data-off-canvas 46 var attrName = hyphenate(className); 47 48 // Add to the Foundation object and the plugins list (for reflowing) 49 this._plugins[attrName] = this[className] = plugin; 50 }, 51 /** 52 * @function 53 * Populates the _uuids array with pointers to each individual plugin instance. 54 * Adds the `zfPlugin` data-attribute to programmatically created plugins to allow use of $(selector).foundation(method) calls. 55 * Also fires the initialization event for each plugin, consolidating repetitive code. 56 * @param {Object} plugin - an instance of a plugin, usually `this` in context. 57 * @param {String} name - the name of the plugin, passed as a camelCased string. 58 * @fires Plugin#init 59 */ 60 registerPlugin: function (plugin, name) { 61 var pluginName = name ? hyphenate(name) : functionName(plugin.constructor).toLowerCase(); 62 plugin.uuid = this.GetYoDigits(6, pluginName); 63 64 if (!plugin.$element.attr('data-' + pluginName)) { 65 plugin.$element.attr('data-' + pluginName, plugin.uuid); 66 } 67 if (!plugin.$element.data('zfPlugin')) { 68 plugin.$element.data('zfPlugin', plugin); 69 } 70 /** 71 * Fires when the plugin has initialized. 72 * @event Plugin#init 73 */ 74 plugin.$element.trigger('init.zf.' + pluginName); 75 76 this._uuids.push(plugin.uuid); 77 78 return; 79 }, 80 /** 81 * @function 82 * Removes the plugins uuid from the _uuids array.
83 * Removes the zfPlugin data attribute, as well as the data-plugin-name attribute. 84 * Also fires the destroyed event for the plugin, consolidating repetitive code. 85 * @param {Object} plugin - an instance of a plugin, usually `this` in context. 86 * @fires Plugin#destroyed 87 */ 88 unregisterPlugin: function (plugin) { 89 var pluginName = hyphenate(functionName(plugin.$element.data('zfPlugin').constructor)); 90 91 this._uuids.splice(this._uuids.indexOf(plugin.uuid), 1); 92 plugin.$element.removeAttr('data-' + pluginName).removeData('zfPlugin') 93 /** 94 * Fires when the plugin has been destroyed. 95 * @event Plugin#destroyed 96 */ 97 .trigger('destroyed.zf.' + pluginName); 98 for (var prop in plugin) { 99 plugin[prop] = null; //clean up script to prep for garbage collection. 100 } 101 return; 102 }, 103 104 /** 105 * @function 106 * Causes one or more active plugins to re-initialize, resetting event listeners, recalculating positions, etc. 107 * @param {String} plugins - optional string of an individual plugin key, attained by calling `$(element).data('pluginName')`, or string of a plugin class i.e. `'dropdown'` 108 * @default If no argument is passed, reflow all currently active plugins. 109 */ 110 reInit: function (plugins) { 111 var isJQ = plugins instanceof $; 112 try { 113 if (isJQ) { 114 plugins.each(function () { 115 $(this).data('zfPlugin')._init(); 116 }); 117 } else { 118 var type = typeof plugins, 119 _this = this, 120 fns = { 121 'object': function (plgs) { 122 plgs.forEach(function (p) { 123 p = hyphenate(p); 124 $('[data-' + p + ']').foundation('_init'); 125 }); 126 }, 127 'string': function () { 128 plugins = hyphenate(plugins); 129 $('[data-' + plugins + ']').foundation('_init'); 130 }, 131 'undefined': function () { 132 this['object'](Object.keys(_this._plugins)); 133 } 134 }; 135 fns[type](plugins); 136 } 137 } catch (err) { 138 console.error(err); 139 } finally { 140 return plugins; 141 } 142 }, 143 144 /** 145 * returns a random base-36 uid with namespacing 146 * @function 147 * @param {Number} length - number of random base-36 digits desired. Increase for more random strings. 148 * @param {String} namespace - name of plugin to be incorporated in uid, optional. 149 * @default {String} '' - if no plugin name is provided, nothing is appended to the uid. 150 * @returns {String} - unique id 151 */ 152 GetYoDigits: function (length, namespace) { 153 length = length || 6; 154 return Math.round(Math.pow(36, length + 1) - Math.random() * Math.pow(36, length)).toString(36).slice(1) + (namespace ? '-' + namespace : ''); 155 }, 156 /** 157 * Initialize plugins on any elements within `elem` (and `elem` itself) that aren't already initialized. 158 * @param {Object} elem - jQuery object containing the element to check inside. Also checks the element itself, unless it's the `document` object. 159 * @param {String|Array} plugins - A list of plugins to initialize. Leave this out to initialize everything. 160 */ 161 reflow: function (elem, plugins) { 162 163 // If plugins is undefined, just grab everything 164 if (typeof plugins === 'undefined') { 165 plugins = Object.keys(this._plugins); 166 } 167 // If plugins is a string, convert it to an array with one item 168 else if (typeof plugins === 'string') { 169 plugins = [plugins]; 170 } 171 172 var _this = this; 173 174 // Iterate through each plugin 175 $.each(plugins, function (i, name) { 176 // Get the current plugin 177 var plugin = _this._plugins[name]; 178 179 // Localize the search to all elements inside elem, as well as elem itself, unless elem === document 180 var $elem = $(elem).find('[data-' + name + ']').addBack('[data-' + name + ']'); 181 182 // For each plugin found, initialize it 183 $elem.each(function () { 184 var $el = $(this), 185 opts = {}; 186 // Don't double-dip on plugins 187 if ($el.data('zfPlugin')) { 188 console.warn("Tried to initialize " + name + " on an element that already has a Foundation plugin."); 189 return; 190 } 191 192 if ($el.attr('data-options')) { 193 var thing = $el.attr('data-options').split(';').forEach(function (e, i) { 194 var opt = e.split(':').map(function (el) { 195 return el.trim(); 196 }); 197 if (opt[0]) opts[opt[0]] = parseValue(opt[1]); 198 }); 199 } 200 try { 201 $el.data('zfPlugin', new plugin($(this), opts)); 202 } catch (er) { 203 console.error(er); 204 } finally { 205 return; 206 } 207 }); 208 }); 209 }, 210 getFnName: functionName, 211 transitionend: function ($elem) { 212 var transitions = { 213 'transition': 'transitionend', 214 'WebkitTransition': 'webkitTransitionEnd', 215 'MozTransition': 'transitionend', 216 'OTransition': 'otransitionend' 217 }; 218 var elem = document.createElement('div'), 219 end; 220 221 for (var t in transitions) { 222 if (typeof elem.style[t] !== 'undefined') { 223 end = transitions[t]; 224 } 225 } 226 if (end) { 227 return end; 228 } else { 229 end = setTimeout(function () { 230 $elem.triggerHandler('transitionend', [$elem]); 231 }, 1); 232 return 'transitionend'; 233 } 234 } 235 }; 236 237 Foundation.util = { 238 /** 239 * Function for applying a debounce effect to a function call. 240 * @function 241 * @param {Function} func - Function to be called at end of timeout. 242 * @param {Number} delay - Time in ms to delay the call of `func`. 243 * @returns function 244 */ 245 throttle: function (func, delay) { 246 var timer = null; 247 248 return function () { 249 var context = this, 250 args = arguments; 251 252 if (timer === null) { 253 timer = setTimeout(function () {
254 func.apply(context, args); 255 timer = null; 256 }, delay); 257 } 258 }; 259 } 260 }; 261 262 // TODO: consider not making this a jQuery function 263 // TODO: need way to reflow vs. re-initialize 264 /** 265 * The Foundation jQuery method. 266 * @param {String|Array} method - An action to perform on the current jQuery object. 267 */ 268 var foundation = function (method) { 269 var type = typeof method, 270 $meta = $('meta.foundation-mq'), 271 $noJS = $('.no-js'); 272 273 if (!$meta.length) { 274 $('<meta class="foundation-mq">').appendTo(document.head); 275 } 276 if ($noJS.length) { 277 $noJS.removeClass('no-js'); 278 } 279 280 if (type === 'undefined') { 281 //needs to initialize the Foundation object, or an individual plugin. 282 Foundation.MediaQuery._init(); 283 Foundation.reflow(this); 284 } else if (type === 'string') { 285 //an individual method to invoke on a plugin or group of plugins 286 var args = Array.prototype.slice.call(arguments, 1); //collect all the arguments, if necessary 287 var plugClass = this.data('zfPlugin'); //determine the class of plugin 288 289 if (plugClass !== undefined && plugClass[method] !== undefined) { 290 //make sure both the class and method exist 291 if (this.length === 1) { 292 //if there's only one, call it directly. 293 plugClass[method].apply(plugClass, args); 294 } else { 295 this.each(function (i, el) { 296 //otherwise loop through the jQuery collection and invoke the method on each 297 plugClass[method].apply($(el).data('zfPlugin'), args); 298 }); 299 } 300 } else { 301 //error for no class or no method 302 throw new ReferenceError("We're sorry, '" + method + "' is not an available method for " + (plugClass ? functionName(plugClass) : 'this element') + '.'); 303 } 304 } else { 305 //error for invalid argument type 306 throw new TypeError('We\'re sorry, ' + type + ' is not a valid parameter. You must use a string representing the method you wish to invoke.'); 307 } 308 return this; 309 }; 310 311 window.Foundation = Foundation; 312 $.fn.foundation = foundation; 313 314 // Polyfill for requestAnimationFrame 315 (function () { 316 if (!Date.now || !window.Date.now) window.Date.now = Date.now = function () { 317 return new Date().getTime(); 318 }; 319 320 var vendors = ['webkit', 'moz']; 321 for (var i = 0; i < vendors.length && !window.requestAnimationFrame; ++i) { 322 var vp = vendors[i]; 323 window.requestAnimationFrame = window[vp + 'RequestAnimationFrame']; 324 window.cancelAnimationFrame = window[vp + 'CancelAnimationFrame'] || window[vp + 'CancelRequestAnimationFrame']; 325 } 326 if (/iP(ad|hone|od).*OS 6/.test(window.navigator.userAgent) || !window.requestAnimationFrame || !window.cancelAnimationFrame) { 327 var lastTime = 0; 328 window.requestAnimationFrame = function (callback) { 329 var now = Date.now(); 330 var nextTime = Math.max(lastTime + 16, now); 331 return setTimeout(function () { 332 callback(lastTime = nextTime); 333 }, nextTime - now); 334 }; 335 window.cancelAnimationFrame = clearTimeout; 336 } 337 /** 338 * Polyfill for performance.now, required by rAF 339 */ 340 if (!window.performance || !window.performance.now) { 341 window.performance = { 342 start: Date.now(), 343 now: function () { 344 return Date.now() - this.start; 345 } 346 }; 347 } 348 })(); 349 if (!Function.prototype.bind) { 350 Function.prototype.bind = function (oThis) { 351 if (typeof this !== 'function') { 352 // closest thing possible to the ECMAScript 5 353 // internal IsCallable function 354 throw new TypeError('Function.prototype.bind - what is trying to be bound is not callable'); 355 } 356 357 var aArgs = Array.prototype.slice.call(arguments, 1), 358 fToBind = this, 359 fNOP = function () {}, 360 fBound = function () { 361 return fToBind.apply(this instanceof fNOP ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments))); 362 }; 363 364 if (this.prototype) { 365 // native functions don't have a prototype 366 fNOP.prototype = this.prototype; 367 } 368 fBound.prototype = new fNOP(); 369 370 return fBound; 371 }; 372 } 373 // Polyfill to get the name of a function in IE9 374 function functionName(fn) { 375 if (Function.prototype.name === undefined) { 376 var funcNameRegex = /function\s([^(]{1,})\(/; 377 var results = funcNameRegex.exec(fn.toString()); 378 return results && results.length > 1 ? results[1].trim() : ""; 379 } else if (fn.prototype === undefined) { 380 return fn.constructor.name; 381 } else { 382 return fn.prototype.constructor.name; 383 } 384 } 385 function parseValue(str) { 386 if ('true' === str) return true;else if ('false' === str) return false;else if (!isNaN(str * 1)) return parseFloat(str); 387 return str; 388 } 389 // Convert PascalCase to kebab-case 390 // Thank you: http://stackoverflow.com/a/8955580 391 function hyphenate(str) { 392 return str.replace(/([a-z])([A-Z])/g, '$1-$2').toLowerCase(); 393 } 394}(jQuery); 395'use strict'; 396 397!function ($) { 398 399 // Default set of media queries 400 var defaultQueries = { 401 'default': 'only screen', 402 landscape: 'only screen and (orientation: landscape)', 403 portrait: 'only screen and (orientation: portrait)', 404 retina: 'only screen and (-webkit-min-device-pixel-ratio: 2),' + 'only screen and (min--moz-device-pixel-ratio: 2),' + 'only screen and (-o-min-device-pixel-ratio: 2/1),' + 'only screen and (min-device-pixel-ratio: 2),' + 'only screen and (min-resolution: 192dpi),' + 'only screen and (min-resolution: 2dppx)' 405 }; 406 407 var MediaQuery = { 408 queries: [], 409 410 current: '', 411 412 /** 413 * Initializes the media query helper, by extracting the breakpoint list from the CSS and activating the breakpoint watcher. 414 * @function 415 * @private 416 */ 417 _init: function () { 418 var self = this; 419 var extractedStyles = $('.foundation-mq').css('font-family'); 420 var namedQueries; 421 422 namedQueries = parseStyleToObject(extractedStyles); 423
424 for (var key in namedQueries) { 425 if (namedQueries.hasOwnProperty(key)) { 426 self.queries.push({ 427 name: key, 428 value: 'only screen and (min-width: ' + namedQueries[key] + ')' 429 }); 430 } 431 } 432 433 this.current = this._getCurrentSize(); 434 435 this._watcher(); 436 }, 437 438 439 /** 440 * Checks if the screen is at least as wide as a breakpoint. 441 * @function 442 * @param {String} size - Name of the breakpoint to check. 443 * @returns {Boolean} `true` if the breakpoint matches, `false` if it's smaller. 444 */ 445 atLeast: function (size) { 446 var query = this.get(size); 447 448 if (query) { 449 return window.matchMedia(query).matches; 450 } 451 452 return false; 453 }, 454 455 456 /** 457 * Checks if the screen matches to a breakpoint. 458 * @function 459 * @param {String} size - Name of the breakpoint to check, either 'small only' or 'small'. Omitting 'only' falls back to using atLeast() method. 460 * @returns {Boolean} `true` if the breakpoint matches, `false` if it does not. 461 */ 462 is: function (size) { 463 size = size.trim().split(' '); 464 if (size.length > 1 && size[1] === 'only') { 465 if (size[0] === this._getCurrentSize()) return true; 466 } else { 467 return this.atLeast(size[0]); 468 } 469 return false; 470 }, 471 472 473 /** 474 * Gets the media query of a breakpoint. 475 * @function 476 * @param {String} size - Name of the breakpoint to get. 477 * @returns {String|null} - The media query of the breakpoint, or `null` if the breakpoint doesn't exist. 478 */ 479 get: function (size) { 480 for (var i in this.queries) { 481 if (this.queries.hasOwnProperty(i)) { 482 var query = this.queries[i]; 483 if (size === query.name) return query.value; 484 } 485 } 486 487 return null; 488 }, 489 490 491 /** 492 * Gets the current breakpoint name by testing every breakpoint and returning the last one to match (the biggest one). 493 * @function 494 * @private 495 * @returns {String} Name of the current breakpoint. 496 */ 497 _getCurrentSize: function () { 498 var matched; 499 500 for (var i = 0; i < this.queries.length; i++) { 501 var query = this.queries[i]; 502 503 if (window.matchMedia(query.value).matches) { 504 matched = query; 505 } 506 } 507 508 if (typeof matched === 'object') { 509 return matched.name; 510 } else { 511 return matched; 512 } 513 }, 514 515 516 /** 517 * Activates the breakpoint watcher, which fires an event on the window whenever the breakpoint changes. 518 * @function 519 * @private 520 */ 521 _watcher: function () { 522 var _this = this; 523 524 $(window).on('resize.zf.mediaquery', function () { 525 var newSize = _this._getCurrentSize(), 526 currentSize = _this.current; 527 528 if (newSize !== currentSize) { 529 // Change the current media query 530 _this.current = newSize; 531 532 // Broadcast the media query change on the window 533 $(window).trigger('changed.zf.mediaquery', [newSize, currentSize]); 534 } 535 }); 536 } 537 }; 538 539 Foundation.MediaQuery = MediaQuery; 540 541 // matchMedia() polyfill - Test a CSS media type/query in JS. 542 // Authors & copyright (c) 2012: Scott Jehl, Paul Irish, Nicholas Zakas, David Knight. Dual MIT/BSD license 543 window.matchMedia || (window.matchMedia = function () { 544 'use strict'; 545 546 // For browsers that support matchMedium api such as IE 9 and webkit 547 548 var styleMedia = window.styleMedia || window.media; 549 550 // For those that don't support matchMedium 551 if (!styleMedia) { 552 var style = document.createElement('style'), 553 script = document.getElementsByTagName('script')[0], 554 info = null; 555 556 style.type = 'text/css'; 557 style.id = 'matchmediajs-test'; 558 559 script && script.parentNode && script.parentNode.insertBefore(style, script); 560 561 // 'style.currentStyle' is used by IE <= 8 and 'window.getComputedStyle' for all other browsers 562 info = 'getComputedStyle' in window && window.getComputedStyle(style, null) || style.currentStyle; 563 564 styleMedia = { 565 matchMedium: function (media) { 566 var text = '@media ' + media + '{ #matchmediajs-test { width: 1px; } }'; 567 568 // 'style.styleSheet' is used by IE <= 8 and 'style.textContent' for all other browsers 569 if (style.styleSheet) { 570 style.styleSheet.cssText = text; 571 } else { 572 style.textContent = text; 573 } 574 575 // Test if media query is true or false 576 return info.width === '1px'; 577 } 578 }; 579 } 580 581 return function (media) { 582 return { 583 matches: styleMedia.matchMedium(media || 'all'), 584 media: media || 'all' 585 }; 586 }; 587 }()); 588 589 // Thank you: https://github.com/sindresorhus/query-string 590 function parseStyleToObject(str) { 591 var styleObject = {}; 592 593 if (typeof str !== 'string') { 594 return styleObject; 595 } 596 597 str = str.trim().slice(1, -1);
597 // browsers re-quote string style values 598 599 if (!str) { 600 return styleObject; 601 } 602 603 styleObject = str.split('&').reduce(function (ret, param) { 604 var parts = param.replace(/\+/g, ' ').split('='); 605 var key = parts[0]; 606 var val = parts[1]; 607 key = decodeURIComponent(key); 608 609 // missing `=` should be `null`: 610 // http://w3.org/TR/2012/WD-url-20120524/#collect-url-parameters 611 val = val === undefined ? null : decodeURIComponent(val); 612 613 if (!ret.hasOwnProperty(key)) { 614 ret[key] = val; 615 } else if (Array.isArray(ret[key])) { 616 ret[key].push(val); 617 } else { 618 ret[key] = [ret[key], val]; 619 } 620 return ret; 621 }, {}); 622 623 return styleObject; 624 } 625 626 Foundation.MediaQuery = MediaQuery; 627}(jQuery); 628/* 629 * This content is licensed according to the W3C Software License at 630 * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document 631 * 632 * File: tabs-manual.js 633 * 634 * Desc: Tablist widget that implements ARIA Authoring Practices 635 */ 636 637'use strict'; 638 639class TabsManual { 640 constructor(groupNode) { 641 this.tablistNode = groupNode; 642 643 this.tabs = []; 644 645 this.firstTab = null; 646 this.lastTab = null; 647 648 this.tabs = Array.from(this.tablistNode.querySelectorAll('[role=tab]')); 649 this.tabpanels = []; 650 651 for (var i = 0; i < this.tabs.length; i += 1) { 652 var tab = this.tabs[i]; 653 var tabpanel = document.getElementById(tab.getAttribute('aria-controls')); 654 655 tab.tabIndex = -1; 656 tab.setAttribute('aria-selected', 'false'); 657 this.tabpanels.push(tabpanel); 658 659 tab.addEventListener('keydown', this.onKeydown.bind(this)); 660 tab.addEventListener('click', this.onClick.bind(this)); 661 662 if (!this.firstTab) { 663 this.firstTab = tab; 664 } 665 this.lastTab = tab; 666 } 667 668 this.setSelectedTab(this.firstTab); 669 } 670 671 setSelectedTab(currentTab) { 672 for (var i = 0; i < this.tabs.length; i += 1) { 673 var tab = this.tabs[i]; 674 if (currentTab === tab) { 675 tab.setAttribute('aria-selected', 'true'); 676 tab.removeAttribute('tabindex'); 677 this.tabpanels[i].classList.remove('is-hidden'); 678 } else { 679 tab.setAttribute('aria-selected', 'false'); 680 tab.tabIndex = -1; 681 this.tabpanels[i].classList.add('is-hidden'); 682 } 683 } 684 } 685 686 moveFocusToTab(currentTab) { 687 currentTab.focus(); 688 } 689 690 moveFocusToPreviousTab(currentTab) { 691 var index; 692 693 if (currentTab === this.firstTab) { 694 this.moveFocusToTab(this.lastTab); 695 } else { 696 index = this.tabs.indexOf(currentTab); 697 this.moveFocusToTab(this.tabs[index - 1]); 698 } 699 } 700 701 moveFocusToNextTab(currentTab) { 702 var index; 703 704 if (currentTab === this.lastTab) { 705 this.moveFocusToTab(this.firstTab); 706 } else { 707 index = this.tabs.indexOf(currentTab); 708 this.moveFocusToTab(this.tabs[index + 1]); 709 } 710 } 711 712 /* EVENT HANDLERS */ 713 714 onKeydown(event) { 715 var tgt = event.currentTarget, 716 flag = false; 717 718 switch (event.key) { 719 case 'ArrowLeft': 720 this.moveFocusToPreviousTab(tgt); 721 flag = true; 722 break; 723 724 case 'ArrowRight': 725 this.moveFocusToNextTab(tgt); 726 flag = true; 727 break; 728 729 case 'Home': 730 this.moveFocusToTab(this.firstTab); 731 flag = true; 732 break; 733 734 case 'End': 735 this.moveFocusToTab(this.lastTab); 736 flag = true; 737 break; 738 739 default: 740 break; 741 } 742 743 if (flag) { 744 event.stopPropagation(); 745 event.preventDefault(); 746 } 747 } 748 749 // Since this example uses buttons for the tabs, the click onr also is activated 750 // with the space and enter keys 751 onClick(event) { 752 this.setSelectedTab(event.currentTarget); 753 } 754} 755 756// Initialize tablist 757 758window.addEventListener('load', function () { 759 var tablists = document.querySelectorAll('[role=tablist].manual'); 760 for (var i = 0; i < tablists.length; i++) { 761 new TabsManual(tablists[i]); 762 } 763}); 764 765'use strict'; 766 767var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 768 769function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 770 771!function ($) { 772 773 /** 774 * Orbit module. 775 * @module foundation.orbit 776 * @requires foundation.util.keyboard 777 * @requires foundation.util.motion 778 * @requires foundation.util.timerAndImageLoader 779 * @requires foundation.util.touch 780 */ 781 782 var Orbit = function () { 783 /** 784 * Creates a new instance of an orbit carousel. 785 * @class 786 * @param {jQuery} element - jQuery object to make into an Orbit Carousel. 787 * @param {Object} options - Overrides to the default plugin settings. 788 */ 789 function Orbit(element, options) { 790 _classCallCheck(this, Orbit); 791 792 this.$element = element; 793 this.options = $.extend({}, Orbit.defaults, this.$element.data(), options); 794 795 this._init(); 796
797 Foundation.registerPlugin(this, 'Orbit'); 798 Foundation.Keyboard.register('Orbit', { 799 'ltr': { 800 'ARROW_RIGHT': 'next', 801 'ARROW_LEFT': 'previous' 802 }, 803 'rtl': { 804 'ARROW_LEFT': 'next', 805 'ARROW_RIGHT': 'previous' 806 } 807 }); 808 } 809 810 /** 811 * Initializes the plugin by creating jQuery collections, setting attributes, and starting the animation. 812 * @function 813 * @private 814 */ 815 816 817 _createClass(Orbit, [{ 818 key: '_init', 819 value: function _init() { 820 // @TODO: consider discussion on PR #9278 about DOM pollution by changeSlide 821 this._reset(); 822 823 this.$wrapper = this.$element.find('.' + this.options.containerClass); 824 this.$slides = this.$element.find('.' + this.options.slideClass); 825 826 var $images = this.$element.find('img'), 827 initActive = this.$slides.filter('.is-active'), 828 id = this.$element[0].id || Foundation.GetYoDigits(6, 'orbit'); 829 830 this.$element.attr({ 831 'data-resize': id, 832 'id': id 833 }); 834 835 if (!initActive.length) { 836 this.$slides.eq(0).addClass('is-active'); 837 } 838 839 if (!this.options.useMUI) { 840 this.$slides.addClass('no-motionui'); 841 } 842 843 if ($images.length) { 844 Foundation.onImagesLoaded($images, this._prepareForOrbit.bind(this)); 845 } else { 846 this._prepareForOrbit(); //hehe 847 } 848 849 if (this.options.bullets) { 850 this._loadBullets(); 851 } 852 853 this._events(); 854 855 if (this.options.autoPlay && this.$slides.length > 1) { 856 this.geoSync(); 857 } 858 859 if (this.options.accessible) { 860 // allow wrapper to be focusable to enable arrow navigation 861 this.$wrapper.attr('tabindex', 0); 862 } 863 } 864 865 /** 866 * Creates a jQuery collection of bullets, if they are being used. 867 * @function 868 * @private 869 */ 870 871 }, { 872 key: '_loadBullets', 873 value: function _loadBullets() { 874 this.$bullets = this.$element.find('.' + this.options.boxOfBullets).find('button'); 875 } 876 877 /** 878 * Sets a `timer` object on the orbit, and starts the counter for the next slide. 879 * @function 880 */ 881 882 }, { 883 key: 'geoSync', 884 value: function geoSync() { 885 var _this = this; 886 this.timer = new Foundation.Timer(this.$element, { 887 duration: this.options.timerDelay, 888 infinite: false 889 }, function () { 890 _this.changeSlide(true); 891 }); 892 this.timer.start(); 893 } 894 895 /** 896 * Sets wrapper and slide heights for the orbit. 897 * @function 898 * @private 899 */ 900 901 }, { 902 key: '_prepareForOrbit', 903 value: function _prepareForOrbit() { 904 var _this = this; 905 this._setWrapperHeight(); 906 } 907 908 /** 909 * Calulates the height of each slide in the collection, and uses the tallest one for the wrapper height. 910 * @function 911 * @private 912 * @param {Function} cb - a callback function to fire when complete. 913 */ 914 915 }, { 916 key: '_setWrapperHeight', 917 value: function _setWrapperHeight(cb) { 918 //rewrite this to `for` loop 919 var max = 0, 920 temp, 921 counter = 0, 922 _this = this; 923 924 this.$slides.each(function () { 925 temp = this.getBoundingClientRect().height; 926 $(this).attr('data-slide', counter); 927 928 if (_this.$slides.filter('.is-active')[0] !== _this.$slides.eq(counter)[0]) { 929 //if not the active slide, set css position and display property 930 $(this).css({ 'position': 'relative', 'display': 'none' }); 931 } 932 max = temp > max ? temp : max; 933 counter++; 934 }); 935 936 if (counter === this.$slides.length) { 937 this.$wrapper.css({ 'height': max }); //only change the wrapper height property once. 938 if (cb) { 939 cb(max); 940 } //fire callback with max height dimension. 941 } 942 } 943 944 /** 945 * Sets the max-height of each slide. 946 * @function 947 * @private 948 */ 949 950 }, {
vendor: 5,174 bytes, lines 951-1100
951 key: '_setSlideHeight', 952 value: function _setSlideHeight(height) { 953 this.$slides.each(function () { 954 $(this).css('max-height', height); 955 }); 956 } 957 958 /** 959 * Adds event listeners to basically everything within the element. 960 * @function 961 * @private 962 */ 963 964 }, { 965 key: '_events', 966 value: function _events() { 967 var _this = this; 968 969 //*************************************** 970 //**Now using custom event - thanks to:** 971 //** Yohai Ararat of Toronto ** 972 //*************************************** 973 // 974 this.$element.off('.resizeme.zf.trigger').on({ 975 'resizeme.zf.trigger': this._prepareForOrbit.bind(this) 976 }); 977 if (this.$slides.length > 1) { 978 979 if (this.options.swipe) { 980 this.$slides.off('swipeleft.zf.orbit swiperight.zf.orbit').on('swipeleft.zf.orbit', function (e) { 981 e.preventDefault(); 982 _this.changeSlide(true); 983 }).on('swiperight.zf.orbit', function (e) { 984 e.preventDefault(); 985 _this.changeSlide(false); 986 }); 987 } 988 //*************************************** 989 990 if (this.options.autoPlay) { 991 this.$slides.on('click.zf.orbit', function () { 992 _this.$element.data('clickedOn', _this.$element.data('clickedOn') ? false : true); 993 _this.timer[_this.$element.data('clickedOn') ? 'pause' : 'start'](); 994 }); 995 996 if (this.options.pauseOnHover) { 997 this.$element.on('mouseenter.zf.orbit', function () { 998 _this.timer.pause(); 999 }).on('mouseleave.zf.orbit', function () { 1000 if (!_this.$element.data('clickedOn')) { 1001 _this.timer.start(); 1002 } 1003 }); 1004 } 1005 } 1006 1007 if (this.options.navButtons) { 1008 var $controls = this.$element.find('.' + this.options.nextClass + ', .' + this.options.prevClass); 1009 $controls.attr('tabindex', 0) 1010 //also need to handle enter/return and spacebar key presses 1011 .on('click.zf.orbit touchend.zf.orbit', function (e) { 1012 e.preventDefault(); 1013 _this.changeSlide($(this).hasClass(_this.options.nextClass)); 1014 }); 1015 } 1016 1017 if (this.options.bullets) { 1018 this.$bullets.on('click.zf.orbit touchend.zf.orbit', function () { 1019 if (/is-active/g.test(this.className)) { 1020 return false; 1021 } //if this is active, kick out of function. 1022 var idx = $(this).data('slide'), 1023 ltr = idx > _this.$slides.filter('.is-active').data('slide'), 1024 $slide = _this.$slides.eq(idx); 1025 1026 _this.changeSlide(ltr, $slide, idx); 1027 }); 1028 } 1029 1030 if (this.options.accessible) { 1031 this.$wrapper.add(this.$bullets).on('keydown.zf.orbit', function (e) { 1032 // handle keyboard event with keyboard util 1033 Foundation.Keyboard.handleKey(e, 'Orbit', { 1034 next: function () { 1035 _this.changeSlide(true); 1036 }, 1037 previous: function () { 1038 _this.changeSlide(false); 1039 }, 1040 handled: function () { 1041 // if bullet is focused, make sure focus moves 1042 if ($(e.target).is(_this.$bullets)) { 1043 _this.$bullets.filter('.is-active').focus(); 1044 } 1045 } 1046 }); 1047 }); 1048 } 1049 } 1050 } 1051 1052 /** 1053 * Resets Orbit so it can be reinitialized 1054 */ 1055 1056 }, { 1057 key: '_reset', 1058 value: function _reset() { 1059 // Don't do anything if there are no slides (first run) 1060 if (typeof this.$slides == 'undefined') { 1061 return; 1062 } 1063 1064 if (this.$slides.length > 1) { 1065 // Remove old events 1066 this.$element.off('.zf.orbit').find('*').off('.zf.orbit'); 1067 1068 // Restart timer if autoPlay is enabled 1069 if (this.options.autoPlay) { 1070 this.timer.restart(); 1071 } 1072 1073 // Reset all sliddes 1074 this.$slides.each(function (el) { 1075 $(el).removeClass('is-active is-active is-in').removeAttr('aria-live').hide(); 1076 }); 1077 1078 // Show the first slide 1079 this.$slides.first().addClass('is-active').show(); 1080 1081 // Triggers when the slide has finished animating 1082 this.$element.trigger('slidechange.zf.orbit', [this.$slides.first()]); 1083 1084 // Select first bullet if bullets are present 1085 if (this.options.bullets) { 1086 this._updateBullets(0); 1087 } 1088 } 1089 } 1090 1091 /** 1092 * Changes the current slide to a new one. 1093 * @function 1094 * @param {Boolean} isLTR - flag if the slide should move left to right. 1095 * @param {jQuery} chosenSlide - the jQuery element of the slide to show next, if one is selected. 1096 * @param {Number} idx - the index of the new slide in its collection, if one chosen. 1097 * @fires Orbit#slidechange 1098 */ 1099 1100 }, {
1101 key: 'changeSlide', 1102 value: function changeSlide(isLTR, chosenSlide, idx) { 1103 if (!this.$slides) { 1104 return; 1105 } // Don't freak out if we're in the middle of cleanup 1106 var $curSlide = this.$slides.filter('.is-active').eq(0); 1107 1108 if (/mui/g.test($curSlide[0].className)) { 1109 return false; 1110 } //if the slide is currently animating, kick out of the function 1111 1112 var $firstSlide = this.$slides.first(), 1113 $lastSlide = this.$slides.last(), 1114 dirIn = isLTR ? 'Right' : 'Left', 1115 dirOut = isLTR ? 'Left' : 'Right', 1116 _this = this, 1117 $newSlide; 1118 1119 if (!chosenSlide) { 1120 //most of the time, this will be auto played or clicked from the navButtons. 1121 $newSlide = isLTR ? //if wrapping enabled, check to see if there is a `next` or `prev` sibling, if not, select the first or last slide to fill in. if wrapping not enabled, attempt to select `next` or `prev`, if there's nothing there, the function will kick out on next step. CRAZY NESTED TERNARIES!!!!! 1122 this.options.infiniteWrap ? $curSlide.next('.' + this.options.slideClass).length ? $curSlide.next('.' + this.options.slideClass) : $firstSlide : $curSlide.next('.' + this.options.slideClass) : //pick next slide if moving left to right 1123 this.options.infiniteWrap ? $curSlide.prev('.' + this.options.slideClass).length ? $curSlide.prev('.' + this.options.slideClass) : $lastSlide : $curSlide.prev('.' + this.options.slideClass); //pick prev slide if moving right to left 1124 } else { 1125 $newSlide = chosenSlide; 1126 } 1127 1128 if ($newSlide.length) { 1129 /** 1130 * Triggers before the next slide starts animating in and only if a next slide has been found. 1131 * @event Orbit#beforeslidechange 1132 */ 1133 this.$element.trigger('beforeslidechange.zf.orbit', [$curSlide, $newSlide]); 1134 1135 if (this.options.bullets) { 1136 idx = idx || this.$slides.index($newSlide); //grab index to update bullets 1137 this._updateBullets(idx); 1138 } 1139 1140 if (this.options.useMUI && !this.$element.is(':hidden')) { 1141 Foundation.Motion.animateIn($newSlide.addClass('is-active').css({ 'position': 'absolute', 'top': 0 }), this.options['animInFrom' + dirIn], function () { 1142 $newSlide.css({ 'position': 'relative', 'display': 'block' }).attr('aria-live', 'polite'); 1143 }); 1144 1145 Foundation.Motion.animateOut($curSlide.removeClass('is-active'), this.options['animOutTo' + dirOut], function () { 1146 $curSlide.removeAttr('aria-live'); 1147 if (_this.options.autoPlay && !_this.timer.isPaused) { 1148 _this.timer.restart(); 1149 } 1150 //do stuff? 1151 }); 1152 } else { 1153 $curSlide.removeClass('is-active is-in').removeAttr('aria-live').hide(); 1154 $newSlide.addClass('is-active is-in').attr('aria-live', 'polite').show(); 1155 if (this.options.autoPlay && !this.timer.isPaused) { 1156 this.timer.restart(); 1157 } 1158 } 1159 /** 1160 * Triggers when the slide has finished animating in. 1161 * @event Orbit#slidechange 1162 */ 1163 this.$element.trigger('slidechange.zf.orbit', [$newSlide]); 1164 } 1165 } 1166 1167 /** 1168 * Updates the active state of the bullets, if displayed. 1169 * @function 1170 * @private 1171 * @param {Number} idx - the index of the current slide. 1172 */ 1173 1174 }, { 1175 key: '_updateBullets', 1176 value: function _updateBullets(idx) { 1177 var $oldBullet = this.$element.find('.' + this.options.boxOfBullets).find('.is-active').removeClass('is-active').blur(), 1178 span = $oldBullet.find('span:last').detach(), 1179 $newBullet = this.$bullets.eq(idx).addClass('is-active').append(span); 1180 } 1181 1182 /** 1183 * Destroys the carousel and hides the element. 1184 * @function 1185 */ 1186 1187 }, { 1188 key: 'destroy', 1189 value: function destroy() { 1190 this.$element.off('.zf.orbit').find('*').off('.zf.orbit').end().hide(); 1191 Foundation.unregisterPlugin(this); 1192 } 1193 }]); 1194 1195 return Orbit; 1196 }(); 1197 1198 Orbit.defaults = { 1199 /** 1200 * Tells the JS to look for and loadBullets. 1201 * @option 1202 * @type {boolean} 1203 * @default true 1204 */ 1205 bullets: true, 1206 /** 1207 * Tells the JS to apply event listeners to nav buttons 1208 * @option 1209 * @type {boolean} 1210 * @default true 1211 */ 1212 navButtons: true, 1213 /** 1214 * motion-ui animation class to apply 1215 * @option 1216 * @type {string} 1217 * @default 'slide-in-right' 1218 */ 1219 animInFromRight: 'slide-in-right', 1220 /** 1221 * motion-ui animation class to apply 1222 * @option 1223 * @type {string} 1224 * @default 'slide-out-right' 1225 */ 1226 animOutToRight: 'slide-out-right', 1227 /** 1228 * motion-ui animation class to apply 1229 * @option 1230 * @type {string} 1231 * @default 'slide-in-left' 1232 * 1233 */ 1234 animInFromLeft: 'slide-in-left', 1235 /** 1236 * motion-ui animation class to apply 1237 * @option 1238 * @type {string} 1239 * @default 'slide-out-left' 1240 */ 1241 animOutToLeft: 'slide-out-left', 1242 /** 1243 * Allows Orbit to automatically animate on page load. 1244 * @option 1245 * @type {boolean} 1246 * @default true 1247 */ 1248 autoPlay: true, 1249 /** 1250 * Amount of time, in ms, between slide transitions 1251 * @option 1252 * @type {number} 1253 * @default 5000 1254 */ 1255 timerDelay: 5000, 1256 /** 1257 * Allows Orbit to infinitely loop through the slides 1258 * @option 1259 * @type {boolean} 1260 * @default true 1261 */ 1262 infiniteWrap: true, 1263 /** 1264 * Allows the Orbit slides to bind to swipe events for mobile, requires an additional util library 1265 * @option 1266 * @type {boolean} 1267 * @default true 1268 */ 1269 swipe: true, 1270 /** 1271 * Allows the timing function to pause animation on hover. 1272 * @option 1273 * @type {boolean} 1274 * @default true 1275 */ 1276 pauseOnHover: true, 1277 /** 1278 * Allows Orbit to bind keyboard events to the slider, to animate frames with arrow keys 1279 * @option 1280 * @type {boolean} 1281 * @default true 1282 */ 1283 accessible: true, 1284 /** 1285 * Class applied to the container of Orbit 1286 * @option 1287 * @type {string} 1288 * @default 'orbit-container' 1289 */ 1290 containerClass: 'orbit-container', 1291 /** 1292 * Class applied to individual slides. 1293 * @option 1294 * @type {string} 1295 * @default 'orbit-slide' 1296 */ 1297 slideClass: 'orbit-slide', 1298 /** 1299 * Class applied to the bullet container. You're welcome. 1300 * @option 1301 * @type {string} 1302 * @default 'orbit-bullets' 1303 */ 1304 boxOfBullets: 'orbit-bullets', 1305 /** 1306 * Class applied to the `next` navigation button. 1307 * @option 1308 * @type {string} 1309 * @default 'orbit-next' 1310 */ 1311 nextClass: 'orbit-next', 1312 /** 1313 * Class applied to the `previous` navigation button. 1314 * @option 1315 * @type {string} 1316 * @default 'orbit-previous' 1317 */ 1318 prevClass: 'orbit-previous', 1319 /** 1320 * Boolean to flag the js to use motion ui classes or not. Default to true for backwards compatability. 1321 * @option 1322 * @type {boolean} 1323 * @default true 1324 */ 1325 useMUI: true 1326 }; 1327 1328 // Window exports 1329 Foundation.plugin(Orbit, 'Orbit'); 1330}(jQuery); 1331'use strict'; 1332 1333var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 1334 1335function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1336 1337!function ($) { 1338 1339 /** 1340 * Reveal module. 1341 * @module foundation.reveal 1342 * @requires foundation.util.keyboard 1343 * @requires foundation.util.box 1344 * @requires foundation.util.triggers 1345 * @requires foundation.util.mediaQuery 1346 * @requires foundation.util.motion if using animations 1347 */ 1348 1349 var Reveal = function () { 1350 /** 1351 * Creates a new instance of Reveal. 1352 * @class 1353 * @param {jQuery} element - jQuery object to use for the modal. 1354 * @param {Object} options - optional parameters. 1355 */ 1356 function Reveal(element, options) { 1357 _classCallCheck(this, Reveal); 1358 1359 this.$element = element; 1360 this.options = $.extend({}, Reveal.defaults, this.$element.data(), options); 1361 this._init(); 1362 1363 Foundation.registerPlugin(this, 'Reveal'); 1364 Foundation.Keyboard.register('Reveal', { 1365 'ENTER': 'open', 1366 'SPACE': 'open', 1367 'ESCAPE': 'close' 1368 }); 1369 } 1370 1371 /** 1372 * Initializes the modal by adding the overlay and close buttons, (if selected). 1373 * @private 1374 */ 1375 1376 1377 _createClass(Reveal, [{ 1378 key: '_init', 1379 value: function _init() { 1380 this.id = this.$element.attr('id'); 1381 this.isActive = false;
1382 this.cached = { mq: Foundation.MediaQuery.current }; 1383 this.isMobile = mobileSniff(); 1384 1385 this.$anchor = $('[data-open="' + this.id + '"]').length ? $('[data-open="' + this.id + '"]') : $('[data-toggle="' + this.id + '"]'); 1386 this.$anchor.attr({ 1387 'aria-controls': this.id, 1388 'aria-haspopup': true, 1389 'tabindex': 0 1390 }); 1391 1392 if (this.options.fullScreen || this.$element.hasClass('full')) { 1393 this.options.fullScreen = true; 1394 this.options.overlay = false; 1395 } 1396 if (this.options.overlay && !this.$overlay) { 1397 this.$overlay = this._makeOverlay(this.id); 1398 } 1399 1400 this.$element.attr({ 1401 'role': 'dialog', 1402 'aria-hidden': true, 1403 'data-yeti-box': this.id, 1404 'data-resize': this.id 1405 }); 1406 1407 if (this.$overlay) { 1408 this.$element.detach().appendTo(this.$overlay); 1409 } else { 1410 this.$element.detach().appendTo($(this.options.appendTo)); 1411 this.$element.addClass('without-overlay'); 1412 } 1413 this._events(); 1414 if (this.options.deepLink && window.location.hash === '#' + this.id) { 1415 $(window).one('load.zf.reveal', this.open.bind(this)); 1416 } 1417 } 1418 1419 /** 1420 * Creates an overlay div to display behind the modal. 1421 * @private 1422 */ 1423 1424 }, { 1425 key: '_makeOverlay', 1426 value: function _makeOverlay() { 1427 return $('<div></div>').addClass('reveal-overlay').appendTo(this.options.appendTo); 1428 } 1429 1430 /** 1431 * Updates position of modal 1432 * TODO: Figure out if we actually need to cache these values or if it doesn't matter 1433 * @private 1434 */ 1435 1436 }, { 1437 key: '_updatePosition', 1438 value: function _updatePosition() { 1439 var width = this.$element.outerWidth(); 1440 var outerWidth = $(window).width(); 1441 var height = this.$element.outerHeight(); 1442 var outerHeight = $(window).height(); 1443 var left, top; 1444 if (this.options.hOffset === 'auto') { 1445 left = parseInt((outerWidth - width) / 2, 10); 1446 } else { 1447 left = parseInt(this.options.hOffset, 10); 1448 } 1449 if (this.options.vOffset === 'auto') { 1450 if (height > outerHeight) { 1451 top = parseInt(Math.min(100, outerHeight / 10), 10); 1452 } else { 1453 top = parseInt((outerHeight - height) / 4, 10); 1454 } 1455 } else { 1456 top = parseInt(this.options.vOffset, 10); 1457 } 1458 this.$element.css({ top: top + 'px' }); 1459 // only worry about left if we don't have an overlay or we havea horizontal offset, 1460 // otherwise we're perfectly in the middle 1461 if (!this.$overlay || this.options.hOffset !== 'auto') { 1462 this.$element.css({ left: left + 'px' }); 1463 this.$element.css({ margin: '0px' }); 1464 } 1465 } 1466 1467 /** 1468 * Adds event handlers for the modal. 1469 * @private 1470 */ 1471 1472 }, { 1473 key: '_events', 1474 value: function _events() { 1475 var _this2 = this; 1476 1477 var _this = this; 1478 1479 this.$element.on({ 1480 'open.zf.trigger': this.open.bind(this), 1481 'close.zf.trigger': function (event, $element) { 1482 if (event.target === _this.$element[0] || $(event.target).parents('[data-closable]')[0] === $element) { 1483 // only close reveal when it's explicitly called 1484 return _this2.close.apply(_this2); 1485 } 1486 }, 1487 'toggle.zf.trigger': this.toggle.bind(this), 1488 'resizeme.zf.trigger': function () { 1489 _this._updatePosition(); 1490 } 1491 }); 1492 1493 if (this.$anchor.length) { 1494 this.$anchor.on('keydown.zf.reveal', function (e) { 1495 if (e.which === 13 || e.which === 32) { 1496 e.stopPropagation(); 1497 e.preventDefault(); 1498 _this.open(); 1499 } 1500 }); 1501 } 1502 1503 if (this.options.closeOnClick && this.options.overlay) { 1504 this.$overlay.off('.zf.reveal').on('click.zf.reveal', function (e) { 1505 if (e.target === _this.$element[0] || $.contains(_this.$element[0], e.target) || !$.contains(document, e.target)) { 1506 return; 1507 } 1508 _this.close(); 1509 }); 1510 } 1511 if (this.options.deepLink) { 1512 $(window).on('popstate.zf.reveal:' + this.id, this._handleState.bind(this)); 1513 } 1514 } 1515 1516 /** 1517 * Handles modal methods on back/forward button clicks or any other event that triggers popstate. 1518 * @private 1519 */ 1520 1521 }, {
1522 key: '_handleState', 1523 value: function _handleState(e) { 1524 if (window.location.hash === '#' + this.id && !this.isActive) { 1525 this.open(); 1526 } else { 1527 this.close(); 1528 } 1529 } 1530 1531 /** 1532 * Opens the modal controlled by `this.$anchor`, and closes all others by default. 1533 * @function 1534 * @fires Reveal#closeme 1535 * @fires Reveal#open 1536 */ 1537 1538 }, { 1539 key: 'open', 1540 value: function open() { 1541 var _this3 = this; 1542 1543 if (this.options.deepLink) { 1544 var hash = '#' + this.id; 1545 1546 if (window.history.pushState) { 1547 window.history.pushState(null, null, hash); 1548 } else { 1549 window.location.hash = hash; 1550 } 1551 } 1552 1553 this.isActive = true; 1554 1555 // Make elements invisible, but remove display: none so we can get size and positioning 1556 this.$element.css({ 'visibility': 'hidden' }).show().scrollTop(0); 1557 if (this.options.overlay) { 1558 this.$overlay.css({ 'visibility': 'hidden' }).show(); 1559 } 1560 1561 this._updatePosition(); 1562 1563 this.$element.hide().css({ 'visibility': '' }); 1564 1565 if (this.$overlay) { 1566 this.$overlay.css({ 'visibility': '' }).hide(); 1567 if (this.$element.hasClass('fast')) { 1568 this.$overlay.addClass('fast'); 1569 } else if (this.$element.hasClass('slow')) { 1570 this.$overlay.addClass('slow'); 1571 } 1572 } 1573 1574 if (!this.options.multipleOpened) { 1575 /** 1576 * Fires immediately before the modal opens. 1577 * Closes any other modals that are currently open 1578 * @event Reveal#closeme 1579 */ 1580 this.$element.trigger('closeme.zf.reveal', this.id); 1581 } 1582 1583 var _this = this; 1584 1585 function addRevealOpenClasses() { 1586 if (_this.isMobile) { 1587 if (!_this.originalScrollPos) { 1588 _this.originalScrollPos = window.pageYOffset; 1589 } 1590 $('html, body').addClass('is-reveal-open'); 1591 } else { 1592 $('body').addClass('is-reveal-open'); 1593 } 1594 } 1595 // Motion UI method of reveal 1596 if (this.options.animationIn) { 1597 (function () { 1598 var afterAnimation = function () { 1599 _this.$element.attr({ 1600 'aria-hidden': false, 1601 'tabindex': -1 1602 }).focus(); 1603 addRevealOpenClasses(); 1604 Foundation.Keyboard.trapFocus(_this.$element); 1605 }; 1606 1607 if (_this3.options.overlay) { 1608 Foundation.Motion.animateIn(_this3.$overlay, 'fade-in'); 1609 } 1610 Foundation.Motion.animateIn(_this3.$element, _this3.options.animationIn, function () { 1611 if (_this3.$element) { 1612 // protect against object having been removed 1613 _this3.focusableElements = Foundation.Keyboard.findFocusable(_this3.$element); 1614 afterAnimation(); 1615 } 1616 }); 1617 })(); 1618 } 1619 // jQuery method of reveal 1620 else { 1621 if (this.options.overlay) { 1622 this.$overlay.show(0); 1623 } 1624 this.$element.show(this.options.showDelay); 1625 } 1626 1627 // handle accessibility 1628 this.$element.attr({ 1629 'aria-hidden': false, 1630 'tabindex': -1 1631 }).focus(); 1632 Foundation.Keyboard.trapFocus(this.$element); 1633 1634 /** 1635 * Fires when the modal has successfully opened. 1636 * @event Reveal#open 1637 */ 1638 this.$element.trigger('open.zf.reveal'); 1639 1640 addRevealOpenClasses(); 1641 1642 setTimeout(function () { 1643 _this3._extraHandlers(); 1644 }, 0); 1645 } 1646 1647 /** 1648 * Adds extra event handlers for the body and window if necessary. 1649 * @private 1650 */ 1651 1652 }, { 1653 key: '_extraHandlers', 1654 value: function _extraHandlers() { 1655 var _this = this; 1656 if (!this.$element) { 1657 return; 1658 } // If we're in the middle of cleanup, don't freak out 1659 this.focusableElements = Foundation.Keyboard.findFocusable(this.$element); 1660 1661 if (!this.options.overlay && this.options.closeOnClick && !this.options.fullScreen) { 1662 $('body').on('click.zf.reveal', function (e) { 1663 if (e.target === _this.$element[0] || $.contains(_this.$element[0], e.target) || !$.contains(document, e.target)) { 1664 return; 1665 } 1666 _this.close(); 1667 }); 1668 } 1669 1670 if (this.options.closeOnEsc) { 1671 $(window).on('keydown.zf.reveal', function (e) { 1672 Foundation.Keyboard.handleKey(e, 'Reveal', { 1673 close: function () { 1674 if (_this.options.closeOnEsc) { 1675 _this.close(); 1676 _this.$anchor.focus(); 1677 } 1678 } 1679 }); 1680 }); 1681 } 1682 1683 // lock focus within modal while tabbing 1684 this.$element.on('keydown.zf.reveal', function (e) { 1685 var $target = $(this); 1686 // handle keyboard event with keyboard util 1687 Foundation.Keyboard.handleKey(e, 'Reveal', { 1688 open: function () { 1689 if (_this.$element.find(':focus').is(_this.$element.find('[data-close]'))) { 1690 setTimeout(function () { 1691 // set focus back to anchor if close button has been activated 1692 _this.$anchor.focus(); 1693 }, 1); 1694 } else if ($target.is(_this.focusableElements)) { 1695 // dont't trigger if acual element has focus (i.e. inputs, links, ...) 1696 _this.open(); 1697 } 1698 }, 1699 close: function () { 1700 if (_this.options.closeOnEsc) { 1701 _this.close(); 1702 _this.$anchor.focus(); 1703 } 1704 }, 1705 handled: function (preventDefault) { 1706 if (preventDefault) { 1707 e.preventDefault(); 1708 } 1709 } 1710 }); 1711 }); 1712 } 1713 1714 /** 1715 * Closes the modal. 1716 * @function 1717 * @fires Reveal#closed 1718 */ 1719 1720 }, {
1721 key: 'close', 1722 value: function close() { 1723 if (!this.isActive || !this.$element.is(':visible')) { 1724 return false; 1725 } 1726 var _this = this; 1727 1728 // Motion UI method of hiding 1729 if (this.options.animationOut) { 1730 if (this.options.overlay) { 1731 Foundation.Motion.animateOut(this.$overlay, 'fade-out', finishUp); 1732 } else { 1733 finishUp(); 1734 } 1735 1736 Foundation.Motion.animateOut(this.$element, this.options.animationOut); 1737 } 1738 // jQuery method of hiding 1739 else { 1740 if (this.options.overlay) { 1741 this.$overlay.hide(0, finishUp); 1742 } else { 1743 finishUp(); 1744 } 1745 1746 this.$element.hide(this.options.hideDelay); 1747 } 1748 1749 // Conditionals to remove extra event listeners added on open 1750 if (this.options.closeOnEsc) { 1751 $(window).off('keydown.zf.reveal'); 1752 } 1753 1754 if (!this.options.overlay && this.options.closeOnClick) { 1755 $('body').off('click.zf.reveal'); 1756 } 1757 1758 this.$element.off('keydown.zf.reveal'); 1759 1760 function finishUp() { 1761 if (_this.isMobile) { 1762 $('html, body').removeClass('is-reveal-open'); 1763 if (_this.originalScrollPos) { 1764 $('body').scrollTop(_this.originalScrollPos); 1765 _this.originalScrollPos = null; 1766 } 1767 } else { 1768 $('body').removeClass('is-reveal-open'); 1769 } 1770 1771 Foundation.Keyboard.releaseFocus(_this.$element); 1772 1773 _this.$element.attr('aria-hidden', true); 1774 1775 /** 1776 * Fires when the modal is done closing. 1777 * @event Reveal#closed 1778 */ 1779 _this.$element.trigger('closed.zf.reveal'); 1780 } 1781 1782 /** 1783 * Resets the modal content 1784 * This prevents a running video to keep going in the background 1785 */ 1786 if (this.options.resetOnClose) { 1787 this.$element.html(this.$element.html()); 1788 } 1789 1790 this.isActive = false; 1791 if (_this.options.deepLink) { 1792 if (window.history.replaceState) { 1793 window.history.replaceState('', document.title, window.location.href.replace('#' + this.id, '')); 1794 } else { 1795 window.location.hash = ''; 1796 } 1797 } 1798 } 1799 1800 /** 1801 * Toggles the open/closed state of a modal. 1802 * @function 1803 */ 1804 1805 }, { 1806 key: 'toggle', 1807 value: function toggle() { 1808 if (this.isActive) { 1809 this.close(); 1810 } else { 1811 this.open(); 1812 } 1813 } 1814 }, { 1815 key: 'destroy', 1816 1817 1818 /** 1819 * Destroys an instance of a modal. 1820 * @function 1821 */ 1822 value: function destroy() { 1823 if (this.options.overlay) { 1824 this.$element.appendTo($(this.options.appendTo)); // move $element outside of $overlay to prevent error unregisterPlugin() 1825 this.$overlay.hide().off().remove(); 1826 } 1827 this.$element.hide().off(); 1828 this.$anchor.off('.zf'); 1829 $(window).off('.zf.reveal:' + this.id); 1830 1831 Foundation.unregisterPlugin(this); 1832 } 1833 }]); 1834 1835 return Reveal; 1836 }(); 1837 1838 Reveal.defaults = { 1839 /** 1840 * Motion-UI class to use for animated elements. If none used, defaults to simple show/hide. 1841 * @option 1842 * @type {string} 1843 * @default '' 1844 */ 1845 animationIn: '', 1846 /** 1847 * Motion-UI class to use for animated elements. If none used, defaults to simple show/hide. 1848 * @option 1849 * @type {string} 1850 * @default '' 1851 */ 1852 animationOut: '', 1853 /** 1854 * Time, in ms, to delay the opening of a modal after a click if no animation used. 1855 * @option 1856 * @type {number} 1857 * @default 0 1858 */ 1859 showDelay: 0, 1860 /** 1861 * Time, in ms, to delay the closing of a modal after a click if no animation used. 1862 * @option 1863 * @type {number} 1864 * @default 0 1865 */ 1866 hideDelay: 0, 1867 /** 1868 * Allows a click on the body/overlay to close the modal. 1869 * @option 1870 * @type {boolean} 1871 * @default true 1872 */ 1873 closeOnClick: true, 1874 /** 1875 * Allows the modal to close if the user presses the `ESCAPE` key. 1876 * @option 1877 * @type {boolean} 1878 * @default true 1879 */ 1880 closeOnEsc: true, 1881 /** 1882 * If true, allows multiple modals to be displayed at once. 1883 * @option 1884 * @type {boolean} 1885 * @default false 1886 */ 1887 multipleOpened: false, 1888 /** 1889 * Distance, in pixels, the modal should push down from the top of the screen. 1890 * @option 1891 * @type {number|string} 1892 * @default auto 1893 */ 1894 vOffset: 'auto', 1895 /** 1896 * Distance, in pixels, the modal should push in from the side of the screen. 1897 * @option 1898 * @type {number|string} 1899 * @default auto 1900 */ 1901 hOffset: 'auto', 1902 /** 1903 * Allows the modal to be fullscreen, completely blocking out the rest of the view. JS checks for this as well. 1904 * @option 1905 * @type {boolean} 1906 * @default false 1907 */ 1908 fullScreen: false, 1909 /** 1910 * Percentage of screen height the modal should push up from the bottom of the view. 1911 * @option 1912 * @type {number} 1913 * @default 10 1914 */ 1915 btmOffsetPct: 10, 1916 /** 1917 * Allows the modal to generate an overlay div, which will cover the view when modal opens. 1918 * @option 1919 * @type {boolean} 1920 * @default true 1921 */ 1922 overlay: true, 1923 /** 1924 * Allows the modal to remove and reinject markup on close. Should be true if using video elements w/o using provider's api, otherwise, videos will continue to play in the background. 1925 * @option 1926 * @type {boolean} 1927 * @default false 1928 */ 1929 resetOnClose: false, 1930 /** 1931 * Allows the modal to alter the url on open/close, and allows the use of the `back` button to close modals. ALSO, allows a modal to auto-maniacally open on page load IF the hash === the modal'
1931s user-set id. 1932 * @option 1933 * @type {boolean} 1934 * @default false 1935 */ 1936 deepLink: false, 1937 /** 1938 * Allows the modal to append to custom div. 1939 * @option 1940 * @type {string} 1941 * @default "body" 1942 */ 1943 appendTo: "body" 1944 1945 }; 1946 1947 // Window exports 1948 Foundation.plugin(Reveal, 'Reveal'); 1949 1950 function iPhoneSniff() { 1951 return (/iP(ad|hone|od).*OS/.test(window.navigator.userAgent) 1952 ); 1953 } 1954 1955 function androidSniff() { 1956 return (/Android/.test(window.navigator.userAgent) 1957 ); 1958 } 1959 1960 function mobileSniff() { 1961 return iPhoneSniff() || androidSniff(); 1962 } 1963}(jQuery); 1964'use strict'; 1965 1966var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 1967 1968function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 1969 1970!function ($) { 1971 1972 /** 1973 * Drilldown module. 1974 * @module foundation.drilldown 1975 * @requires foundation.util.keyboard 1976 * @requires foundation.util.motion 1977 * @requires foundation.util.nest 1978 */ 1979 1980 var Drilldown = function () { 1981 /** 1982 * Creates a new instance of a drilldown menu. 1983 * @class 1984 * @param {jQuery} element - jQuery object to make into an accordion menu. 1985 * @param {Object} options - Overrides to the default plugin settings. 1986 */ 1987 function Drilldown(element, options) { 1988 _classCallCheck(this, Drilldown); 1989 1990 this.$element = element; 1991 this.options = $.extend({}, Drilldown.defaults, this.$element.data(), options); 1992 1993 Foundation.Nest.Feather(this.$element, 'drilldown'); 1994 1995 this._init(); 1996 1997 Foundation.registerPlugin(this, 'Drilldown'); 1998 Foundation.Keyboard.register('Drilldown', { 1999 'ENTER': 'open', 2000 'SPACE': 'open', 2001 'ARROW_RIGHT': 'next', 2002 'ARROW_UP': 'up', 2003 'ARROW_DOWN': 'down', 2004 'ARROW_LEFT': 'previous', 2005 'ESCAPE': 'close', 2006 'TAB': 'down', 2007 'SHIFT_TAB': 'up' 2008 }); 2009 } 2010 2011 /** 2012 * Initializes the drilldown by creating jQuery collections of elements 2013 * @private 2014 */ 2015 2016 2017 _createClass(Drilldown, [{ 2018 key: '_init', 2019 value: function _init() { 2020 this.$submenuAnchors = this.$element.find('li.is-drilldown-submenu-parent').children('a'); 2021 this.$submenus = this.$submenuAnchors.parent('li').children('[data-submenu]'); 2022 this.$menuItems = this.$element.find('li').not('.js-drilldown-back').attr('role', 'menuitem').find('a'); 2023 this.$element.attr('data-mutate', this.$element.attr('data-drilldown') || Foundation.GetYoDigits(6, 'drilldown')); 2024 2025 this._prepareMenu(); 2026 this._registerEvents(); 2027 2028 this._keyboardEvents(); 2029 } 2030 2031 /** 2032 * prepares drilldown menu by setting attributes to links and elements 2033 * sets a min height to prevent content jumping 2034 * wraps the element if not already wrapped 2035 * @private 2036 * @function 2037 */ 2038 2039 }, { 2040 key: '_prepareMenu', 2041 value: function _prepareMenu() { 2042 var _this = this; 2043 // if(!this.options.holdOpen){ 2044 // this._menuLinkEvents(); 2045 // } 2046 this.$submenuAnchors.each(function () { 2047 var $link = $(this); 2048 var $sub = $link.parent(); 2049 if (_this.options.parentLink) { 2050 $link.clone().prependTo($sub.children('[data-submenu]')).wrap('<li class="is-submenu-parent-item is-submenu-item is-drilldown-submenu-item" role="menu-item"></li>'); 2051 } 2052 $link.data('savedHref', $link.attr('href')).removeAttr('href').attr('tabindex', 0); 2053 $link.children('[data-submenu]').attr({ 2054 'aria-hidden': true, 2055 'tabindex': 0, 2056 'role': 'menu' 2057 }); 2058 _this._events($link); 2059 }); 2060 this.$submenus.each(function () { 2061 var $menu = $(this), 2062 $back = $menu.find('.js-drilldown-back'); 2063 if (!$back.length) { 2064 switch (_this.options.backButtonPosition) { 2065 case "bottom": 2066 $menu.append(_this.options.backButton); 2067 break; 2068 case "top": 2069 $menu.prepend(_this.options.backButton); 2070 break; 2071 default: 2072 console.error("Unsupported backButtonPosition value '" + _this.options.backButtonPosition + "'"); 2073 } 2074 } 2075 _this._back($menu); 2076 }); 2077 2078 this.$submenus.addClass('invisible'); 2079 if (!this.options.autoHeight) { 2080 this.$submenus.addClass('drilldown-submenu-cover-previous'); 2081 } 2082 2083 // create a wrapper on element if it doesn't exist. 2084 if (!this.$element.parent().hasClass('is-drilldown')) { 2085 this.$wrapper = $(this.options.wrapper).addClass('is-drilldown'); 2086 if (this.options.animateHeight) this.$wrapper.addClass('animate-height'); 2087 this.$element.wrap(this.$wrapper); 2088 } 2089 // set wrapper 2090 this.$wrapper = this.$element.parent(); 2091 this.$wrapper.css(this._getMaxDims()); 2092 } 2093 }, {
2094 key: '_resize', 2095 value: function _resize() { 2096 this.$wrapper.css({ 'max-width': 'none', 'min-height': 'none' }); 2097 // _getMaxDims has side effects (boo) but calling it should update all other necessary heights & widths 2098 this.$wrapper.css(this._getMaxDims()); 2099 } 2100 2101 /** 2102 * Adds event handlers to elements in the menu. 2103 * @function 2104 * @private 2105 * @param {jQuery} $elem - the current menu item to add handlers to. 2106 */ 2107 2108 }, { 2109 key: '_events', 2110 value: function _events($elem) { 2111 var _this = this; 2112 2113 $elem.off('click.zf.drilldown').on('click.zf.drilldown', function (e) { 2114 if ($(e.target).parentsUntil('ul', 'li').hasClass('is-drilldown-submenu-parent')) { 2115 e.stopImmediatePropagation(); 2116 e.preventDefault(); 2117 } 2118 2119 // if(e.target !== e.currentTarget.firstElementChild){ 2120 // return false; 2121 // } 2122 _this._show($elem.parent('li')); 2123 2124 if (_this.options.closeOnClick) { 2125 var $body = $('body'); 2126 $body.off('.zf.drilldown').on('click.zf.drilldown', function (e) { 2127 if (e.target === _this.$element[0] || $.contains(_this.$element[0], e.target)) { 2128 return; 2129 } 2130 e.preventDefault(); 2131 _this._hideAll(); 2132 $body.off('.zf.drilldown'); 2133 }); 2134 } 2135 }); 2136 this.$element.on('mutateme.zf.trigger', this._resize.bind(this)); 2137 } 2138 2139 /** 2140 * Adds event handlers to the menu element. 2141 * @function 2142 * @private 2143 */ 2144 2145 }, { 2146 key: '_registerEvents', 2147 value: function _registerEvents() { 2148 if (this.options.scrollTop) { 2149 this._bindHandler = this._scrollTop.bind(this); 2150 this.$element.on('open.zf.drilldown hide.zf.drilldown closed.zf.drilldown', this._bindHandler); 2151 } 2152 } 2153 2154 /** 2155 * Scroll to Top of Element or data-scroll-top-element 2156 * @function 2157 * @fires Drilldown#scrollme 2158 */ 2159 2160 }, { 2161 key: '_scrollTop', 2162 value: function _scrollTop() { 2163 var _this = this; 2164 var $scrollTopElement = _this.options.scrollTopElement != '' ? $(_this.options.scrollTopElement) : _this.$element, 2165 scrollPos = parseInt($scrollTopElement.offset().top + _this.options.scrollTopOffset); 2166 $('html, body').stop(true).animate({ scrollTop: scrollPos }, _this.options.animationDuration, _this.options.animationEasing, function () { 2167 /** 2168 * Fires after the menu has scrolled 2169 * @event Drilldown#scrollme 2170 */ 2171 if (this === $('html')[0]) _this.$element.trigger('scrollme.zf.drilldown'); 2172 }); 2173 } 2174 2175 /** 2176 * Adds keydown event listener to `li`'s in the menu. 2177 * @private 2178 */ 2179 2180 }, { 2181 key: '_keyboardEvents', 2182 value: function _keyboardEvents() { 2183 var _this = this; 2184 2185 this.$menuItems.add(this.$element.find('.js-drilldown-back > a, .is-submenu-parent-item > a')).on('keydown.zf.drilldown', function (e) { 2186 var $element = $(this), 2187 $elements = $element.parent('li').parent('ul').children('li').children('a'), 2188 $prevElement, 2189 $nextElement; 2190 2191 $elements.each(function (i) { 2192 if ($(this).is($element)) { 2193 $prevElement = $elements.eq(Math.max(0, i - 1)); 2194 $nextElement = $elements.eq(Math.min(i + 1, $elements.length - 1)); 2195 return; 2196 } 2197 }); 2198 2199 Foundation.Keyboard.handleKey(e, 'Drilldown', { 2200 next: function () { 2201 if ($element.is(_this.$submenuAnchors)) { 2202 _this._show($element.parent('li')); 2203 $element.parent('li').one(Foundation.transitionend($element), function () { 2204 $element.parent('li').find('ul li a').filter(_this.$menuItems).first().focus(); 2205 }); 2206 return true; 2207 } 2208 }, 2209 previous: function () { 2210 _this._hide($element.parent('li').parent('ul')); 2211 $element.parent('li').parent('ul').one(Foundation.transitionend($element), function () { 2212 setTimeout(function () { 2213 $element.parent('li').parent('ul').parent('li').children('a').first().focus(); 2214 }, 1); 2215 }); 2216 return true; 2217 }, 2218 up: function () { 2219 $prevElement.focus(); 2220 // Don't tap focus on first element in root ul 2221 return !$element.is(_this.$element.find('> li:first-child > a')); 2222 }, 2223 down: function () { 2224 $nextElement.focus(); 2225 // Don't tap focus on last element in root ul 2226 return !$element.is(_this.$element.find('> li:last-child > a')); 2227 }, 2228 close: function () { 2229 // Don't close on element in root ul 2230 if (!$element.is(_this.$element.find('> li > a'))) { 2231 _this._hide($element.parent().parent()); 2232 $element.parent().parent().siblings('a').focus(); 2233 } 2234 }, 2235 open: function () { 2236 if (!$element.is(_this.$menuItems)) { 2237 // not menu item means back button 2238 _this._hide($element.parent('li').parent('ul')); 2239 $element.parent('li').parent('ul').one(Foundation.transitionend($element), function () { 2240 setTimeout(function () { 2241 $element.parent('li').parent('ul').parent('li').children('a').first().focus(); 2242 }, 1); 2243 }); 2244 return true; 2245 } else if ($element.is(_this.$submenuAnchors)) { 2246 _this._show($element.parent('li')); 2247 $element.parent('li').one(Foundation.transitionend($element), function () { 2248 $element.parent('li').find('ul li a').filter(_this.$menuItems).first().focus(); 2249 }); 2250 return true; 2251 } 2252 }, 2253 handled: function (preventDefault) { 2254 if (preventDefault) { 2255 e.preventDefault(); 2256 } 2257 e.stopImmediatePropagation(); 2258 } 2259 }); 2260 }); // end keyboardAccess 2261 } 2262 2263 /** 2264 * Closes all open elements, and returns to root menu. 2265 * @function 2266 * @fires Drilldown#closed 2267 */ 2268 2269 }, {
2270 key: '_hideAll', 2271 value: function _hideAll() { 2272 var $elem = this.$element.find('.is-drilldown-submenu.is-active').addClass('is-closing'); 2273 if (this.options.autoHeight) this.$wrapper.css({ height: $elem.parent().closest('ul').data('calcHeight') }); 2274 $elem.one(Foundation.transitionend($elem), function (e) { 2275 $elem.removeClass('is-active is-closing'); 2276 }); 2277 /** 2278 * Fires when the menu is fully closed. 2279 * @event Drilldown#closed 2280 */ 2281 this.$element.trigger('closed.zf.drilldown'); 2282 } 2283 2284 /** 2285 * Adds event listener for each `back` button, and closes open menus. 2286 * @function 2287 * @fires Drilldown#back 2288 * @param {jQuery} $elem - the current sub-menu to add `back` event. 2289 */ 2290 2291 }, { 2292 key: '_back', 2293 value: function _back($elem) { 2294 var _this = this; 2295 $elem.off('click.zf.drilldown'); 2296 $elem.children('.js-drilldown-back').on('click.zf.drilldown', function (e) { 2297 e.stopImmediatePropagation(); 2298 // console.log('mouseup on back'); 2299 _this._hide($elem); 2300 2301 // If there is a parent submenu, call show 2302 var parentSubMenu = $elem.parent('li').parent('ul').parent('li'); 2303 if (parentSubMenu.length) { 2304 _this._show(parentSubMenu); 2305 } 2306 }); 2307 } 2308 2309 /** 2310 * Adds event listener to menu items w/o submenus to close open menus on click. 2311 * @function 2312 * @private 2313 */ 2314 2315 }, { 2316 key: '_menuLinkEvents', 2317 value: function _menuLinkEvents() { 2318 var _this = this; 2319 this.$menuItems.not('.is-drilldown-submenu-parent').off('click.zf.drilldown').on('click.zf.drilldown', function (e) { 2320 // e.stopImmediatePropagation(); 2321 setTimeout(function () { 2322 _this._hideAll(); 2323 }, 0); 2324 }); 2325 } 2326 2327 /** 2328 * Opens a submenu. 2329 * @function 2330 * @fires Drilldown#open 2331 * @param {jQuery} $elem - the current element with a submenu to open, i.e. the `li` tag. 2332 */ 2333 2334 }, { 2335 key: '_show', 2336 value: function _show($elem) { 2337 if (this.options.autoHeight) this.$wrapper.css({ height: $elem.children('[data-submenu]').data('calcHeight') }); 2338 $elem.attr('aria-expanded', true); 2339 $elem.children('[data-submenu]').addClass('is-active').removeClass('invisible').attr('aria-hidden', false); 2340 /** 2341 * Fires when the submenu has opened. 2342 * @event Drilldown#open 2343 */ 2344 this.$element.trigger('open.zf.drilldown', [$elem]); 2345 } 2346 }, { 2347 key: '_hide', 2348 2349 2350 /** 2351 * Hides a submenu 2352 * @function 2353 * @fires Drilldown#hide 2354 * @param {jQuery} $elem - the current sub-menu to hide, i.e. the `ul` tag. 2355 */ 2356 value: function _hide($elem) { 2357 if (this.options.autoHeight) this.$wrapper.css({ height: $elem.parent().closest('ul').data('calcHeight') }); 2358 var _this = this; 2359 $elem.parent('li').attr('aria-expanded', false); 2360 $elem.attr('aria-hidden', true).addClass('is-closing'); 2361 $elem.addClass('is-closing').one(Foundation.transitionend($elem), function () { 2362 $elem.removeClass('is-active is-closing'); 2363 $elem.blur().addClass('invisible'); 2364 }); 2365 /** 2366 * Fires when the submenu has closed. 2367 * @event Drilldown#hide 2368 */ 2369 $elem.trigger('hide.zf.drilldown', [$elem]); 2370 } 2371 2372 /** 2373 * Iterates through the nested menus to calculate the min-height, and max-width for the menu. 2374 * Prevents content jumping. 2375 * @function 2376 * @private 2377 */ 2378 2379 }, { 2380 key: '_getMaxDims', 2381 value: function _getMaxDims() { 2382 var maxHeight = 0, 2383 result = {}, 2384 _this = this; 2385 this.$submenus.add(this.$element).each(function () { 2386 var numOfElems = $(this).children('li').length; 2387 var height = Foundation.Box.GetDimensions(this).height; 2388 maxHeight = height > maxHeight ? height : maxHeight; 2389 if (_this.options.autoHeight) { 2390 $(this).data('calcHeight', height); 2391 if (!$(this).hasClass('is-drilldown-submenu')) result['height'] = height; 2392 } 2393 }); 2394 2395 if (!this.options.autoHeight) result['min-height'] = maxHeight + 'px'; 2396 2397 result['max-width'] = this.$element[0].getBoundingClientRect().width + 'px'; 2398 2399 return result; 2400 } 2401 2402 /** 2403 * Destroys the Drilldown Menu 2404 * @function 2405 */ 2406 2407 }, {
2408 key: 'destroy', 2409 value: function destroy() { 2410 if (this.options.scrollTop) this.$element.off('.zf.drilldown', this._bindHandler); 2411 this._hideAll(); 2412 this.$element.off('mutateme.zf.trigger'); 2413 Foundation.Nest.Burn(this.$element, 'drilldown'); 2414 this.$element.unwrap().find('.js-drilldown-back, .is-submenu-parent-item').remove().end().find('.is-active, .is-closing, .is-drilldown-submenu').removeClass('is-active is-closing is-drilldown-submenu').end().find('[data-submenu]').removeAttr('aria-hidden tabindex role'); 2415 this.$submenuAnchors.each(function () { 2416 $(this).off('.zf.drilldown'); 2417 }); 2418 2419 this.$submenus.removeClass('drilldown-submenu-cover-previous'); 2420 2421 this.$element.find('a').each(function () { 2422 var $link = $(this); 2423 $link.removeAttr('tabindex'); 2424 if ($link.data('savedHref')) { 2425 $link.attr('href', $link.data('savedHref')).removeData('savedHref'); 2426 } else { 2427 return; 2428 } 2429 }); 2430 Foundation.unregisterPlugin(this); 2431 } 2432 }]); 2433 2434 return Drilldown; 2435 }(); 2436 2437 Drilldown.defaults = { 2438 /** 2439 * Markup used for JS generated back button. Prepended or appended (see backButtonPosition) to submenu lists and deleted on `destroy` method, 'js-drilldown-back' class required. Remove the backslash (`\`) if copy and pasting. 2440 * @option 2441 * @type {string} 2442 * @default '<li class="js-drilldown-back"><a tabindex="0">Back</a></li>' 2443 */ 2444 backButton: '<li class="js-drilldown-back"><a tabindex="0">Back</a></li>', 2445 /** 2446 * Position the back button either at the top or bottom of drilldown submenus. Can be `'left'` or `'bottom'`. 2447 * @option 2448 * @type {string} 2449 * @default top 2450 */ 2451 backButtonPosition: 'top', 2452 /** 2453 * Markup used to wrap drilldown menu. Use a class name for independent styling; the JS applied class: `is-drilldown` is required. Remove the backslash (`\`) if copy and pasting. 2454 * @option 2455 * @type {string} 2456 * @default '<div></div>' 2457 */ 2458 wrapper: '<div></div>', 2459 /** 2460 * Adds the parent link to the submenu. 2461 * @option 2462 * @type {boolean} 2463 * @default false 2464 */ 2465 parentLink: false, 2466 /** 2467 * Allow the menu to return to root list on body click. 2468 * @option 2469 * @type {boolean} 2470 * @default false 2471 */ 2472 closeOnClick: false, 2473 /** 2474 * Allow the menu to auto adjust height. 2475 * @option 2476 * @type {boolean} 2477 * @default false 2478 */ 2479 autoHeight: false, 2480 /** 2481 * Animate the auto adjust height. 2482 * @option 2483 * @type {boolean} 2484 * @default false 2485 */ 2486 animateHeight: false, 2487 /** 2488 * Scroll to the top of the menu after opening a submenu or navigating back using the menu back button 2489 * @option 2490 * @type {boolean} 2491 * @default false 2492 */ 2493 scrollTop: false, 2494 /** 2495 * String jquery selector (for example 'body') of element to take offset().top from, if empty string the drilldown menu offset().top is taken 2496 * @option 2497 * @type {string} 2498 * @default '' 2499 */ 2500 scrollTopElement: '', 2501 /** 2502 * ScrollTop offset 2503 * @option 2504 * @type {number} 2505 * @default 0 2506 */ 2507 scrollTopOffset: 0, 2508 /** 2509 * Scroll animation duration 2510 * @option 2511 * @type {number} 2512 * @default 500 2513 */ 2514 animationDuration: 500, 2515 /** 2516 * Scroll animation easing. Can be `'swing'` or `'linear'`. 2517 * @option 2518 * @type {string} 2519 * @see {@link https://api.jquery.com/animate|JQuery animate} 2520 * @default 'swing' 2521 */ 2522 animationEasing: 'swing' 2523 // holdOpen: false 2524 }; 2525 2526 // Window exports 2527 Foundation.plugin(Drilldown, 'Drilldown'); 2528}(jQuery); 2529/* 2530 * This content is licensed according to the W3C Software License at 2531 * https://www.w3.org/Consortium/Legal/2015/copyright-software-and-document 2532 * 2533 * Simple accordion pattern example 2534 */ 2535 2536'use strict'; 2537 2538class Accordion { 2539 constructor(domNode) { 2540 this.rootEl = domNode; 2541 this.buttonEl = this.rootEl.querySelector('button[aria-expanded]'); 2542 2543 const controlsId = this.buttonEl.getAttribute('aria-controls'); 2544 this.contentEl = document.getElementById(controlsId); 2545 2546 this.open = this.buttonEl.getAttribute('aria-expanded') === 'true'; 2547 2548 // add event listeners 2549 this.buttonEl.addEventListener('click', this.onButtonClick.bind(this)); 2550 } 2551 2552 onButtonClick() { 2553 this.toggle(!this.open); 2554 } 2555 2556 toggle(open) { 2557 // don't do anything if the open state doesn't change 2558 if (open === this.open) { 2559 return; 2560 } 2561 2562 // update the internal state 2563 this.open = open; 2564 2565 // handle DOM updates 2566 this.buttonEl.setAttribute('aria-expanded', `${open}`); 2567 if (open) { 2568 this.contentEl.removeAttribute('hidden'); 2569 } else { 2570 this.contentEl.setAttribute('hidden', ''); 2571 } 2572 } 2573 2574 // Add public open and close methods for convenience 2575 open() { 2576 this.toggle(true); 2577 } 2578 2579 close() { 2580 this.toggle(false); 2581 } 2582} 2583 2584// init accordions 2585const accordions = document.querySelectorAll('.accordion .no-style'); 2586accordions.forEach((accordionEl) => { 2587 new Accordion(accordionEl); 2588}); 2589 2590'use strict'; 2591 2592var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 2593 2594function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 2595 2596!function ($) { 2597 2598 /** 2599 * DropdownMenu module. 2600 * @module foundation.dropdown-menu 2601 * @requires foundation.util.keyboard 2602 * @requires foundation.util.box 2603 * @requires foundation.util.nest 2604 */ 2605 2606 var DropdownMenu = function () { 2607 /** 2608 * Creates a new instance of DropdownMenu. 2609 * @class 2610 * @fires DropdownMenu#init 2611 * @param {jQuery} element - jQuery object to make into a dropdown menu. 2612 * @param {Object} options - Overrides to the default plugin settings. 2613 */ 2614 function DropdownMenu(element, options) { 2615 _classCallCheck(this, DropdownMenu); 2616 2617 this.$element = element; 2618 this.options = $.extend({}, DropdownMenu.defaults, this.$element.data(), options); 2619 2620 Foundation.Nest.Feather(this.$element, 'dropdown'); 2621 this._init(); 2622 2623 Foundation.registerPlugin(this, 'DropdownMenu'); 2624 Foundation.Keyboard.register('DropdownMenu', { 2625 'ENTER': 'open', 2626 'SPACE': 'open',
2627 'ARROW_RIGHT': 'next', 2628 'ARROW_UP': 'up', 2629 'ARROW_DOWN': 'down', 2630 'ARROW_LEFT': 'previous', 2631 'ESCAPE': 'close' 2632 }); 2633 } 2634 2635 /** 2636 * Initializes the plugin, and calls _prepareMenu 2637 * @private 2638 * @function 2639 */ 2640 2641 2642 _createClass(DropdownMenu, [{ 2643 key: '_init', 2644 value: function _init() { 2645 var subs = this.$element.find('li.is-dropdown-submenu-parent'); 2646 this.$element.children('.is-dropdown-submenu-parent').children('.is-dropdown-submenu').addClass('first-sub'); 2647 2648 this.$menuItems = this.$element.find('[role="menuitem"]'); 2649 this.$tabs = this.$element.children('[role="menuitem"]'); 2650 this.$tabs.find('ul.is-dropdown-submenu').addClass(this.options.verticalClass); 2651 2652 if (this.$element.hasClass(this.options.rightClass) || this.options.alignment === 'right' || Foundation.rtl() || this.$element.parents('.top-bar-right').is('*')) { 2653 this.options.alignment = 'right'; 2654 subs.addClass('opens-left'); 2655 } else { 2656 subs.addClass('opens-right'); 2657 } 2658 this.changed = false; 2659 this._events(); 2660 } 2661 }, { 2662 key: '_isVertical', 2663 value: function _isVertical() { 2664 return this.$tabs.css('display') === 'block'; 2665 } 2666 2667 /** 2668 * Adds event listeners to elements within the menu 2669 * @private 2670 * @function 2671 */ 2672 2673 }, { 2674 key: '_events', 2675 value: function _events() { 2676 var _this = this, 2677 hasTouch = 'ontouchstart' in window || typeof window.ontouchstart !== 'undefined', 2678 parClass = 'is-dropdown-submenu-parent'; 2679 2680 // used for onClick and in the keyboard handlers 2681 var handleClickFn = function (e) { 2682 var $elem = $(e.target).parentsUntil('ul', '.' + parClass), 2683 hasSub = $elem.hasClass(parClass), 2684 hasClicked = $elem.attr('data-is-click') === 'true', 2685 $sub = $elem.children('.is-dropdown-submenu'); 2686 2687 if (hasSub) { 2688 if (hasClicked) { 2689 if (!_this.options.closeOnClick || !_this.options.clickOpen && !hasTouch || _this.options.forceFollow && hasTouch) { 2690 return; 2691 } else { 2692 e.stopImmediatePropagation(); 2693 e.preventDefault(); 2694 _this._hide($elem); 2695 } 2696 } else { 2697 e.preventDefault(); 2698 e.stopImmediatePropagation(); 2699 _this._show($sub); 2700 $elem.add($elem.parentsUntil(_this.$element, '.' + parClass)).attr('data-is-click', true); 2701 } 2702 } 2703 }; 2704 2705 if (this.options.clickOpen || hasTouch) { 2706 this.$menuItems.on('click.zf.dropdownmenu touchstart.zf.dropdownmenu', handleClickFn); 2707 } 2708 2709 // Handle Leaf element Clicks 2710 if (_this.options.closeOnClickInside) { 2711 this.$menuItems.on('click.zf.dropdownmenu', function (e) { 2712 var $elem = $(this), 2713 hasSub = $elem.hasClass(parClass); 2714 if (!hasSub) { 2715 _this._hide(); 2716 } 2717 }); 2718 } 2719 2720 if (!this.options.disableHover) { 2721 this.$menuItems.on('mouseenter.zf.dropdownmenu', function (e) { 2722 var $elem = $(this), 2723 hasSub = $elem.hasClass(parClass); 2724 2725 if (hasSub) { 2726 clearTimeout($elem.data('_delay')); 2727 $elem.data('_delay', setTimeout(function () { 2728 _this._show($elem.children('.is-dropdown-submenu')); 2729 }, _this.options.hoverDelay)); 2730 } 2731 }).on('mouseleave.zf.dropdownmenu', function (e) { 2732 var $elem = $(this), 2733 hasSub = $elem.hasClass(parClass); 2734 if (hasSub && _this.options.autoclose) { 2735 if ($elem.attr('data-is-click') === 'true' && _this.options.clickOpen) { 2736 return false; 2737 } 2738 2739 clearTimeout($elem.data('_delay')); 2740 $elem.data('_delay', setTimeout(function () { 2741 _this._hide($elem); 2742 }, _this.options.closingTime)); 2743 } 2744 }); 2745 } 2746 this.$menuItems.on('keydown.zf.dropdownmenu', function (e) { 2747 var $element = $(e.target).parentsUntil('ul', '[role="menuitem"]'), 2748 isTab = _this.$tabs.index($element) > -1, 2749 $elements = isTab ? _this.$tabs : $element.siblings('li').add($element), 2750 $prevElement, 2751 $nextElement; 2752 2753 $elements.each(function (i) { 2754 if ($(this).is($element)) { 2755 $prevElement = $elements.eq(i - 1); 2756 $nextElement = $elements.eq(i + 1); 2757 return; 2758 } 2759 }); 2760 2761 var nextSibling = function () { 2762 if (!$element.is(':last-child')) { 2763 $nextElement.children('a:first').focus(); 2764 e.preventDefault(); 2765 } 2766 }, 2767 prevSibling = function () { 2768 $prevElement.children('a:first').focus(); 2769 e.preventDefault(); 2770 }, 2771 openSub = function () {
2772 var $sub = $element.children('ul.is-dropdown-submenu'); 2773 if ($sub.length) { 2774 _this._show($sub); 2775 $element.find('li > a:first').focus(); 2776 e.preventDefault(); 2777 } else { 2778 return; 2779 } 2780 }, 2781 closeSub = function () { 2782 //if ($element.is(':first-child')) { 2783 var close = $element.parent('ul').parent('li'); 2784 close.children('a:first').focus(); 2785 _this._hide(close); 2786 e.preventDefault(); 2787 //} 2788 }; 2789 var functions = { 2790 open: openSub, 2791 close: function () { 2792 _this._hide(_this.$element); 2793 _this.$menuItems.find('a:first').focus(); // focus to first element 2794 e.preventDefault(); 2795 }, 2796 handled: function () { 2797 e.stopImmediatePropagation(); 2798 } 2799 }; 2800 2801 if (isTab) { 2802 if (_this._isVertical()) { 2803 // vertical menu 2804 if (Foundation.rtl()) { 2805 // right aligned 2806 $.extend(functions, { 2807 down: nextSibling, 2808 up: prevSibling, 2809 next: closeSub, 2810 previous: openSub 2811 }); 2812 } else { 2813 // left aligned 2814 $.extend(functions, { 2815 down: nextSibling, 2816 up: prevSibling, 2817 next: openSub, 2818 previous: closeSub 2819 }); 2820 } 2821 } else { 2822 // horizontal menu 2823 if (Foundation.rtl()) { 2824 // right aligned 2825 $.extend(functions, { 2826 next: prevSibling, 2827 previous: nextSibling, 2828 down: openSub, 2829 up: closeSub 2830 }); 2831 } else { 2832 // left aligned 2833 $.extend(functions, { 2834 next: nextSibling, 2835 previous: prevSibling, 2836 down: openSub, 2837 up: closeSub 2838 }); 2839 } 2840 } 2841 } else { 2842 // not tabs -> one sub 2843 if (Foundation.rtl()) { 2844 // right aligned 2845 $.extend(functions, { 2846 next: closeSub, 2847 previous: openSub, 2848 down: nextSibling, 2849 up: prevSibling 2850 }); 2851 } else { 2852 // left aligned 2853 $.extend(functions, { 2854 next: openSub, 2855 previous: closeSub, 2856 down: nextSibling, 2857 up: prevSibling 2858 }); 2859 } 2860 } 2861 Foundation.Keyboard.handleKey(e, 'DropdownMenu', functions); 2862 }); 2863 } 2864 2865 /** 2866 * Adds an event handler to the body to close any dropdowns on a click. 2867 * @function 2868 * @private 2869 */ 2870 2871 }, { 2872 key: '_addBodyHandler', 2873 value: function _addBodyHandler() { 2874 var $body = $(document.body), 2875 _this = this; 2876 $body.off('mouseup.zf.dropdownmenu touchend.zf.dropdownmenu').on('mouseup.zf.dropdownmenu touchend.zf.dropdownmenu', function (e) { 2877 var $link = _this.$element.find(e.target); 2878 if ($link.length) { 2879 return; 2880 } 2881 2882 _this._hide(); 2883 $body.off('mouseup.zf.dropdownmenu touchend.zf.dropdownmenu'); 2884 }); 2885 } 2886 2887 /** 2888 * Opens a dropdown pane, and checks for collisions first. 2889 * @param {jQuery} $sub - ul element that is a submenu to show 2890 * @function 2891 * @private 2892 * @fires DropdownMenu#show 2893 */ 2894 2895 }, { 2896 key: '_show', 2897 value: function _show($sub) { 2898 var idx = this.$tabs.index(this.$tabs.filter(function (i, el) { 2899 return $(el).find($sub).length > 0; 2900 })); 2901 var $sibs = $sub.parent('li.is-dropdown-submenu-parent').siblings('li.is-dropdown-submenu-parent'); 2902 this._hide($sibs, idx); 2903 $sub.css('visibility', 'hidden').addClass('js-dropdown-active').parent('li.is-dropdown-submenu-parent').addClass('is-active'); 2904 var clear = Foundation.Box.ImNotTouchingYou($sub, null, true); 2905 if (!clear) { 2906 var oldClass = this.options.alignment === 'left' ? '-right' : '-left', 2907 $parentLi = $sub.parent('.is-dropdown-submenu-parent'); 2908 $parentLi.removeClass('opens' + oldClass).addClass('opens-' + this.options.alignment); 2909 clear = Foundation.Box.ImNotTouchingYou($sub, null, true); 2910 if (!clear) { 2911 $parentLi.removeClass('opens-' + this.options.alignment).addClass('opens-inner'); 2912 } 2913 this.changed = true; 2914 } 2915 $sub.css('visibility', ''); 2916 if (this.options.closeOnClick) { 2917 this._addBodyHandler(); 2918 } 2919 /** 2920 * Fires when the new dropdown pane is visible. 2921 * @event DropdownMenu#show 2922 */ 2923 this.$element.trigger('show.zf.dropdownmenu', [$sub]); 2924 } 2925 2926 /** 2927 * Hides a single, currently open dropdown pane, if passed a parameter, otherwise, hides everything. 2928 * @function 2929 * @param {jQuery} $elem - element with a submenu to hide 2930 * @param {Number} idx - index of the $tabs collection to hide 2931 * @private 2932 */ 2933 2934 }, {
2935 key: '_hide', 2936 value: function _hide($elem, idx) { 2937 var $toClose; 2938 if ($elem && $elem.length) { 2939 $toClose = $elem; 2940 } else if (idx !== undefined) { 2941 $toClose = this.$tabs.not(function (i, el) { 2942 return i === idx; 2943 }); 2944 } else { 2945 $toClose = this.$element; 2946 } 2947 var somethingToClose = $toClose.hasClass('is-active') || $toClose.find('.is-active').length > 0; 2948 2949 if (somethingToClose) { 2950 $toClose.find('li.is-active').add($toClose).attr({ 2951 'data-is-click': false 2952 }).removeClass('is-active'); 2953 2954 $toClose.find('ul.js-dropdown-active').removeClass('js-dropdown-active'); 2955 2956 if (this.changed || $toClose.find('opens-inner').length) { 2957 var oldClass = this.options.alignment === 'left' ? 'right' : 'left'; 2958 $toClose.find('li.is-dropdown-submenu-parent').add($toClose).removeClass('opens-inner opens-' + this.options.alignment).addClass('opens-' + oldClass); 2959 this.changed = false; 2960 } 2961 /** 2962 * Fires when the open menus are closed. 2963 * @event DropdownMenu#hide 2964 */ 2965 this.$element.trigger('hide.zf.dropdownmenu', [$toClose]); 2966 } 2967 } 2968 2969 /** 2970 * Destroys the plugin. 2971 * @function 2972 */ 2973 2974 }, { 2975 key: 'destroy', 2976 value: function destroy() { 2977 this.$menuItems.off('.zf.dropdownmenu').removeAttr('data-is-click').removeClass('is-right-arrow is-left-arrow is-down-arrow opens-right opens-left opens-inner'); 2978 $(document.body).off('.zf.dropdownmenu'); 2979 Foundation.Nest.Burn(this.$element, 'dropdown'); 2980 Foundation.unregisterPlugin(this); 2981 } 2982 }]); 2983 2984 return DropdownMenu; 2985 }(); 2986 2987 /** 2988 * Default settings for plugin 2989 */ 2990 2991 2992 DropdownMenu.defaults = { 2993 /** 2994 * Disallows hover events from opening submenus 2995 * @option 2996 * @type {boolean} 2997 * @default false 2998 */ 2999 disableHover: false, 3000 /** 3001 * Allow a submenu to automatically close on a mouseleave event, if not clicked open. 3002 * @option 3003 * @type {boolean} 3004 * @default true 3005 */ 3006 autoclose: true, 3007 /** 3008 * Amount of time to delay opening a submenu on hover event. 3009 * @option 3010 * @type {number} 3011 * @default 50 3012 */ 3013 hoverDelay: 50, 3014 /** 3015 * Allow a submenu to open/remain open on parent click event. Allows cursor to move away from menu. 3016 * @option 3017 * @type {boolean} 3018 * @default false 3019 */ 3020 clickOpen: false, 3021 /** 3022 * Amount of time to delay closing a submenu on a mouseleave event. 3023 * @option 3024 * @type {number} 3025 * @default 500 3026 */ 3027 3028 closingTime: 500, 3029 /** 3030 * Position of the menu relative to what direction the submenus should open. Handled by JS. Can be `'left'` or `'right'`. 3031 * @option 3032 * @type {string} 3033 * @default 'left' 3034 */ 3035 alignment: 'left', 3036 /** 3037 * Allow clicks on the body to close any open submenus. 3038 * @option 3039 * @type {boolean} 3040 * @default true 3041 */ 3042 closeOnClick: true, 3043 /** 3044 * Allow clicks on leaf anchor links to close any open submenus. 3045 * @option 3046 * @type {boolean} 3047 * @default true 3048 */ 3049 closeOnClickInside: true, 3050 /** 3051 * Class applied to vertical oriented menus, Foundation default is `vertical`. Update this if using your own class. 3052 * @option 3053 * @type {string} 3054 * @default 'vertical' 3055 */ 3056 verticalClass: 'vertical', 3057 /** 3058 * Class applied to right-side oriented menus, Foundation default is `align-right`. Update this if using your own class. 3059 * @option 3060 * @type {string} 3061 * @default 'align-right' 3062 */ 3063 rightClass: 'align-right', 3064 /** 3065 * Boolean to force overide the clicking of links to perform default action, on second touch event for mobile. 3066 * @option 3067 * @type {boolean} 3068 * @default true 3069 */ 3070 forceFollow: true 3071 }; 3072 3073 // Window exports 3074 Foundation.plugin(DropdownMenu, 'DropdownMenu'); 3075}(jQuery); 3076'use strict'; 3077 3078var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 3079 3080function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 3081 3082!function ($) { 3083 3084 /** 3085 * ResponsiveMenu module. 3086 * @module foundation.responsiveMenu 3087 * @requires foundation.util.triggers 3088 * @requires foundation.util.mediaQuery 3089 */ 3090 3091 var ResponsiveMenu = function () { 3092 /** 3093 * Creates a new instance of a responsive menu. 3094 * @class 3095 * @fires ResponsiveMenu#init 3096 * @param {jQuery} element - jQuery object to make into a dropdown menu. 3097 * @param {Object} options - Overrides to the default plugin settings. 3098 */ 3099 function ResponsiveMenu(element, options) { 3100 _classCallCheck(this, ResponsiveMenu); 3101 3102 this.$element = $(element); 3103 this.rules = this.$element.data('responsive-menu'); 3104 this.currentMq = null; 3105 this.currentPlugin = null; 3106 3107 this._init(); 3108 this._events(); 3109 3110 Foundation.registerPlugin(this, 'ResponsiveMenu'); 3111 } 3112 3113 /** 3114 * Initializes the Menu by parsing the classes from the 'data-ResponsiveMenu' attribute on the element. 3115 * @function 3116 * @private 3117 */ 3118 3119 3120 _createClass(ResponsiveMenu, [{ 3121 key: '_init', 3122 value: function _init() { 3123 // The first time an Interchange plugin is initialized, this.rules is converted from a string of "classes" to an object of rules 3124 if (typeof this.rules === 'string') { 3125 var rulesTree = {}; 3126 3127 // Parse rules from "classes" pulled from data attribute 3128 var rules = this.rules.split(' '); 3129 3130 // Iterate through every rule found 3131 for (var i = 0; i < rules.length; i++) { 3132 var rule = rules[i].split('-'); 3133 var ruleSize = rule.length > 1 ? rule[0] : 'small'; 3134 var rulePlugin = rule.length > 1 ? rule[1] : rule[0]; 3135 3136 if (MenuPlugins[rulePlugin] !== null) { 3137 rulesTree[ruleSize] = MenuPlugins[rulePlugin]; 3138 } 3139 } 3140 3141 this.rules = rulesTree; 3142 } 3143 3144 if (!$.isEmptyObject(this.rules)) { 3145 this._checkMediaQueries(); 3146 } 3147 // Add data-mutate since children may need it. 3148 this.$element.attr('data-mutate', this.$element.attr('data-mutate') || Foundation.GetYoDigits(6, 'responsive-menu')); 3149 } 3150 3151 /** 3152 * Initializes events for the Menu. 3153 * @function 3154 * @private 3155 */ 3156 3157 }, {
3158 key: '_events', 3159 value: function _events() { 3160 var _this = this; 3161 3162 $(window).on('changed.zf.mediaquery', function () { 3163 _this._checkMediaQueries(); 3164 }); 3165 // $(window).on('resize.zf.ResponsiveMenu', function() { 3166 // _this._checkMediaQueries(); 3167 // }); 3168 } 3169 3170 /** 3171 * Checks the current screen width against available media queries. If the media query has changed, and the plugin needed has changed, the plugins will swap out. 3172 * @function 3173 * @private 3174 */ 3175 3176 }, { 3177 key: '_checkMediaQueries', 3178 value: function _checkMediaQueries() { 3179 var matchedMq, 3180 _this = this; 3181 // Iterate through each rule and find the last matching rule 3182 $.each(this.rules, function (key) { 3183 if (Foundation.MediaQuery.atLeast(key)) { 3184 matchedMq = key; 3185 } 3186 }); 3187 3188 // No match? No dice 3189 if (!matchedMq) return; 3190 3191 // Plugin already initialized? We good 3192 if (this.currentPlugin instanceof this.rules[matchedMq].plugin) return; 3193 3194 // Remove existing plugin-specific CSS classes 3195 $.each(MenuPlugins, function (key, value) { 3196 _this.$element.removeClass(value.cssClass); 3197 }); 3198 3199 // Add the CSS class for the new plugin 3200 this.$element.addClass(this.rules[matchedMq].cssClass); 3201 3202 // Create an instance of the new plugin 3203 if (this.currentPlugin) this.currentPlugin.destroy(); 3204 this.currentPlugin = new this.rules[matchedMq].plugin(this.$element, {}); 3205 } 3206 3207 /** 3208 * Destroys the instance of the current plugin on this element, as well as the window resize handler that switches the plugins out. 3209 * @function 3210 */ 3211 3212 }, { 3213 key: 'destroy', 3214 value: function destroy() { 3215 this.currentPlugin.destroy(); 3216 $(window).off('.zf.ResponsiveMenu'); 3217 Foundation.unregisterPlugin(this); 3218 } 3219 }]); 3220 3221 return ResponsiveMenu; 3222 }(); 3223 3224 ResponsiveMenu.defaults = {}; 3225 3226 // The plugin matches the plugin classes with these plugin instances. 3227 var MenuPlugins = { 3228 dropdown: { 3229 cssClass: 'dropdown', 3230 plugin: Foundation._plugins['dropdown-menu'] || null 3231 }, 3232 drilldown: { 3233 cssClass: 'drilldown', 3234 plugin: Foundation._plugins['drilldown'] || null 3235 }, 3236 accordion: { 3237 cssClass: 'accordion-menu', 3238 plugin: Foundation._plugins['accordion-menu'] || null 3239 }, 3240 simple: { 3241 cssClass: '', 3242 plugin: function(){ 3243 this.destroy = function(){} 3244 } 3245 } 3246 }; 3247 3248 // Window exports 3249 Foundation.plugin(ResponsiveMenu, 'ResponsiveMenu'); 3250}(jQuery); 3251'use strict'; 3252 3253!function ($) { 3254 3255 /** 3256 * Motion module. 3257 * @module foundation.motion 3258 */ 3259 3260 var initClasses = ['mui-enter', 'mui-leave']; 3261 var activeClasses = ['mui-enter-active', 'mui-leave-active']; 3262 3263 var Motion = { 3264 animateIn: function (element, animation, cb) { 3265 animate(true, element, animation, cb); 3266 }, 3267 3268 animateOut: function (element, animation, cb) { 3269 animate(false, element, animation, cb); 3270 } 3271 }; 3272 3273 function Move(duration, elem, fn) { 3274 var anim, 3275 prog, 3276 start = null; 3277 // console.log('called'); 3278 3279 if (duration === 0) { 3280 fn.apply(elem); 3281 elem.trigger('finished.zf.animate', [elem]).triggerHandler('finished.zf.animate', [elem]); 3282 return; 3283 } 3284 3285 function move(ts) { 3286 if (!start) start = ts; 3287 // console.log(start, ts); 3288 prog = ts - start; 3289 fn.apply(elem); 3290 3291 if (prog < duration) { 3292 anim = window.requestAnimationFrame(move, elem); 3293 } else { 3294 window.cancelAnimationFrame(anim); 3295 elem.trigger('finished.zf.animate', [elem]).triggerHandler('finished.zf.animate', [elem]); 3296 } 3297 } 3298 anim = window.requestAnimationFrame(move); 3299 } 3300 3301 /** 3302 * Animates an element in or out using a CSS transition class. 3303 * @function 3304 * @private 3305 * @param {Boolean} isIn - Defines if the animation is in or out. 3306 * @param {Object} element - jQuery or HTML object to animate. 3307 * @param {String} animation - CSS class to use. 3308 * @param {Function} cb - Callback to run when animation is finished. 3309 */ 3310 function animate(isIn, element, animation, cb) { 3311 element = $(element).eq(0); 3312 3313 if (!element.length) return; 3314 3315 var initClass = isIn ? initClasses[0] : initClasses[1]; 3316 var activeClass = isIn ? activeClasses[0] : activeClasses[1]; 3317 3318 // Set up the animation 3319 reset(); 3320 3321 element.addClass(animation).css('transition', 'none'); 3322 3323 requestAnimationFrame(function () { 3324 element.addClass(initClass); 3325 if (isIn) element.show(); 3326 }); 3327 3328 // Start the animation 3329 requestAnimationFrame(function () { 3330 element[0].offsetWidth; 3331 element.css('transition', '').addClass(activeClass); 3332 }); 3333 3334 // Clean up the animation when it finishes 3335 element.one(Foundation.transitionend(element), finish); 3336 3337 // Hides the element (for out animations), resets the element, and runs a callback 3338 function finish() { 3339 if (!isIn) element.hide(); 3340 reset(); 3341 if (cb) cb.apply(element); 3342 } 3343 3344 // Resets transitions and removes motion-specific classes 3345 function reset() { 3346 element[0].style.transitionDuration = 0; 3347 element.removeClass(initClass + ' ' + activeClass + ' ' + animation); 3348 } 3349 } 3350 3351 Foundation.Move = Move; 3352 Foundation.Motion = Motion; 3353}(jQuery); 3354/******************************************* 3355 * * 3356 * This util was created by Marius Olbertz * 3357 * Please thank Marius on GitHub /owlbertz * 3358 * or the web http://www.mariusolbertz.de/ * 3359 * * 3360 ******************************************/ 3361 3362'use strict'; 3363 3364!function ($) { 3365 3366 var keyCodes = { 3367 9: 'TAB', 3368 13: 'ENTER', 3369 27: 'ESCAPE', 3370 32: 'SPACE', 3371 37: 'ARROW_LEFT', 3372 38: 'ARROW_UP', 3373 39: 'ARROW_RIGHT', 3374 40: 'ARROW_DOWN' 3375 }; 3376 3377 var commands = {}; 3378 3379 var Keyboard = { 3380 keys: getKeyCodes(keyCodes), 3381 3382 /** 3383 * Parses the (keyboard) event and returns a String that represents its key 3384 * Can be used like Foundation.parseKey(event) === Foundation.keys.SPACE 3385 * @param {Event} event - the event generated by the event handler 3386 * @return String key - String that represents the key pressed 3387 */ 3388 parseKey: function (event) { 3389 var key = keyCodes[event.which || event.keyCode] || String.fromCharCode(event.which).toUpperCase(); 3390 3391 // Remove un-printable characters, e.g. for `fromCharCode` calls for CTRL only events 3392 key = key.replace(/\W+/, ''); 3393 3394 if (event.shiftKey) key = 'SHIFT_' + key; 3395 if (event.ctrlKey) key = 'CTRL_' + key; 3396 if (event.altKey) key = 'ALT_' + key; 3397 3398 // Remove trailing underscore, in case only modifiers were used (e.g. only `CTRL_ALT`) 3399 key = key.replace(/_$/, ''); 3400 3401 return key; 3402 }, 3403 3404 3405 /** 3406 * Handles the given (keyboard) event 3407 * @param {Event} event - the event generated by the event handler 3408 * @param {String} component - Foundation component's name, e.g. Slider or Reveal 3409 * @param {Objects} functions - collection of functions that are to be executed 3410 */ 3411 handleKey: function (event, component, functions) { 3412 var commandList = commands[component], 3413 keyCode = this.parseKey(event), 3414 cmds, 3415 command, 3416 fn; 3417 3418 if (!commandList) return console.warn('Component not defined!'); 3419 3420 if (typeof commandList.ltr === 'undefined') { 3421 // this component does not differentiate between ltr and rtl 3422 cmds = commandList; // use plain list 3423 } else {
3424 // merge ltr and rtl: if document is rtl, rtl overwrites ltr and vice versa 3425 if (Foundation.rtl()) cmds = $.extend({}, commandList.ltr, commandList.rtl);else cmds = $.extend({}, commandList.rtl, commandList.ltr); 3426 } 3427 command = cmds[keyCode]; 3428 3429 fn = functions[command]; 3430 if (fn && typeof fn === 'function') { 3431 // execute function if exists 3432 var returnValue = fn.apply(); 3433 if (functions.handled || typeof functions.handled === 'function') { 3434 // execute function when event was handled 3435 functions.handled(returnValue); 3436 } 3437 } else { 3438 if (functions.unhandled || typeof functions.unhandled === 'function') { 3439 // execute function when event was not handled 3440 functions.unhandled(); 3441 } 3442 } 3443 }, 3444 3445 3446 /** 3447 * Finds all focusable elements within the given `$element` 3448 * @param {jQuery} $element - jQuery object to search within 3449 * @return {jQuery} $focusable - all focusable elements within `$element` 3450 */ 3451 findFocusable: function ($element) { 3452 if (!$element) { 3453 return false; 3454 } 3455 return $element.find('a[href], area[href], input:not([disabled]), select:not([disabled]), textarea:not([disabled]), button:not([disabled]), iframe, object, embed, *[tabindex], *[contenteditable]').filter(function () { 3456 if (!$(this).is(':visible') || $(this).attr('tabindex') < 0) { 3457 return false; 3458 } //only have visible elements and those that have a tabindex greater or equal 0 3459 return true; 3460 }); 3461 }, 3462 3463 3464 /** 3465 * Returns the component name name 3466 * @param {Object} component - Foundation component, e.g. Slider or Reveal 3467 * @return String componentName 3468 */ 3469 3470 register: function (componentName, cmds) { 3471 commands[componentName] = cmds; 3472 }, 3473 3474 3475 /** 3476 * Traps the focus in the given element. 3477 * @param {jQuery} $element jQuery object to trap the foucs into. 3478 */ 3479 trapFocus: function ($element) { 3480 var $focusable = Foundation.Keyboard.findFocusable($element), 3481 $firstFocusable = $focusable.eq(0), 3482 $lastFocusable = $focusable.eq(-1); 3483 3484 $element.on('keydown.zf.trapfocus', function (event) { 3485 if (event.target === $lastFocusable[0] && Foundation.Keyboard.parseKey(event) === 'TAB') { 3486 event.preventDefault(); 3487 $firstFocusable.focus(); 3488 } else if (event.target === $firstFocusable[0] && Foundation.Keyboard.parseKey(event) === 'SHIFT_TAB') { 3489 event.preventDefault(); 3490 $lastFocusable.focus(); 3491 } 3492 }); 3493 }, 3494 3495 /** 3496 * Releases the trapped focus from the given element. 3497 * @param {jQuery} $element jQuery object to release the focus for. 3498 */ 3499 releaseFocus: function ($element) { 3500 $element.off('keydown.zf.trapfocus'); 3501 } 3502 }; 3503 3504 /* 3505 * Constants for easier comparing. 3506 * Can be used like Foundation.parseKey(event) === Foundation.keys.SPACE 3507 */ 3508 function getKeyCodes(kcs) { 3509 var k = {}; 3510 for (var kc in kcs) { 3511 k[kcs[kc]] = kcs[kc]; 3512 }return k; 3513 } 3514 3515 Foundation.Keyboard = Keyboard; 3516}(jQuery); 3517'use strict'; 3518 3519var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 3520 3521function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 3522 3523!function ($) { 3524 3525 /** 3526 * Sticky module. 3527 * @module foundation.sticky 3528 * @requires foundation.util.triggers 3529 * @requires foundation.util.mediaQuery 3530 */ 3531 3532 var Sticky = function () { 3533 /** 3534 * Creates a new instance of a sticky thing. 3535 * @class 3536 * @param {jQuery} element - jQuery object to make sticky. 3537 * @param {Object} options - options object passed when creating the element programmatically. 3538 */ 3539 function Sticky(element, options) { 3540 _classCallCheck(this, Sticky); 3541 3542 this.$element = element; 3543 this.options = $.extend({}, Sticky.defaults, this.$element.data(), options); 3544 3545 this._init(); 3546 3547 Foundation.registerPlugin(this, 'Sticky'); 3548 } 3549 3550 /** 3551 * Initializes the sticky element by adding classes, getting/setting dimensions, breakpoints and attributes 3552 * @function 3553 * @private 3554 */ 3555 3556 3557 _createClass(Sticky, [{ 3558 key: '_init', 3559 value: function _init() { 3560 var $parent = this.$element.parent('[data-sticky-container]'), 3561 id = this.$element[0].id || Foundation.GetYoDigits(6, 'sticky'), 3562 _this = this; 3563 3564 if (!$parent.length) { 3565 this.wasWrapped = true; 3566 } 3567 this.$container = $parent.length ? $parent : $(this.options.container).wrapInner(this.$element); 3568 this.$container.addClass(this.options.containerClass); 3569 3570 this.$element.addClass(this.options.stickyClass).attr({ 'data-resize': id }); 3571 3572 this.scrollCount = this.options.checkEvery; 3573 this.isStuck = false;
3574 $(window).one('load.zf.sticky', function () { 3575 //We calculate the container height to have correct values for anchor points offset calculation. 3576 _this.containerHeight = _this.$element.css("display") == "none" ? 0 : _this.$element[0].getBoundingClientRect().height; 3577 _this.$container.css('height', _this.containerHeight); 3578 _this.elemHeight = _this.containerHeight; 3579 if (_this.options.anchor !== '') { 3580 _this.$anchor = $('#' + _this.options.anchor); 3581 } else { 3582 _this._parsePoints(); 3583 } 3584 3585 _this._setSizes(function () { 3586 var scroll = window.pageYOffset; 3587 _this._calc(false, scroll); 3588 //Unstick the element will ensure that proper classes are set. 3589 if (!_this.isStuck) { 3590 _this._removeSticky(scroll >= _this.topPoint ? false : true); 3591 } 3592 }); 3593 _this._events(id.split('-').reverse().join('-')); 3594 }); 3595 } 3596 3597 /** 3598 * If using multiple elements as anchors, calculates the top and bottom pixel values the sticky thing should stick and unstick on. 3599 * @function 3600 * @private 3601 */ 3602 3603 }, { 3604 key: '_parsePoints', 3605 value: function _parsePoints() { 3606 var top = this.options.topAnchor == "" ? 1 : this.options.topAnchor, 3607 btm = this.options.btmAnchor == "" ? document.documentElement.scrollHeight : this.options.btmAnchor, 3608 pts = [top, btm], 3609 breaks = {}; 3610 for (var i = 0, len = pts.length; i < len && pts[i]; i++) { 3611 var pt; 3612 if (typeof pts[i] === 'number') { 3613 pt = pts[i]; 3614 } else { 3615 var place = pts[i].split(':'), 3616 anchor = $('#' + place[0]); 3617 3618 pt = anchor.offset().top; 3619 if (place[1] && place[1].toLowerCase() === 'bottom') { 3620 pt += anchor[0].getBoundingClientRect().height; 3621 } 3622 } 3623 breaks[i] = pt; 3624 } 3625 3626 this.points = breaks; 3627 return; 3628 } 3629 3630 /** 3631 * Adds event handlers for the scrolling element. 3632 * @private 3633 * @param {String} id - psuedo-random id for unique scroll event listener. 3634 */ 3635 3636 }, { 3637 key: '_events', 3638 value: function _events(id) { 3639 var _this = this, 3640 scrollListener = this.scrollListener = 'scroll.zf.' + id; 3641 if (this.isOn) { 3642 return; 3643 } 3644 if (this.canStick) { 3645 this.isOn = true; 3646 $(window).off(scrollListener).on(scrollListener, function (e) { 3647 if (_this.scrollCount === 0) { 3648 _this.scrollCount = _this.options.checkEvery; 3649 _this._setSizes(function () { 3650 _this._calc(false, window.pageYOffset); 3651 }); 3652 } else { 3653 _this.scrollCount--; 3654 _this._calc(false, window.pageYOffset); 3655 } 3656 }); 3657 } 3658 3659 this.$element.off('resizeme.zf.trigger').on('resizeme.zf.trigger', function (e, el) { 3660 _this._setSizes(function () { 3661 _this._calc(false); 3662 if (_this.canStick) { 3663 if (!_this.isOn) { 3664 _this._events(id); 3665 } 3666 } else if (_this.isOn) { 3667 _this._pauseListeners(scrollListener); 3668 } 3669 }); 3670 }); 3671 } 3672 3673 /** 3674 * Removes event handlers for scroll and change events on anchor. 3675 * @fires Sticky#pause 3676 * @param {String} scrollListener - unique, namespaced scroll listener attached to `window` 3677 */ 3678 3679 }, { 3680 key: '_pauseListeners', 3681 value: function _pauseListeners(scrollListener) { 3682 this.isOn = false; 3683 $(window).off(scrollListener); 3684 3685 /** 3686 * Fires when the plugin is paused due to resize event shrinking the view. 3687 * @event Sticky#pause 3688 * @private 3689 */ 3690 this.$element.trigger('pause.zf.sticky'); 3691 } 3692 3693 /** 3694 * Called on every `scroll` event and on `_init` 3695 * fires functions based on booleans and cached values 3696 * @param {Boolean} checkSizes - true if plugin should recalculate sizes and breakpoints. 3697 * @param {Number} scroll - current scroll position passed from scroll event cb function. If not passed, defaults to `window.pageYOffset`. 3698 */ 3699 3700 }, {
3701 key: '_calc', 3702 value: function _calc(checkSizes, scroll) { 3703 if (checkSizes) { 3704 this._setSizes(); 3705 } 3706 3707 if (!this.canStick) { 3708 if (this.isStuck) { 3709 this._removeSticky(true); 3710 } 3711 return false; 3712 } 3713 3714 if (!scroll) { 3715 scroll = window.pageYOffset; 3716 } 3717 3718 if (scroll >= this.topPoint) { 3719 if (scroll <= this.bottomPoint) { 3720 if (!this.isStuck) { 3721 this._setSticky(); 3722 } 3723 } else { 3724 if (this.isStuck) { 3725 this._removeSticky(false); 3726 } 3727 } 3728 } else { 3729 if (this.isStuck) { 3730 this._removeSticky(true); 3731 } 3732 } 3733 } 3734 3735 /** 3736 * Causes the $element to become stuck. 3737 * Adds `position: fixed;`, and helper classes. 3738 * @fires Sticky#stuckto 3739 * @function 3740 * @private 3741 */ 3742 3743 }, { 3744 key: '_setSticky', 3745 value: function _setSticky() { 3746 var _this = this, 3747 stickTo = this.options.stickTo, 3748 mrgn = stickTo === 'top' ? 'marginTop' : 'marginBottom', 3749 notStuckTo = stickTo === 'top' ? 'bottom' : 'top', 3750 css = {}; 3751 3752 css[mrgn] = this.options[mrgn] + 'em'; 3753 css[stickTo] = 0; 3754 css[notStuckTo] = 'auto'; 3755 this.isStuck = true; 3756 this.$element.removeClass('is-anchored is-at-' + notStuckTo).addClass('is-stuck is-at-' + stickTo).css(css) 3757 /** 3758 * Fires when the $element has become `position: fixed;` 3759 * Namespaced to `top` or `bottom`, e.g. `sticky.zf.stuckto:top` 3760 * @event Sticky#stuckto 3761 */ 3762 .trigger('sticky.zf.stuckto:' + stickTo); 3763 this.$element.on("transitionend webkitTransitionEnd oTransitionEnd otransitionend MSTransitionEnd", function () { 3764 _this._setSizes(); 3765 }); 3766 } 3767 3768 /** 3769 * Causes the $element to become unstuck. 3770 * Removes `position: fixed;`, and helper classes. 3771 * Adds other helper classes. 3772 * @param {Boolean} isTop - tells the function if the $element should anchor to the top or bottom of its $anchor element. 3773 * @fires Sticky#unstuckfrom 3774 * @private 3775 */ 3776 3777 }, { 3778 key: '_removeSticky', 3779 value: function _removeSticky(isTop) { 3780 var stickTo = this.options.stickTo, 3781 stickToTop = stickTo === 'top', 3782 css = {}, 3783 anchorPt = (this.points ? this.points[1] - this.points[0] : this.anchorHeight) - this.elemHeight, 3784 mrgn = stickToTop ? 'marginTop' : 'marginBottom', 3785 notStuckTo = stickToTop ? 'bottom' : 'top', 3786 topOrBottom = isTop ? 'top' : 'bottom'; 3787 3788 css[mrgn] = 0; 3789 3790 css['bottom'] = 'auto'; 3791 if (isTop) { 3792 css['top'] = 0; 3793 } else { 3794 css['top'] = anchorPt; 3795 } 3796 3797 this.isStuck = false; 3798 this.$element.removeClass('is-stuck is-at-' + stickTo).addClass('is-anchored is-at-' + topOrBottom).css(css) 3799 /** 3800 * Fires when the $element has become anchored. 3801 * Namespaced to `top` or `bottom`, e.g. `sticky.zf.unstuckfrom:bottom` 3802 * @event Sticky#unstuckfrom 3803 */ 3804 .trigger('sticky.zf.unstuckfrom:' + topOrBottom); 3805 } 3806 3807 /** 3808 * Sets the $element and $container sizes for plugin. 3809 * Calls `_setBreakPoints`. 3810 * @param {Function} cb - optional callback function to fire on completion of `_setBreakPoints`. 3811 * @private 3812 */ 3813 3814 }, { 3815 key: '_setSizes', 3816 value: function _setSizes(cb) { 3817 this.canStick = Foundation.MediaQuery.is(this.options.stickyOn); 3818 if (!this.canStick) { 3819 if (cb && typeof cb === 'function') { 3820 cb(); 3821 } 3822 } 3823 var _this = this, 3824 newElemWidth = this.$container[0].getBoundingClientRect().width, 3825 comp = window.getComputedStyle(this.$container[0]), 3826 pdngl = parseInt(comp['padding-left'], 10), 3827 pdngr = parseInt(comp['padding-right'], 10); 3828 3829 if (this.$anchor && this.$anchor.length) { 3830 this.anchorHeight = this.$anchor[0].getBoundingClientRect().height; 3831 } else { 3832 this._parsePoints(); 3833 } 3834 3835 this.$element.css({ 3836 'max-width': newElemWidth - pdngl - pdngr + 'px' 3837 }); 3838 3839 var newContainerHeight = this.$element[0].getBoundingClientRect().height || this.containerHeight; 3840 if (this.$element.css("display") == "none") { 3841 newContainerHeight = 0; 3842 } 3843 this.containerHeight = newContainerHeight; 3844 this.$container.css({ 3845 height: newContainerHeight 3846 }); 3847 this.elemHeight = newContainerHeight; 3848 3849 if (!this.isStuck) { 3850 if (this.$element.hasClass('is-at-bottom')) { 3851 var anchorPt = (this.points ? this.points[1] - this.$container.offset().top : this.anchorHeight) - this.elemHeight;
3852 this.$element.css('top', anchorPt); 3853 } 3854 } 3855 3856 this._setBreakPoints(newContainerHeight, function () { 3857 if (cb && typeof cb === 'function') { 3858 cb(); 3859 } 3860 }); 3861 } 3862 3863 /** 3864 * Sets the upper and lower breakpoints for the element to become sticky/unsticky. 3865 * @param {Number} elemHeight - px value for sticky.$element height, calculated by `_setSizes`. 3866 * @param {Function} cb - optional callback function to be called on completion. 3867 * @private 3868 */ 3869 3870 }, { 3871 key: '_setBreakPoints', 3872 value: function _setBreakPoints(elemHeight, cb) { 3873 if (!this.canStick) { 3874 if (cb && typeof cb === 'function') { 3875 cb(); 3876 } else { 3877 return false; 3878 } 3879 } 3880 var mTop = emCalc(this.options.marginTop), 3881 mBtm = emCalc(this.options.marginBottom), 3882 topPoint = this.points ? this.points[0] : this.$anchor.offset().top, 3883 bottomPoint = this.points ? this.points[1] : topPoint + this.anchorHeight, 3884 3885 // topPoint = this.$anchor.offset().top || this.points[0], 3886 // bottomPoint = topPoint + this.anchorHeight || this.points[1], 3887 winHeight = window.innerHeight; 3888 3889 if (this.options.stickTo === 'top') { 3890 topPoint -= mTop; 3891 bottomPoint -= elemHeight + mTop; 3892 } else if (this.options.stickTo === 'bottom') { 3893 topPoint -= winHeight - (elemHeight + mBtm); 3894 bottomPoint -= winHeight - mBtm; 3895 } else { 3896 //this would be the stickTo: both option... tricky 3897 } 3898 3899 this.topPoint = topPoint; 3900 this.bottomPoint = bottomPoint; 3901 3902 if (cb && typeof cb === 'function') { 3903 cb(); 3904 } 3905 } 3906 3907 /** 3908 * Destroys the current sticky element. 3909 * Resets the element to the top position first. 3910 * Removes event listeners, JS-added css properties and classes, and unwraps the $element if the JS added the $container. 3911 * @function 3912 */ 3913 3914 }, { 3915 key: 'destroy', 3916 value: function destroy() { 3917 this._removeSticky(true); 3918 3919 this.$element.removeClass(this.options.stickyClass + ' is-anchored is-at-top').css({ 3920 height: '', 3921 top: '', 3922 bottom: '', 3923 'max-width': '' 3924 }).off('resizeme.zf.trigger'); 3925 if (this.$anchor && this.$anchor.length) { 3926 this.$anchor.off('change.zf.sticky'); 3927 } 3928 $(window).off(this.scrollListener); 3929 3930 if (this.wasWrapped) { 3931 this.$element.unwrap(); 3932 } else { 3933 this.$container.removeClass(this.options.containerClass).css({ 3934 height: '' 3935 }); 3936 } 3937 Foundation.unregisterPlugin(this); 3938 } 3939 }]); 3940 3941 return Sticky; 3942 }(); 3943 3944 Sticky.defaults = { 3945 /** 3946 * Customizable container template. Add your own classes for styling and sizing. 3947 * @option 3948 * @type {string} 3949 * @default '<div data-sticky-container></div>' 3950 */ 3951 container: '<div data-sticky-container></div>', 3952 /** 3953 * Location in the view the element sticks to. Can be `'top'` or `'bottom'`. 3954 * @option 3955 * @type {string} 3956 * @default 'top' 3957 */ 3958 stickTo: 'top', 3959 /** 3960 * If anchored to a single element, the id of that element. 3961 * @option 3962 * @type {string} 3963 * @default '' 3964 */ 3965 anchor: '', 3966 /** 3967 * If using more than one element as anchor points, the id of the top anchor. 3968 * @option 3969 * @type {string} 3970 * @default '' 3971 */ 3972 topAnchor: '', 3973 /** 3974 * If using more than one element as anchor points, the id of the bottom anchor. 3975 * @option 3976 * @type {string} 3977 * @default '' 3978 */ 3979 btmAnchor: '', 3980 /** 3981 * Margin, in `em`'s to apply to the top of the element when it becomes sticky. 3982 * @option 3983 * @type {number} 3984 * @default 1 3985 */ 3986 marginTop: 1, 3987 /** 3988 * Margin, in `em`'s to apply to the bottom of the element when it becomes sticky. 3989 * @option 3990 * @type {number} 3991 * @default 1 3992 */ 3993 marginBottom: 1, 3994 /** 3995 * Breakpoint string that is the minimum screen size an element should become sticky. 3996 * @option 3997 * @type {string} 3998 * @default 'medium' 3999 */ 4000 stickyOn: 'medium', 4001 /** 4002 * Class applied to sticky element, and removed on destruction. Foundation defaults to `sticky`. 4003 * @option 4004 * @type {string} 4005 * @default 'sticky' 4006 */ 4007 stickyClass: 'sticky', 4008 /** 4009 * Class applied to sticky container. Foundation defaults to `sticky-container`. 4010 * @option 4011 * @type {string} 4012 * @default 'sticky-container' 4013 */ 4014 containerClass: 'sticky-container', 4015 /** 4016 * Number of scroll events between the plugin's recalculating sticky points. Setting it to `0` will cause it to recalc every scroll event, setting it to `-1` will prevent recalc on scroll. 4017 * @option 4018 * @type {number} 4019 * @default -1 4020 */ 4021 checkEvery: -1 4022 }; 4023 4024 /** 4025 * Helper function to calculate em values 4026 * @param Number {em} - number of em's to calculate into pixels 4027 */ 4028 function emCalc(em) { 4029 return parseInt(window.getComputedStyle(document.body, null).fontSize, 10) * em; 4030 } 4031 4032 // Window exports 4033 Foundation.plugin(Sticky, 'Sticky'); 4034}(jQuery); 4035'use strict'; 4036 4037var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 4038 4039function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 4040 4041!function ($) { 4042 4043 /** 4044 * OffCanvas module. 4045 * @module foundation.offcanvas 4046 * @requires foundation.util.keyboard 4047 * @requires foundation.util.mediaQuery 4048 * @requires foundation.util.triggers 4049 * @requires foundation.util.motion 4050 */ 4051 4052 var OffCanvas = function () { 4053 /** 4054 * Creates a new instance of an off-canvas wrapper. 4055 * @class 4056 * @fires OffCanvas#init 4057 * @param {Object} element - jQuery object to initialize. 4058 * @param {Object} options - Overrides to the default plugin settings. 4059 */ 4060 function OffCanvas(element, options) { 4061 _classCallCheck(this, OffCanvas); 4062 4063 this.$element = element; 4064 this.options = $.extend({}, OffCanvas.defaults, this.$element.data(), options); 4065 this.$lastTrigger = $(); 4066 this.$triggers = $(); 4067 4068 this._init(); 4069 this._events(); 4070 4071 Foundation.registerPlugin(this, 'OffCanvas'); 4072 Foundation.Keyboard.register('OffCanvas', { 4073 'ESCAPE': 'close' 4074 }); 4075 } 4076 4077 /** 4078 * Initializes the off-canvas wrapper by adding the exit overlay (if needed). 4079 * @function 4080 * @private 4081 */ 4082 4083 4084 _createClass(OffCanvas, [{ 4085 key: '_init', 4086 value: function _init() { 4087 var id = this.$element.attr('id'); 4088 4089 this.$element.attr('aria-hidden', 'true'); 4090 4091 this.$element.addClass('is-transition-' + this.options.transition); 4092 4093 // Find triggers that affect this element and add aria-expanded to them 4094 this.$triggers = $(document).find('[data-open="' + id + '"], [data-close="' + id + '"], [data-toggle="' + id + '"]').attr('aria-expanded', 'false').attr('aria-controls', id); 4095 4096 // Add an overlay over the content if necessary 4097 if (this.options.contentOverlay === true) {
4098 var overlay = document.createElement('div'); 4099 var overlayPosition = $(this.$element).css("position") === 'fixed' ? 'is-overlay-fixed' : 'is-overlay-absolute'; 4100 overlay.setAttribute('class', 'js-off-canvas-overlay ' + overlayPosition); 4101 this.$overlay = $(overlay); 4102 if (overlayPosition === 'is-overlay-fixed') { 4103 $('body').append(this.$overlay); 4104 } else { 4105 this.$element.siblings('[data-off-canvas-content]').append(this.$overlay); 4106 } 4107 } 4108 4109 this.options.isRevealed = this.options.isRevealed || new RegExp(this.options.revealClass, 'g').test(this.$element[0].className); 4110 4111 if (this.options.isRevealed === true) { 4112 this.options.revealOn = this.options.revealOn || this.$element[0].className.match(/(reveal-for-medium|reveal-for-large)/g)[0].split('-')[2]; 4113 this._setMQChecker(); 4114 } 4115 if (!this.options.transitionTime === true) { 4116 this.options.transitionTime = parseFloat(window.getComputedStyle($('[data-off-canvas]')[0]).transitionDuration) * 1000; 4117 } 4118 } 4119 4120 /** 4121 * Adds event handlers to the off-canvas wrapper and the exit overlay. 4122 * @function 4123 * @private 4124 */ 4125 4126 }, { 4127 key: '_events', 4128 value: function _events() { 4129 this.$element.off('.zf.trigger .zf.offcanvas').on({ 4130 'open.zf.trigger': this.open.bind(this), 4131 'close.zf.trigger': this.close.bind(this), 4132 'toggle.zf.trigger': this.toggle.bind(this), 4133 'keydown.zf.offcanvas': this._handleKeyboard.bind(this) 4134 }); 4135 4136 if (this.options.closeOnClick === true) { 4137 var $target = this.options.contentOverlay ? this.$overlay : $('[data-off-canvas-content]'); 4138 $target.on({ 'click.zf.offcanvas': this.close.bind(this) }); 4139 } 4140 } 4141 4142 /** 4143 * Applies event listener for elements that will reveal at certain breakpoints. 4144 * @private 4145 */ 4146 4147 }, { 4148 key: '_setMQChecker', 4149 value: function _setMQChecker() { 4150 var _this = this; 4151 4152 $(window).on('changed.zf.mediaquery', function () { 4153 if (Foundation.MediaQuery.atLeast(_this.options.revealOn)) { 4154 _this.reveal(true); 4155 } else { 4156 _this.reveal(false); 4157 } 4158 }).one('load.zf.offcanvas', function () { 4159 if (Foundation.MediaQuery.atLeast(_this.options.revealOn)) { 4160 _this.reveal(true); 4161 } 4162 }); 4163 } 4164 4165 /** 4166 * Handles the revealing/hiding the off-canvas at breakpoints, not the same as open. 4167 * @param {Boolean} isRevealed - true if element should be revealed. 4168 * @function 4169 */ 4170 4171 }, { 4172 key: 'reveal', 4173 value: function reveal(isRevealed) { 4174 var $closer = this.$element.find('[data-close]'); 4175 if (isRevealed) { 4176 this.close(); 4177 this.isRevealed = true; 4178 this.$element.attr('aria-hidden', 'false'); 4179 this.$element.off('open.zf.trigger toggle.zf.trigger'); 4180 if ($closer.length) { 4181 $closer.hide(); 4182 } 4183 } else { 4184 this.isRevealed = false; 4185 this.$element.attr('aria-hidden', 'true'); 4186 this.$element.on({ 4187 'open.zf.trigger': this.open.bind(this), 4188 'toggle.zf.trigger': this.toggle.bind(this) 4189 }); 4190 if ($closer.length) { 4191 $closer.show(); 4192 } 4193 } 4194 } 4195 4196 /** 4197 * Stops scrolling of the body when offcanvas is open on mobile Safari and other troublesome browsers. 4198 * @private 4199 */ 4200 4201 }, { 4202 key: '_stopScrolling', 4203 value: function _stopScrolling(event) { 4204 return false; 4205 } 4206 4207 // Taken and adapted from http://stackoverflow.com/questions/16889447/prevent-full-page-scrolling-ios 4208 // Only really works for y, not sure how to extend to x or if we need to. 4209 4210 }, { 4211 key: '_recordScrollable', 4212 value: function _recordScrollable(event) { 4213 var elem = this; // called from event handler context with this as elem 4214 4215 // If the element is scrollable (content overflows), then... 4216 if (elem.scrollHeight !== elem.clientHeight) { 4217 // If we're at the top, scroll down one pixel to allow scrolling up 4218 if (elem.scrollTop === 0) { 4219 elem.scrollTop = 1; 4220 } 4221 // If we're at the bottom, scroll up one pixel to allow scrolling down 4222 if (elem.scrollTop === elem.scrollHeight - elem.clientHeight) { 4223 elem.scrollTop = elem.scrollHeight - elem.clientHeight - 1; 4224 } 4225 } 4226 elem.allowUp = elem.scrollTop > 0; 4227 elem.allowDown = elem.scrollTop < elem.scrollHeight - elem.clientHeight; 4228 elem.lastY = event.originalEvent.pageY; 4229 } 4230 }, {
4231 key: '_stopScrollPropagation', 4232 value: function _stopScrollPropagation(event) { 4233 var elem = this; // called from event handler context with this as elem 4234 var up = event.pageY < elem.lastY; 4235 var down = !up; 4236 elem.lastY = event.pageY; 4237 4238 if (up && elem.allowUp || down && elem.allowDown) { 4239 event.stopPropagation(); 4240 } else { 4241 event.preventDefault(); 4242 } 4243 } 4244 4245 /** 4246 * Opens the off-canvas menu. 4247 * @function 4248 * @param {Object} event - Event object passed from listener. 4249 * @param {jQuery} trigger - element that triggered the off-canvas to open. 4250 * @fires OffCanvas#opened 4251 */ 4252 4253 }, { 4254 key: 'open', 4255 value: function open(event, trigger) { 4256 if (this.$element.hasClass('is-open') || this.isRevealed) { 4257 return; 4258 } 4259 var _this = this; 4260 4261 if (trigger) { 4262 this.$lastTrigger = trigger; 4263 } 4264 4265 if (this.options.forceTo === 'top') { 4266 window.scrollTo(0, 0); 4267 } else if (this.options.forceTo === 'bottom') { 4268 window.scrollTo(0, document.body.scrollHeight); 4269 } 4270 4271 /** 4272 * Fires when the off-canvas menu opens. 4273 * @event OffCanvas#opened 4274 */ 4275 _this.$element.addClass('is-open'); 4276 4277 this.$triggers.attr('aria-expanded', 'true'); 4278 this.$element.attr('aria-hidden', 'false').trigger('opened.zf.offcanvas'); 4279 4280 // If `contentScroll` is set to false, add class and disable scrolling on touch devices. 4281 if (this.options.contentScroll === false) { 4282 $('body').addClass('is-off-canvas-open').on('touchmove', this._stopScrolling); 4283 this.$element.on('touchstart', this._recordScrollable); 4284 this.$element.on('touchmove', this._stopScrollPropagation); 4285 } 4286 4287 if (this.options.contentOverlay === true) { 4288 this.$overlay.addClass('is-visible'); 4289 } 4290 4291 if (this.options.closeOnClick === true && this.options.contentOverlay === true) { 4292 this.$overlay.addClass('is-closable'); 4293 } 4294 4295 if (this.options.autoFocus === true) { 4296 this.$element.one(Foundation.transitionend(this.$element), function () { 4297 _this.$element.find('a, button').eq(0).focus(); 4298 }); 4299 } 4300 4301 if (this.options.trapFocus === true) { 4302 this.$element.siblings('[data-off-canvas-content]').attr('tabindex', '-1'); 4303 Foundation.Keyboard.trapFocus(this.$element); 4304 } 4305 } 4306 4307 /** 4308 * Closes the off-canvas menu. 4309 * @function 4310 * @param {Function} cb - optional cb to fire after closure. 4311 * @fires OffCanvas#closed 4312 */ 4313 4314 }, { 4315 key: 'close', 4316 value: function close(cb) { 4317 if (!this.$element.hasClass('is-open') || this.isRevealed) { 4318 return; 4319 } 4320 4321 var _this = this; 4322 4323 _this.$element.removeClass('is-open'); 4324 4325 this.$element.attr('aria-hidden', 'true') 4326 /** 4327 * Fires when the off-canvas menu opens. 4328 * @event OffCanvas#closed 4329 */ 4330 .trigger('closed.zf.offcanvas'); 4331 4332 // If `contentScroll` is set to false, remove class and re-enable scrolling on touch devices. 4333 if (this.options.contentScroll === false) { 4334 $('body').removeClass('is-off-canvas-open').off('touchmove', this._stopScrolling); 4335 this.$element.off('touchstart', this._recordScrollable); 4336 this.$element.off('touchmove', this._stopScrollPropagation); 4337 } 4338 4339 if (this.options.contentOverlay === true) { 4340 this.$overlay.removeClass('is-visible'); 4341 } 4342 4343 if (this.options.closeOnClick === true && this.options.contentOverlay === true) { 4344 this.$overlay.removeClass('is-closable'); 4345 } 4346 4347 this.$triggers.attr('aria-expanded', 'false'); 4348 4349 if (this.options.trapFocus === true) { 4350 this.$element.siblings('[data-off-canvas-content]').removeAttr('tabindex'); 4351 Foundation.Keyboard.releaseFocus(this.$element); 4352 } 4353 } 4354 4355 /** 4356 * Toggles the off-canvas menu open or closed. 4357 * @function 4358 * @param {Object} event - Event object passed from listener. 4359 * @param {jQuery} trigger - element that triggered the off-canvas to open. 4360 */ 4361 4362 }, {
4363 key: 'toggle', 4364 value: function toggle(event, trigger) { 4365 if (this.$element.hasClass('is-open')) { 4366 this.close(event, trigger); 4367 } else { 4368 this.open(event, trigger); 4369 } 4370 } 4371 4372 /** 4373 * Handles keyboard input when detected. When the escape key is pressed, the off-canvas menu closes, and focus is restored to the element that opened the menu. 4374 * @function 4375 * @private 4376 */ 4377 4378 }, { 4379 key: '_handleKeyboard', 4380 value: function _handleKeyboard(e) { 4381 var _this2 = this; 4382 4383 Foundation.Keyboard.handleKey(e, 'OffCanvas', { 4384 close: function () { 4385 _this2.close(); 4386 _this2.$lastTrigger.focus(); 4387 return true; 4388 }, 4389 handled: function () { 4390 e.stopPropagation(); 4391 e.preventDefault(); 4392 } 4393 }); 4394 } 4395 4396 /** 4397 * Destroys the offcanvas plugin. 4398 * @function 4399 */ 4400 4401 }, { 4402 key: 'destroy', 4403 value: function destroy() { 4404 this.close(); 4405 this.$element.off('.zf.trigger .zf.offcanvas'); 4406 this.$overlay.off('.zf.offcanvas'); 4407 4408 Foundation.unregisterPlugin(this); 4409 } 4410 }]); 4411 4412 return OffCanvas; 4413 }(); 4414 4415 OffCanvas.defaults = { 4416 /** 4417 * Allow the user to click outside of the menu to close it. 4418 * @option 4419 * @type {boolean} 4420 * @default true 4421 */ 4422 closeOnClick: true, 4423 4424 /** 4425 * Adds an overlay on top of `[data-off-canvas-content]`. 4426 * @option 4427 * @type {boolean} 4428 * @default true 4429 */ 4430 contentOverlay: true, 4431 4432 /** 4433 * Enable/disable scrolling of the main content when an off canvas panel is open. 4434 * @option 4435 * @type {boolean} 4436 * @default true 4437 */ 4438 contentScroll: true, 4439 4440 /** 4441 * Amount of time in ms the open and close transition requires. If none selected, pulls from body style. 4442 * @option 4443 * @type {number} 4444 * @default 0 4445 */ 4446 transitionTime: 0, 4447 4448 /** 4449 * Type of transition for the offcanvas menu. Options are 'push', 'detached' or 'slide'. 4450 * @option 4451 * @type {string} 4452 * @default push 4453 */ 4454 transition: 'push', 4455 4456 /** 4457 * Force the page to scroll to top or bottom on open. 4458 * @option 4459 * @type {?string} 4460 * @default null 4461 */ 4462 forceTo: null, 4463 4464 /** 4465 * Allow the offcanvas to remain open for certain breakpoints. 4466 * @option 4467 * @type {boolean} 4468 * @default false 4469 */ 4470 isRevealed: false, 4471 4472 /** 4473 * Breakpoint at which to reveal. JS will use a RegExp to target standard classes, if changing classnames, pass your class with the `revealClass` option. 4474 * @option 4475 * @type {?string} 4476 * @default null 4477 */ 4478 revealOn: null, 4479 4480 /** 4481 * Force focus to the offcanvas on open. If true, will focus the opening trigger on close. 4482 * @option 4483 * @type {boolean} 4484 * @default true 4485 */ 4486 autoFocus: true, 4487 4488 /** 4489 * Class used to force an offcanvas to remain open. Foundation defaults for this are `reveal-for-large` & `reveal-for-medium`. 4490 * @option 4491 * @type {string} 4492 * @default reveal-for- 4493 * @todo improve the regex testing for this. 4494 */ 4495 revealClass: 'reveal-for-', 4496 4497 /** 4498 * Triggers optional focus trapping when opening an offcanvas. Sets tabindex of [data-off-canvas-content] to -1 for accessibility purposes. 4499 * @option 4500 * @type {boolean} 4501 * @default false 4502 */ 4503 trapFocus: false 4504 }; 4505 4506 // Window exports 4507 Foundation.plugin(OffCanvas, 'OffCanvas'); 4508}(jQuery); 4509'use strict'; 4510 4511!function ($) { 4512 4513 function Timer(elem, options, cb) { 4514 var _this = this, 4515 duration = options.duration, 4516 //options is an object for easily adding features later. 4517 nameSpace = Object.keys(elem.data())[0] || 'timer', 4518 remain = -1, 4519 start, 4520 timer; 4521 4522 this.isPaused = false; 4523 4524 this.restart = function () { 4525 remain = -1; 4526 clearTimeout(timer); 4527 this.start(); 4528 }; 4529 4530 this.start = function () { 4531 this.isPaused = false; 4532 // if(!elem.data('paused')){ return false; }//maybe implement this sanity check if used for other things. 4533 clearTimeout(timer); 4534 remain = remain <= 0 ? duration : remain; 4535 elem.data('paused', false); 4536 start = Date.now(); 4537 timer = setTimeout(function () { 4538 if (options.infinite) { 4539 _this.restart(); //rerun the timer. 4540 } 4541 if (cb && typeof cb === 'function') { 4542 cb(); 4543 } 4544 }, remain); 4545 elem.trigger('timerstart.zf.' + nameSpace); 4546 }; 4547 4548 this.pause = function () { 4549 this.isPaused = true; 4550 //if(elem.data('paused')){ return false; }//maybe implement this sanity check if used for other things. 4551 clearTimeout(timer); 4552 elem.data('paused', true); 4553 var end = Date.now(); 4554 remain = remain - (end - start); 4555 elem.trigger('timerpaused.zf.' + nameSpace); 4556 }; 4557 } 4558 4559 /** 4560 * Runs a callback function when images are fully loaded. 4561 * @param {Object} images - Image(s) to check if loaded. 4562 * @param {Func} callback - Function to execute when image is fully loaded. 4563 */ 4564 function onImagesLoaded(images, callback) { 4565 var self = this, 4566 unloaded = images.length; 4567 4568 if (unloaded === 0) { 4569 callback(); 4570 } 4571 4572 images.each(function () { 4573 // Check if image is loaded 4574 if (this.complete || this.readyState === 4 || this.readyState === 'complete') { 4575 singleImageLoaded(); 4576 } 4577 // Force load the image 4578 else {
4579 // fix for IE. See https://css-tricks.com/snippets/jquery/fixing-load-in-ie-for-cached-images/ 4580 var src = $(this).attr('src'); 4581 $(this).attr('src', src + (src.indexOf('?') >= 0 ? '&' : '?') + new Date().getTime()); 4582 $(this).one('load', function () { 4583 singleImageLoaded(); 4584 }); 4585 } 4586 }); 4587 4588 function singleImageLoaded() { 4589 unloaded--; 4590 if (unloaded === 0) { 4591 callback(); 4592 } 4593 } 4594 } 4595 4596 Foundation.Timer = Timer; 4597 Foundation.onImagesLoaded = onImagesLoaded; 4598}(jQuery); 4599'use strict'; 4600 4601!function ($) { 4602 4603 Foundation.Box = { 4604 ImNotTouchingYou: ImNotTouchingYou, 4605 GetDimensions: GetDimensions, 4606 GetOffsets: GetOffsets 4607 }; 4608 4609 /** 4610 * Compares the dimensions of an element to a container and determines collision events with container. 4611 * @function 4612 * @param {jQuery} element - jQuery object to test for collisions. 4613 * @param {jQuery} parent - jQuery object to use as bounding container. 4614 * @param {Boolean} lrOnly - set to true to check left and right values only. 4615 * @param {Boolean} tbOnly - set to true to check top and bottom values only. 4616 * @default if no parent object passed, detects collisions with `window`. 4617 * @returns {Boolean} - true if collision free, false if a collision in any direction. 4618 */ 4619 function ImNotTouchingYou(element, parent, lrOnly, tbOnly) { 4620 var eleDims = GetDimensions(element), 4621 top, 4622 bottom, 4623 left, 4624 right; 4625 4626 if (parent) { 4627 var parDims = GetDimensions(parent); 4628 4629 bottom = eleDims.offset.top + eleDims.height <= parDims.height + parDims.offset.top; 4630 top = eleDims.offset.top >= parDims.offset.top; 4631 left = eleDims.offset.left >= parDims.offset.left; 4632 right = eleDims.offset.left + eleDims.width <= parDims.width + parDims.offset.left; 4633 } else { 4634 bottom = eleDims.offset.top + eleDims.height <= eleDims.windowDims.height + eleDims.windowDims.offset.top; 4635 top = eleDims.offset.top >= eleDims.windowDims.offset.top; 4636 left = eleDims.offset.left >= eleDims.windowDims.offset.left; 4637 right = eleDims.offset.left + eleDims.width <= eleDims.windowDims.width; 4638 } 4639 4640 var allDirs = [bottom, top, left, right]; 4641 4642 if (lrOnly) { 4643 return left === right === true; 4644 } 4645 4646 if (tbOnly) { 4647 return top === bottom === true; 4648 } 4649 4650 return allDirs.indexOf(false) === -1; 4651 }; 4652 4653 /** 4654 * Uses native methods to return an object of dimension values. 4655 * @function 4656 * @param {jQuery || HTML} element - jQuery object or DOM element for which to get the dimensions. Can be any element other that document or window. 4657 * @returns {Object} - nested object of integer pixel values 4658 * TODO - if element is window, return only those values. 4659 */ 4660 function GetDimensions(elem, test) { 4661 elem = elem.length ? elem[0] : elem; 4662 4663 if (elem === window || elem === document) { 4664 throw new Error("I'm sorry, Dave. I'm afraid I can't do that."); 4665 } 4666 4667 var rect = elem.getBoundingClientRect(), 4668 parRect = elem.parentNode.getBoundingClientRect(), 4669 winRect = document.body.getBoundingClientRect(), 4670 winY = window.pageYOffset, 4671 winX = window.pageXOffset; 4672 4673 return { 4674 width: rect.width, 4675 height: rect.height, 4676 offset: { 4677 top: rect.top + winY, 4678 left: rect.left + winX 4679 }, 4680 parentDims: { 4681 width: parRect.width, 4682 height: parRect.height, 4683 offset: { 4684 top: parRect.top + winY, 4685 left: parRect.left + winX 4686 } 4687 }, 4688 windowDims: { 4689 width: winRect.width, 4690 height: winRect.height, 4691 offset: { 4692 top: winY, 4693 left: winX 4694 } 4695 } 4696 }; 4697 } 4698 4699 /** 4700 * Returns an object of top and left integer pixel values for dynamically rendered elements, 4701 * such as: Tooltip, Reveal, and Dropdown 4702 * @function 4703 * @param {jQuery} element - jQuery object for the element being positioned. 4704 * @param {jQuery} anchor - jQuery object for the element's anchor point. 4705 * @param {String} position - a string relating to the desired position of the element, relative to it's anchor 4706 * @param {Number} vOffset - integer pixel value of desired vertical separation between anchor and element. 4707 * @param {Number} hOffset - integer pixel value of desired horizontal separation between anchor and element. 4708 * @param {Boolean} isOverflow - if a collision event is detected, sets to true to default the element to full width - any desired offset. 4709 * TODO alter/rewrite to work with `em` values as well/instead of pixels 4710 */
4711 function GetOffsets(element, anchor, position, vOffset, hOffset, isOverflow) { 4712 var $eleDims = GetDimensions(element), 4713 $anchorDims = anchor ? GetDimensions(anchor) : null; 4714 4715 switch (position) { 4716 case 'top': 4717 return { 4718 left: Foundation.rtl() ? $anchorDims.offset.left - $eleDims.width + $anchorDims.width : $anchorDims.offset.left, 4719 top: $anchorDims.offset.top - ($eleDims.height + vOffset) 4720 }; 4721 break; 4722 case 'left': 4723 return { 4724 left: $anchorDims.offset.left - ($eleDims.width + hOffset), 4725 top: $anchorDims.offset.top 4726 }; 4727 break; 4728 case 'right': 4729 return { 4730 left: $anchorDims.offset.left + $anchorDims.width + hOffset, 4731 top: $anchorDims.offset.top 4732 }; 4733 break; 4734 case 'center top': 4735 return { 4736 left: $anchorDims.offset.left + $anchorDims.width / 2 - $eleDims.width / 2, 4737 top: $anchorDims.offset.top - ($eleDims.height + vOffset) 4738 }; 4739 break; 4740 case 'center bottom': 4741 return { 4742 left: isOverflow ? hOffset : $anchorDims.offset.left + $anchorDims.width / 2 - $eleDims.width / 2, 4743 top: $anchorDims.offset.top + $anchorDims.height + vOffset 4744 }; 4745 break; 4746 case 'center left': 4747 return { 4748 left: $anchorDims.offset.left - ($eleDims.width + hOffset), 4749 top: $anchorDims.offset.top + $anchorDims.height / 2 - $eleDims.height / 2 4750 }; 4751 break; 4752 case 'center right': 4753 return { 4754 left: $anchorDims.offset.left + $anchorDims.width + hOffset + 1, 4755 top: $anchorDims.offset.top + $anchorDims.height / 2 - $eleDims.height / 2 4756 }; 4757 break; 4758 case 'center': 4759 return { 4760 left: $eleDims.windowDims.offset.left + $eleDims.windowDims.width / 2 - $eleDims.width / 2, 4761 top: $eleDims.windowDims.offset.top + $eleDims.windowDims.height / 2 - $eleDims.height / 2 4762 }; 4763 break; 4764 case 'reveal': 4765 return { 4766 left: ($eleDims.windowDims.width - $eleDims.width) / 2, 4767 top: $eleDims.windowDims.offset.top + vOffset 4768 }; 4769 case 'reveal full': 4770 return { 4771 left: $eleDims.windowDims.offset.left, 4772 top: $eleDims.windowDims.offset.top 4773 }; 4774 break; 4775 case 'left bottom': 4776 return { 4777 left: $anchorDims.offset.left, 4778 top: $anchorDims.offset.top + $anchorDims.height + vOffset 4779 }; 4780 break; 4781 case 'right bottom': 4782 return { 4783 left: $anchorDims.offset.left + $anchorDims.width + hOffset - $eleDims.width, 4784 top: $anchorDims.offset.top + $anchorDims.height + vOffset 4785 }; 4786 break; 4787 default: 4788 return { 4789 left: Foundation.rtl() ? $anchorDims.offset.left - $eleDims.width + $anchorDims.width : $anchorDims.offset.left + hOffset, 4790 top: $anchorDims.offset.top + $anchorDims.height + vOffset 4791 }; 4792 } 4793 } 4794}(jQuery); 4795'use strict'; 4796 4797!function ($) { 4798 4799 var MutationObserver = function () { 4800 var prefixes = ['WebKit', 'Moz', 'O', 'Ms', '']; 4801 for (var i = 0; i < prefixes.length; i++) { 4802 if (prefixes[i] + 'MutationObserver' in window) { 4803 return window[prefixes[i] + 'MutationObserver']; 4804 } 4805 } 4806 return false; 4807 }(); 4808 4809 var triggers = function (el, type) { 4810 el.data(type).split(' ').forEach(function (id) { 4811 $('#' + id)[type === 'close' ? 'trigger' : 'triggerHandler'](type + '.zf.trigger', [el]); 4812 }); 4813 }; 4814 // Elements with [data-open] will reveal a plugin that supports it when clicked. 4815 $(document).on('click.zf.trigger', '[data-open]', function () { 4816 triggers($(this), 'open'); 4817 }); 4818 4819 // Elements with [data-close] will close a plugin that supports it when clicked. 4820 // If used without a value on [data-close], the event will bubble, allowing it to close a parent component. 4821 $(document).on('click.zf.trigger', '[data-close]', function () { 4822 var id = $(this).data('close'); 4823 if (id) { 4824 triggers($(this), 'close'); 4825 } else { 4826 $(this).trigger('close.zf.trigger'); 4827 } 4828 }); 4829 4830 // Elements with [data-toggle] will toggle a plugin that supports it when clicked. 4831 $(document).on('click.zf.trigger', '[data-toggle]', function () { 4832 var id = $(this).data('toggle'); 4833 if (id) { 4834 triggers($(this), 'toggle'); 4835 } else { 4836 $(this).trigger('toggle.zf.trigger'); 4837 } 4838 }); 4839 4840 // Elements with [data-closable] will respond to close.zf.trigger events. 4841 $(document).on('close.zf.trigger', '[data-closable]', function (e) { 4842 e.stopPropagation(); 4843 var animation = $(this).data('closable'); 4844 4845 if (animation !== '') { 4846 Foundation.Motion.animateOut($(this), animation, function () { 4847 $(this).trigger('closed.zf'); 4848 }); 4849 } else { 4850 $(this).fadeOut().trigger('closed.zf'); 4851 } 4852 }); 4853 4854 $(document).on('focus.zf.trigger blur.zf.trigger', '[data-toggle-focus]', function () { 4855 var id = $(this).data('toggle-focus'); 4856 $('#' + id).triggerHandler('toggle.zf.trigger', [$(this)]); 4857 }); 4858 4859 /** 4860 * Fires once after all other scripts have loaded 4861 * @function 4862 * @private 4863 */ 4864 $(window).on('load', function () { 4865 checkListeners(); 4866 }); 4867 4868 function checkListeners() { 4869 eventsListener(); 4870 resizeListener(); 4871 scrollListener(); 4872 mutateListener(); 4873 closemeListener(); 4874 } 4875 4876 //******** only fires this function once on load, if there's something to watch ******** 4877 function closemeListener(pluginName) { 4878 var yetiBoxes = $('[data-yeti-box]'), 4879 plugNames = ['dropdown', 'tooltip', 'reveal']; 4880 4881 if (pluginName) { 4882 if (typeof pluginName === 'string') { 4883 plugNames.push(pluginName); 4884 } else if (typeof pluginName === 'object' && typeof pluginName[0] === 'string') { 4885 plugNames.concat(pluginName); 4886 } else { 4887 console.error('Plugin names must be strings'); 4888 } 4889 } 4890 if (yetiBoxes.length) { 4891 var listeners = plugNames.map(function (name) { 4892 return 'closeme.zf.' + name; 4893 }).join(' '); 4894 4895 $(window).off(listeners).on(listeners, function (e, pluginId) { 4896 var plugin = e.namespace.split('.')[0]; 4897 var plugins = $('[data-' + plugin + ']').not('[data-yeti-box="' + pluginId + '"]'); 4898 4899 plugins.each(function () { 4900 var _this = $(this); 4901 4902 _this.triggerHandler('close.zf.trigger', [_this]); 4903 }); 4904 }); 4905 } 4906 } 4907 4908 function resizeListener(debounce) { 4909 var timer = void 0, 4910 $nodes = $('[data-resize]'); 4911 if ($nodes.length) { 4912 $(window).off('resize.zf.trigger').on('resize.zf.trigger', function (e) { 4913 if (timer) { 4914 clearTimeout(timer); 4915 } 4916 4917 timer = setTimeout(function () { 4918 4919 if (!MutationObserver) { 4920 //fallback for IE 9 4921 $nodes.each(function () { 4922 $(this).triggerHandler('resizeme.zf.trigger'); 4923 }); 4924 } 4925 //trigger all listening elements and signal a resize event 4926 $nodes.attr('data-events', "resize"); 4927 }, debounce || 10); //default time to emit resize event 4928 }); 4929 } 4930 } 4931 4932 function scrollListener(debounce) { 4933 var timer = void 0, 4934 $nodes = $('[data-scroll]'); 4935 if ($nodes.length) { 4936 $(window).off('scroll.zf.trigger').on('scroll.zf.trigger', function (e) { 4937 if (timer) { 4938 clearTimeout(timer); 4939 } 4940 4941 timer = setTimeout(function () { 4942 4943 if (!MutationObserver) { 4944 //fallback for IE 9 4945 $nodes.each(function () { 4946 $(this).triggerHandler('scrollme.zf.trigger'); 4947 }); 4948 } 4949 //trigger all listening elements and signal a scroll event 4950 $nodes.attr('data-events', "scroll"); 4951 }, debounce || 10); //default time to emit scroll event 4952 }); 4953 } 4954 } 4955 4956 function mutateListener(debounce) { 4957 var $nodes = $('[data-mutate]'); 4958 if ($nodes.length && MutationObserver) { 4959 //trigger all listening elements and signal a mutate event 4960 //no IE 9 or 10 4961 $nodes.each(function () { 4962 $(this).triggerHandler('mutateme.zf.trigger'); 4963 }); 4964 } 4965 } 4966 4967 function eventsListener() { 4968 if (!MutationObserver) { 4969 return false;
4970 } 4971 var nodes = document.querySelectorAll('[data-resize], [data-scroll], [data-mutate]'); 4972 4973 //element callback 4974 var listeningElementsMutation = function (mutationRecordsList) { 4975 var $target = $(mutationRecordsList[0].target); 4976 4977 //trigger the event handler for the element depending on type 4978 switch (mutationRecordsList[0].type) { 4979 4980 case "attributes": 4981 if ($target.attr("data-events") === "scroll" && mutationRecordsList[0].attributeName === "data-events") { 4982 $target.triggerHandler('scrollme.zf.trigger', [$target, window.pageYOffset]); 4983 } 4984 if ($target.attr("data-events") === "resize" && mutationRecordsList[0].attributeName === "data-events") { 4985 $target.triggerHandler('resizeme.zf.trigger', [$target]); 4986 } 4987 if (mutationRecordsList[0].attributeName === "style") { 4988 $target.closest("[data-mutate]").attr("data-events", "mutate"); 4989 $target.closest("[data-mutate]").triggerHandler('mutateme.zf.trigger', [$target.closest("[data-mutate]")]); 4990 } 4991 break; 4992 4993 case "childList": 4994 $target.closest("[data-mutate]").attr("data-events", "mutate"); 4995 $target.closest("[data-mutate]").triggerHandler('mutateme.zf.trigger', [$target.closest("[data-mutate]")]); 4996 break; 4997 4998 default: 4999 return false; 5000 //nothing 5001 } 5002 }; 5003 5004 if (nodes.length) { 5005 //for each element that needs to listen for resizing, scrolling, or mutation add a single observer 5006 for (var i = 0; i <= nodes.length - 1; i++) { 5007 var elementObserver = new MutationObserver(listeningElementsMutation); 5008 elementObserver.observe(nodes[i], { attributes: true, childList: true, characterData: false, subtree: true, attributeFilter: ["data-events", "style"] }); 5009 } 5010 } 5011 } 5012 5013 // ------------------------------------ 5014 5015 // [PH] 5016 // Foundation.CheckWatchers = checkWatchers; 5017 Foundation.IHearYou = checkListeners; 5018 // Foundation.ISeeYou = scrollListener; 5019 // Foundation.IFeelYou = closemeListener; 5020}(jQuery); 5021 5022// function domMutationObserver(debounce) { 5023// // !!! This is coming soon and needs more work; not active !!! // 5024// var timer, 5025// nodes = document.querySelectorAll('[data-mutate]'); 5026// // 5027// if (nodes.length) { 5028// // var MutationObserver = (function () { 5029// // var prefixes = ['WebKit', 'Moz', 'O', 'Ms', '']; 5030// // for (var i=0; i < prefixes.length; i++) { 5031// // if (prefixes[i] + 'MutationObserver' in window) { 5032// // return window[prefixes[i] + 'MutationObserver']; 5033// // } 5034// // } 5035// // return false; 5036// // }()); 5037// 5038// 5039// //for the body, we need to listen for all changes effecting the style and class attributes 5040// var bodyObserver = new MutationObserver(bodyMutation); 5041// bodyObserver.observe(document.body, { attributes: true, childList: true, characterData: false, subtree:true, attributeFilter:["style", "class"]}); 5042// 5043// 5044// //body callback 5045// function bodyMutation(mutate) { 5046// //trigger all listening elements and signal a mutation event 5047// if (timer) { clearTimeout(timer); } 5048// 5049// timer = setTimeout(function() { 5050// bodyObserver.disconnect(); 5051// $('[data-mutate]').attr('data-events',"mutate"); 5052// }, debounce || 150); 5053// } 5054// } 5055// } 5056//************************************************** 5057//**Work inspired by multiple jquery swipe plugins** 5058//**Done by Yohai Ararat *************************** 5059//************************************************** 5060(function ($) { 5061 5062 $.spotSwipe = { 5063 version: '1.0.0', 5064 enabled: 'ontouchstart' in document.documentElement, 5065 preventDefault: false, 5066 moveThreshold: 75, 5067 timeThreshold: 200 5068 }; 5069 5070 var startPosX, 5071 startPosY, 5072 startTime, 5073 elapsedTime, 5074 isMoving = false; 5075 5076 function onTouchEnd() { 5077 // alert(this); 5078 this.removeEventListener('touchmove', onTouchMove); 5079 this.removeEventListener('touchend', onTouchEnd); 5080 isMoving = false; 5081 } 5082 5083 function onTouchMove(e) { 5084 if ($.spotSwipe.preventDefault) { 5085 e.preventDefault(); 5086 } 5087 if (isMoving) { 5088 var x = e.touches[0].pageX; 5089 var y = e.touches[0].pageY; 5090 var dx = startPosX - x; 5091 var dy = startPosY - y; 5092 var dir; 5093 elapsedTime = new Date().getTime() - startTime; 5094 if (Math.abs(dx) >= $.spotSwipe.moveThreshold && elapsedTime <= $.spotSwipe.timeThreshold) { 5095 dir = dx > 0 ? 'left' : 'right'; 5096 } 5097 // else if(Math.abs(dy) >= $.spotSwipe.moveThreshold && elapsedTime <= $.spotSwipe.timeThreshold) { 5098 // dir = dy > 0 ? 'down' : 'up'; 5099 // } 5100 if (dir) { 5101 e.preventDefault(); 5102 onTouchEnd.call(this); 5103 $(this).trigger('swipe', dir).trigger('swipe' + dir); 5104 } 5105 } 5106 } 5107 5108 function onTouchStart(e) { 5109 if (e.touches.length == 1) { 5110 startPosX = e.touches[0].pageX; 5111 startPosY = e.touches[0].pageY; 5112 isMoving = true; 5113 startTime = new Date().getTime(); 5114 this.addEventListener('touchmove', onTouchMove, false); 5115 this.addEventListener('touchend', onTouchEnd, false); 5116 } 5117 } 5118
5119 function init() { 5120 this.addEventListener && this.addEventListener('touchstart', onTouchStart, false); 5121 } 5122 5123 function teardown() { 5124 this.removeEventListener('touchstart', onTouchStart); 5125 } 5126 5127 $.event.special.swipe = { setup: init }; 5128 5129 $.each(['left', 'up', 'down', 'right'], function () { 5130 $.event.special['swipe' + this] = { setup: function () { 5131 $(this).on('swipe', $.noop); 5132 } }; 5133 }); 5134})(jQuery); 5135/**************************************************** 5136 * Method for adding psuedo drag events to elements * 5137 ***************************************************/ 5138!function ($) { 5139 $.fn.addTouch = function () { 5140 this.each(function (i, el) { 5141 $(el).bind('touchstart touchmove touchend touchcancel', function () { 5142 //we pass the original event object because the jQuery event 5143 //object is normalized to w3c specs and does not provide the TouchList 5144 handleTouch(event); 5145 }); 5146 }); 5147 5148 var handleTouch = function (event) { 5149 var touches = event.changedTouches, 5150 first = touches[0], 5151 eventTypes = { 5152 touchstart: 'mousedown', 5153 touchmove: 'mousemove', 5154 touchend: 'mouseup' 5155 }, 5156 type = eventTypes[event.type], 5157 simulatedEvent; 5158 5159 if ('MouseEvent' in window && typeof window.MouseEvent === 'function') { 5160 simulatedEvent = new window.MouseEvent(type, { 5161 'bubbles': true, 5162 'cancelable': true, 5163 'screenX': first.screenX, 5164 'screenY': first.screenY, 5165 'clientX': first.clientX, 5166 'clientY': first.clientY 5167 }); 5168 } else { 5169 simulatedEvent = document.createEvent('MouseEvent'); 5170 simulatedEvent.initMouseEvent(type, true, true, window, 1, first.screenX, first.screenY, first.clientX, first.clientY, false, false, false, false, 0 /*left*/, null); 5171 } 5172 first.target.dispatchEvent(simulatedEvent); 5173 }; 5174 }; 5175}(jQuery); 5176 5177//********************************** 5178//**From the jQuery Mobile Library** 5179//**need to recreate functionality** 5180//**and try to improve if possible** 5181//********************************** 5182 5183/* Removing the jQuery function **** 5184************************************ 5185 5186(function( $, window, undefined ) { 5187 5188 var $document = $( document ), 5189 // supportTouch = $.mobile.support.touch, 5190 touchStartEvent = 'touchstart'//supportTouch ? "touchstart" : "mousedown", 5191 touchStopEvent = 'touchend'//supportTouch ? "touchend" : "mouseup", 5192 touchMoveEvent = 'touchmove'//supportTouch ? "touchmove" : "mousemove"; 5193 5194 // setup new event shortcuts 5195 $.each( ( "touchstart touchmove touchend " + 5196 "swipe swipeleft swiperight" ).split( " " ), function( i, name ) { 5197 5198 $.fn[ name ] = function( fn ) { 5199 return fn ? this.bind( name, fn ) : this.trigger( name ); 5200 }; 5201 5202 // jQuery < 1.8 5203 if ( $.attrFn ) { 5204 $.attrFn[ name ] = true; 5205 } 5206 }); 5207 5208 function triggerCustomEvent( obj, eventType, event, bubble ) { 5209 var originalType = event.type; 5210 event.type = eventType; 5211 if ( bubble ) { 5212 $.event.trigger( event, undefined, obj ); 5213 } else { 5214 $.event.dispatch.call( obj, event ); 5215 } 5216 event.type = originalType; 5217 } 5218 5219 // also handles taphold 5220 5221 // Also handles swipeleft, swiperight 5222 $.event.special.swipe = { 5223 5224 // More than this horizontal displacement, and we will suppress scrolling. 5225 scrollSupressionThreshold: 30, 5226 5227 // More time than this, and it isn't a swipe. 5228 durationThreshold: 1000, 5229 5230 // Swipe horizontal displacement must be more than this. 5231 horizontalDistanceThreshold: window.devicePixelRatio >= 2 ? 15 : 30, 5232 5233 // Swipe vertical displacement must be less than this. 5234 verticalDistanceThreshold: window.devicePixelRatio >= 2 ? 15 : 30, 5235 5236 getLocation: function ( event ) { 5237 var winPageX = window.pageXOffset, 5238 winPageY = window.pageYOffset, 5239 x = event.clientX, 5240 y = event.clientY; 5241 5242 if ( event.pageY === 0 && Math.floor( y ) > Math.floor( event.pageY ) || 5243 event.pageX === 0 && Math.floor( x ) > Math.floor( event.pageX ) ) { 5244 5245 // iOS4 clientX/clientY have the value that should have been 5246 // in pageX/pageY. While pageX/page/ have the value 0 5247 x = x - winPageX; 5248 y = y - winPageY; 5249 } else if ( y < ( event.pageY - winPageY) || x < ( event.pageX - winPageX ) ) { 5250 5251 // Some Android browsers have totally bogus values for clientX/Y 5252 // when scrolling/zooming a page. Detectable since clientX/clientY 5253 // should never be smaller than pageX/pageY minus page scroll 5254 x = event.pageX - winPageX; 5255 y = event.pageY - winPageY; 5256 } 5257 5258 return { 5259 x: x, 5260 y: y 5261 }; 5262 }, 5263 5264 start: function( event ) { 5265 var data = event.originalEvent.touches ? 5266 event.originalEvent.touches[ 0 ] : event, 5267 location = $.event.special.swipe.getLocation( data ); 5268 return { 5269 time: ( new Date() ).getTime(), 5270 coords: [ location.x, location.y ], 5271 origin: $( event.target ) 5272 }; 5273 }, 5274 5275 stop: function( event ) { 5276 var data = event.originalEvent.touches ? 5277 event.originalEvent.touches[ 0 ] : event, 5278 location = $.event.special.swipe.getLocation( data ); 5279 return { 5280 time: ( new Date() ).getTime(), 5281 coords: [ location.x, location.y ] 5282 }; 5283 }, 5284 5285 handleSwipe: function( start, stop, thisObject, origTarget ) { 5286 if ( stop.time - start.time < $.event.special.swipe.durationThreshold &&
5287 Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.horizontalDistanceThreshold && 5288 Math.abs( start.coords[ 1 ] - stop.coords[ 1 ] ) < $.event.special.swipe.verticalDistanceThreshold ) { 5289 var direction = start.coords[0] > stop.coords[ 0 ] ? "swipeleft" : "swiperight"; 5290 5291 triggerCustomEvent( thisObject, "swipe", $.Event( "swipe", { target: origTarget, swipestart: start, swipestop: stop }), true ); 5292 triggerCustomEvent( thisObject, direction,$.Event( direction, { target: origTarget, swipestart: start, swipestop: stop } ), true ); 5293 return true; 5294 } 5295 return false; 5296 5297 }, 5298 5299 // This serves as a flag to ensure that at most one swipe event event is 5300 // in work at any given time 5301 eventInProgress: false, 5302 5303 setup: function() { 5304 var events, 5305 thisObject = this, 5306 $this = $( thisObject ), 5307 context = {}; 5308 5309 // Retrieve the events data for this element and add the swipe context 5310 events = $.data( this, "mobile-events" ); 5311 if ( !events ) { 5312 events = { length: 0 }; 5313 $.data( this, "mobile-events", events ); 5314 } 5315 events.length++; 5316 events.swipe = context; 5317 5318 context.start = function( event ) { 5319 5320 // Bail if we're already working on a swipe event 5321 if ( $.event.special.swipe.eventInProgress ) { 5322 return; 5323 } 5324 $.event.special.swipe.eventInProgress = true; 5325 5326 var stop, 5327 start = $.event.special.swipe.start( event ), 5328 origTarget = event.target, 5329 emitted = false; 5330 5331 context.move = function( event ) { 5332 if ( !start || event.isDefaultPrevented() ) { 5333 return; 5334 } 5335 5336 stop = $.event.special.swipe.stop( event ); 5337 if ( !emitted ) { 5338 emitted = $.event.special.swipe.handleSwipe( start, stop, thisObject, origTarget ); 5339 if ( emitted ) { 5340 5341 // Reset the context to make way for the next swipe event 5342 $.event.special.swipe.eventInProgress = false; 5343 } 5344 } 5345 // prevent scrolling 5346 if ( Math.abs( start.coords[ 0 ] - stop.coords[ 0 ] ) > $.event.special.swipe.scrollSupressionThreshold ) { 5347 event.preventDefault(); 5348 } 5349 }; 5350 5351 context.stop = function() { 5352 emitted = true; 5353 5354 // Reset the context to make way for the next swipe event 5355 $.event.special.swipe.eventInProgress = false; 5356 $document.off( touchMoveEvent, context.move ); 5357 context.move = null; 5358 }; 5359 5360 $document.on( touchMoveEvent, context.move ) 5361 .one( touchStopEvent, context.stop ); 5362 }; 5363 $this.on( touchStartEvent, context.start ); 5364 }, 5365 5366 teardown: function() { 5367 var events, context; 5368 5369 events = $.data( this, "mobile-events" ); 5370 if ( events ) { 5371 context = events.swipe; 5372 delete events.swipe; 5373 events.length--; 5374 if ( events.length === 0 ) { 5375 $.removeData( this, "mobile-events" ); 5376 } 5377 } 5378 5379 if ( context ) { 5380 if ( context.start ) { 5381 $( this ).off( touchStartEvent, context.start ); 5382 } 5383 if ( context.move ) { 5384 $document.off( touchMoveEvent, context.move ); 5385 } 5386 if ( context.stop ) { 5387 $document.off( touchStopEvent, context.stop ); 5388 } 5389 } 5390 } 5391 }; 5392 $.each({ 5393 swipeleft: "swipe.left", 5394 swiperight: "swipe.right" 5395 }, function( event, sourceEvent ) { 5396 5397 $.event.special[ event ] = { 5398 setup: function() { 5399 $( this ).bind( sourceEvent, $.noop ); 5400 }, 5401 teardown: function() { 5402 $( this ).unbind( sourceEvent ); 5403 } 5404 }; 5405 }); 5406})( jQuery, this ); 5407*/ 5408'use strict'; 5409 5410!function ($) { 5411 5412 var Nest = { 5413 Feather: function (menu) { 5414 var type = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : 'zf'; 5415 5416 menu.attr('role', 'menubar'); 5417 5418 var items = menu.find('li').attr({ 'role': 'menuitem' }), 5419 subMenuClass = 'is-' + type + '-submenu', 5420 subItemClass = subMenuClass + '-item', 5421 hasSubClass = 'is-' + type + '-submenu-parent'; 5422 5423 items.each(function () { 5424 var $item = $(this), 5425 $sub = $item.children('ul'); 5426 5427 if ($sub.length) { 5428 $item.addClass(hasSubClass).attr({ 5429 'aria-haspopup': true, 5430 'aria-label': $item.children('a:first').text() 5431 }); 5432 // Note: Drilldowns behave differently in how they hide, and so need 5433 // additional attributes. We should look if this possibly over-generalized 5434 // utility (Nest) is appropriate when we rework menus in 6.4 5435 if (type === 'drilldown') { 5436 $item.attr({ 'aria-expanded': false }); 5437 } 5438 5439 $sub.addClass('submenu ' + subMenuClass).attr({ 5440 'data-submenu': '', 5441 'role': 'menu' 5442 }); 5443 if (type === 'drilldown') { 5444 $sub.attr({ 'aria-hidden': true }); 5445 } 5446 } 5447 5448 if ($item.parent('[data-submenu]').length) { 5449 $item.addClass('is-submenu-item ' + subItemClass); 5450 } 5451 }); 5452 5453 return; 5454 }, 5455 Burn: function (menu, type) { 5456 var //items = menu.find('li'), 5457 subMenuClass = 'is-' + type + '-submenu', 5458 subItemClass = subMenuClass + '-item', 5459 hasSubClass = 'is-' + type + '-submenu-parent'; 5460 5461 menu.find('>li, .menu, .menu > li').removeClass(subMenuClass + ' ' + subItemClass + ' ' + hasSubClass + ' is-submenu-item submenu is-active').removeAttr('data-submenu').css('display', ''); 5462 5463 // console.log( menu.find('.' + subMenuClass + ', .' + subItemClass + ', .has-submenu, .is-submenu-item, .submenu, [data-submenu]') 5464 // .removeClass(subMenuClass + ' ' + subItemClass + ' has-submenu is-submenu-item submenu') 5465 // .removeAttr('data-submenu')); 5466 // items.each(function(){ 5467 // var $item = $(this), 5468 // $sub = $item.children('ul'); 5469 // if($item.parent('[data-submenu]').length){ 5470 // $item.removeClass('is-submenu-item ' + subItemClass); 5471 // } 5472 // if($sub.length){ 5473 // $item.removeClass('has-submenu'); 5474 // $sub.removeClass('submenu ' + subMenuClass).removeAttr('data-submenu'); 5475 // } 5476 // }); 5477 } 5478 }; 5479 5480 Foundation.Nest = Nest; 5481}(jQuery); 5482'use strict'; 5483 5484var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 5485 5486function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 5487 5488!function ($) { 5489 5490 /** 5491 * ResponsiveToggle module. 5492 * @module foundation.responsiveToggle 5493 * @requires foundation.util.mediaQuery 5494 */ 5495 5496 var ResponsiveToggle = function () { 5497 /** 5498 * Creates a new instance of Tab Bar. 5499 * @class 5500 * @fires ResponsiveToggle#init 5501 * @param {jQuery} element - jQuery object to attach tab bar functionality to. 5502 * @param {Object} options - Overrides to the default plugin settings. 5503 */ 5504 function ResponsiveToggle(element, options) { 5505 _classCallCheck(this, ResponsiveToggle); 5506 5507 this.$element = $(element); 5508 this.options = $.extend({}, ResponsiveToggle.defaults, this.$element.data(), options); 5509 5510 this._init(); 5511 this._events(); 5512 5513 Foundation.registerPlugin(this, 'ResponsiveToggle'); 5514 } 5515 5516 /** 5517 * Initializes the tab bar by finding the target element, toggling element, and running update(). 5518 * @function 5519 * @private 5520 */ 5521 5522 5523 _createClass(ResponsiveToggle, [{ 5524 key: '_init', 5525 value: function _init() { 5526 var targetID = this.$element.data('responsive-toggle'); 5527 if (!targetID) { 5528 console.error('Your tab bar needs an ID of a Menu as the value of data-tab-bar.'); 5529 } 5530 5531 this.$targetMenu = $('#' + targetID); 5532 this.$toggler = this.$element.find('[data-toggle]').filter(function () { 5533 var target = $(this).data('toggle'); 5534 return target === targetID || target === ""; 5535 }); 5536 this.options = $.extend({}, this.options, this.$targetMenu.data()); 5537 5538 // If they were set, parse the animation classes 5539 if (this.options.animate) { 5540 var input = this.options.animate.split(' '); 5541 5542 this.animationIn = input[0]; 5543 this.animationOut = input[1] || null; 5544 } 5545 5546 this._update(); 5547 } 5548 5549 /** 5550 * Adds necessary event handlers for the tab bar to work. 5551 * @function 5552 * @private 5553 */ 5554 5555 }, {
5556 key: '_events', 5557 value: function _events() { 5558 var _this = this; 5559 5560 this._updateMqHandler = this._update.bind(this); 5561 5562 $(window).on('changed.zf.mediaquery', this._updateMqHandler); 5563 5564 this.$toggler.on('click.zf.responsiveToggle', this.toggleMenu.bind(this)); 5565 } 5566 5567 /** 5568 * Checks the current media query to determine if the tab bar should be visible or hidden. 5569 * @function 5570 * @private 5571 */ 5572 5573 }, { 5574 key: '_update', 5575 value: function _update() { 5576 // Mobile 5577 if (!Foundation.MediaQuery.atLeast(this.options.hideFor)) { 5578 this.$element.show(); 5579 this.$targetMenu.hide(); 5580 } 5581 5582 // Desktop 5583 else { 5584 this.$element.hide(); 5585 this.$targetMenu.show(); 5586 } 5587 } 5588 5589 /** 5590 * Toggles the element attached to the tab bar. The toggle only happens if the screen is small enough to allow it. 5591 * @function 5592 * @fires ResponsiveToggle#toggled 5593 */ 5594 5595 }, { 5596 key: 'toggleMenu', 5597 value: function toggleMenu() { 5598 var _this2 = this; 5599 5600 if (!Foundation.MediaQuery.atLeast(this.options.hideFor)) { 5601 /** 5602 * Fires when the element attached to the tab bar toggles. 5603 * @event ResponsiveToggle#toggled 5604 */ 5605 if (this.options.animate) { 5606 if (this.$targetMenu.is(':hidden')) { 5607 Foundation.Motion.animateIn(this.$targetMenu, this.animationIn, function () { 5608 _this2.$element.trigger('toggled.zf.responsiveToggle'); 5609 _this2.$targetMenu.find('[data-mutate]').triggerHandler('mutateme.zf.trigger'); 5610 }); 5611 } else { 5612 Foundation.Motion.animateOut(this.$targetMenu, this.animationOut, function () { 5613 _this2.$element.trigger('toggled.zf.responsiveToggle'); 5614 }); 5615 } 5616 } else { 5617 this.$targetMenu.toggle(0); 5618 this.$targetMenu.find('[data-mutate]').trigger('mutateme.zf.trigger'); 5619 this.$element.trigger('toggled.zf.responsiveToggle'); 5620 } 5621 } 5622 } 5623 }, { 5624 key: 'destroy', 5625 value: function destroy() { 5626 this.$element.off('.zf.responsiveToggle'); 5627 this.$toggler.off('.zf.responsiveToggle'); 5628 5629 $(window).off('changed.zf.mediaquery', this._updateMqHandler); 5630 5631 Foundation.unregisterPlugin(this); 5632 } 5633 }]); 5634 5635 return ResponsiveToggle; 5636 }(); 5637 5638 ResponsiveToggle.defaults = { 5639 /** 5640 * The breakpoint after which the menu is always shown, and the tab bar is hidden. 5641 * @option 5642 * @type {string} 5643 * @default 'medium' 5644 */ 5645 hideFor: 'medium', 5646 5647 /** 5648 * To decide if the toggle should be animated or not. 5649 * @option 5650 * @type {boolean} 5651 * @default false 5652 */ 5653 animate: false 5654 }; 5655 5656 // Window exports 5657 Foundation.plugin(ResponsiveToggle, 'ResponsiveToggle'); 5658}(jQuery); 5659'use strict'; 5660 5661var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 5662 5663function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 5664 5665!function ($) { 5666 5667 /** 5668 * Equalizer module. 5669 * @module foundation.equalizer 5670 * @requires foundation.util.mediaQuery 5671 * @requires foundation.util.timerAndImageLoader if equalizer contains images 5672 */ 5673 5674 var Equalizer = function () { 5675 /** 5676 * Creates a new instance of Equalizer. 5677 * @class 5678 * @fires Equalizer#init 5679 * @param {Object} element - jQuery object to add the trigger to. 5680 * @param {Object} options - Overrides to the default plugin settings. 5681 */ 5682 function Equalizer(element, options) { 5683 _classCallCheck(this, Equalizer); 5684 5685 this.$element = element; 5686 this.options = $.extend({}, Equalizer.defaults, this.$element.data(), options); 5687 5688 this._init(); 5689 5690 Foundation.registerPlugin(this, 'Equalizer'); 5691 } 5692 5693 /** 5694 * Initializes the Equalizer plugin and calls functions to get equalizer functioning on load. 5695 * @private 5696 */ 5697 5698 5699 _createClass(Equalizer, [{ 5700 key: '_init', 5701 value: function _init() { 5702 var eqId = this.$element.attr('data-equalizer') || ''; 5703 var $watched = this.$element.find('[data-equalizer-watch="' + eqId + '"]'); 5704 5705 this.$watched = $watched.length ? $watched : this.$element.find('[data-equalizer-watch]'); 5706 this.$element.attr('data-resize', eqId || Foundation.GetYoDigits(6, 'eq')); 5707 this.$element.attr('data-mutate', eqId || Foundation.GetYoDigits(6, 'eq')); 5708 5709 this.hasNested = this.$element.find('[data-equalizer]').length > 0; 5710 this.isNested = this.$element.parentsUntil(document.body, '[data-equalizer]').length > 0; 5711 this.isOn = false;
5712 this._bindHandler = { 5713 onResizeMeBound: this._onResizeMe.bind(this), 5714 onPostEqualizedBound: this._onPostEqualized.bind(this) 5715 }; 5716 5717 var imgs = this.$element.find('img'); 5718 var tooSmall; 5719 if (this.options.equalizeOn) { 5720 tooSmall = this._checkMQ(); 5721 $(window).on('changed.zf.mediaquery', this._checkMQ.bind(this)); 5722 } else { 5723 this._events(); 5724 } 5725 if (tooSmall !== undefined && tooSmall === false || tooSmall === undefined) { 5726 if (imgs.length) { 5727 Foundation.onImagesLoaded(imgs, this._reflow.bind(this)); 5728 } else { 5729 this._reflow(); 5730 } 5731 } 5732 } 5733 5734 /** 5735 * Removes event listeners if the breakpoint is too small. 5736 * @private 5737 */ 5738 5739 }, { 5740 key: '_pauseEvents', 5741 value: function _pauseEvents() { 5742 this.isOn = false; 5743 this.$element.off({ 5744 '.zf.equalizer': this._bindHandler.onPostEqualizedBound, 5745 'resizeme.zf.trigger': this._bindHandler.onResizeMeBound, 5746 'mutateme.zf.trigger': this._bindHandler.onResizeMeBound 5747 }); 5748 } 5749 5750 /** 5751 * function to handle $elements resizeme.zf.trigger, with bound this on _bindHandler.onResizeMeBound 5752 * @private 5753 */ 5754 5755 }, { 5756 key: '_onResizeMe', 5757 value: function _onResizeMe(e) { 5758 this._reflow(); 5759 } 5760 5761 /** 5762 * function to handle $elements postequalized.zf.equalizer, with bound this on _bindHandler.onPostEqualizedBound 5763 * @private 5764 */ 5765 5766 }, { 5767 key: '_onPostEqualized', 5768 value: function _onPostEqualized(e) { 5769 if (e.target !== this.$element[0]) { 5770 this._reflow(); 5771 } 5772 } 5773 5774 /** 5775 * Initializes events for Equalizer. 5776 * @private 5777 */ 5778 5779 }, { 5780 key: '_events', 5781 value: function _events() { 5782 var _this = this; 5783 this._pauseEvents(); 5784 if (this.hasNested) { 5785 this.$element.on('postequalized.zf.equalizer', this._bindHandler.onPostEqualizedBound); 5786 } else { 5787 this.$element.on('resizeme.zf.trigger', this._bindHandler.onResizeMeBound); 5788 this.$element.on('mutateme.zf.trigger', this._bindHandler.onResizeMeBound); 5789 } 5790 this.isOn = true; 5791 } 5792 5793 /** 5794 * Checks the current breakpoint to the minimum required size. 5795 * @private 5796 */ 5797 5798 }, { 5799 key: '_checkMQ', 5800 value: function _checkMQ() { 5801 var tooSmall = !Foundation.MediaQuery.is(this.options.equalizeOn); 5802 if (tooSmall) { 5803 if (this.isOn) { 5804 this._pauseEvents(); 5805 this.$watched.css('height', 'auto'); 5806 } 5807 } else { 5808 if (!this.isOn) { 5809 this._events(); 5810 } 5811 } 5812 return tooSmall; 5813 } 5814 5815 /** 5816 * A noop version for the plugin 5817 * @private 5818 */ 5819 5820 }, { 5821 key: '_killswitch', 5822 value: function _killswitch() { 5823 return; 5824 } 5825 5826 /** 5827 * Calls necessary functions to update Equalizer upon DOM change 5828 * @private 5829 */ 5830 5831 }, { 5832 key: '_reflow', 5833 value: function _reflow() { 5834 if (!this.options.equalizeOnStack) { 5835 if (this._isStacked()) { 5836 this.$watched.css('height', 'auto'); 5837 return false; 5838 } 5839 } 5840 if (this.options.equalizeByRow) { 5841 this.getHeightsByRow(this.applyHeightByRow.bind(this)); 5842 } else { 5843 this.getHeights(this.applyHeight.bind(this)); 5844 } 5845 } 5846 5847 /** 5848 * Manually determines if the first 2 elements are *NOT* stacked. 5849 * @private 5850 */ 5851 5852 }, { 5853 key: '_isStacked', 5854 value: function _isStacked() { 5855 if (!this.$watched[0] || !this.$watched[1]) { 5856 return true; 5857 } 5858 return this.$watched[0].getBoundingClientRect().top !== this.$watched[1].getBoundingClientRect().top; 5859 } 5860 5861 /** 5862 * Finds the outer heights of children contained within an Equalizer parent and returns them in an array 5863 * @param {Function} cb - A non-optional callback to return the heights array to. 5864 * @returns {Array} heights - An array of heights of children within Equalizer container 5865 */ 5866 5867 }, {
vendor: 4,117 bytes, lines 5868-5979
5868 key: 'getHeights', 5869 value: function getHeights(cb) { 5870 var heights = []; 5871 for (var i = 0, len = this.$watched.length; i < len; i++) { 5872 this.$watched[i].style.height = 'auto'; 5873 heights.push(this.$watched[i].offsetHeight); 5874 } 5875 cb(heights); 5876 } 5877 5878 /** 5879 * Finds the outer heights of children contained within an Equalizer parent and returns them in an array 5880 * @param {Function} cb - A non-optional callback to return the heights array to. 5881 * @returns {Array} groups - An array of heights of children within Equalizer container grouped by row with element,height and max as last child 5882 */ 5883 5884 }, { 5885 key: 'getHeightsByRow', 5886 value: function getHeightsByRow(cb) { 5887 var lastElTopOffset = this.$watched.length ? this.$watched.first().offset().top : 0, 5888 groups = [], 5889 group = 0; 5890 //group by Row 5891 groups[group] = []; 5892 for (var i = 0, len = this.$watched.length; i < len; i++) { 5893 this.$watched[i].style.height = 'auto'; 5894 //maybe could use this.$watched[i].offsetTop 5895 var elOffsetTop = $(this.$watched[i]).offset().top; 5896 if (elOffsetTop != lastElTopOffset) { 5897 group++; 5898 groups[group] = []; 5899 lastElTopOffset = elOffsetTop; 5900 } 5901 groups[group].push([this.$watched[i], this.$watched[i].offsetHeight]); 5902 } 5903 5904 for (var j = 0, ln = groups.length; j < ln; j++) { 5905 var heights = $(groups[j]).map(function () { 5906 return this[1]; 5907 }).get(); 5908 var max = Math.max.apply(null, heights); 5909 groups[j].push(max); 5910 } 5911 cb(groups); 5912 } 5913 5914 /** 5915 * Changes the CSS height property of each child in an Equalizer parent to match the tallest 5916 * @param {array} heights - An array of heights of children within Equalizer container 5917 * @fires Equalizer#preequalized 5918 * @fires Equalizer#postequalized 5919 */ 5920 5921 }, { 5922 key: 'applyHeight', 5923 value: function applyHeight(heights) { 5924 var max = Math.max.apply(null, heights); 5925 /** 5926 * Fires before the heights are applied 5927 * @event Equalizer#preequalized 5928 */ 5929 this.$element.trigger('preequalized.zf.equalizer'); 5930 5931 this.$watched.css('height', max); 5932 5933 /** 5934 * Fires when the heights have been applied 5935 * @event Equalizer#postequalized 5936 */ 5937 this.$element.trigger('postequalized.zf.equalizer'); 5938 } 5939 5940 /** 5941 * Changes the CSS height property of each child in an Equalizer parent to match the tallest by row 5942 * @param {array} groups - An array of heights of children within Equalizer container grouped by row with element,height and max as last child 5943 * @fires Equalizer#preequalized 5944 * @fires Equalizer#preequalizedrow 5945 * @fires Equalizer#postequalizedrow 5946 * @fires Equalizer#postequalized 5947 */ 5948 5949 }, { 5950 key: 'applyHeightByRow', 5951 value: function applyHeightByRow(groups) { 5952 /** 5953 * Fires before the heights are applied 5954 */ 5955 this.$element.trigger('preequalized.zf.equalizer'); 5956 for (var i = 0, len = groups.length; i < len; i++) { 5957 var groupsILength = groups[i].length, 5958 max = groups[i][groupsILength - 1]; 5959 if (groupsILength <= 2) { 5960 $(groups[i][0][0]).css({ 'height': 'auto' }); 5961 continue; 5962 } 5963 /** 5964 * Fires before the heights per row are applied 5965 * @event Equalizer#preequalizedrow 5966 */ 5967 this.$element.trigger('preequalizedrow.zf.equalizer'); 5968 for (var j = 0, lenJ = groupsILength - 1; j < lenJ; j++) { 5969 $(groups[i][j][0]).css({ 'height': max }); 5970 } 5971 /** 5972 * Fires when the heights per row have been applied 5973 * @event Equalizer#postequalizedrow 5974 */ 5975 this.$element.trigger('postequalizedrow.zf.equalizer'); 5976 } 5977 /** 5978 * Fires when the heights have been applied 5979 */
5980 this.$element.trigger('postequalized.zf.equalizer'); 5981 } 5982 5983 /** 5984 * Destroys an instance of Equalizer. 5985 * @function 5986 */ 5987 5988 }, { 5989 key: 'destroy', 5990 value: function destroy() { 5991 this._pauseEvents(); 5992 this.$watched.css('height', 'auto'); 5993 5994 Foundation.unregisterPlugin(this); 5995 } 5996 }]); 5997 5998 return Equalizer; 5999 }(); 6000 6001 /** 6002 * Default settings for plugin 6003 */ 6004 6005 6006 Equalizer.defaults = { 6007 /** 6008 * Enable height equalization when stacked on smaller screens. 6009 * @option 6010 * @type {boolean} 6011 * @default false 6012 */ 6013 equalizeOnStack: false, 6014 /** 6015 * Enable height equalization row by row. 6016 * @option 6017 * @type {boolean} 6018 * @default false 6019 */ 6020 equalizeByRow: false, 6021 /** 6022 * String representing the minimum breakpoint size the plugin should equalize heights on. 6023 * @option 6024 * @type {string} 6025 * @default '' 6026 */ 6027 equalizeOn: '' 6028 }; 6029 6030 // Window exports 6031 Foundation.plugin(Equalizer, 'Equalizer'); 6032}(jQuery); 6033'use strict'; 6034 6035var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); 6036 6037function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } 6038 6039!function ($) { 6040 6041 /** 6042 * Toggler module. 6043 * @module foundation.toggler 6044 * @requires foundation.util.motion 6045 * @requires foundation.util.triggers 6046 */ 6047 6048 var Toggler = function () { 6049 /** 6050 * Creates a new instance of Toggler. 6051 * @class 6052 * @fires Toggler#init 6053 * @param {Object} element - jQuery object to add the trigger to. 6054 * @param {Object} options - Overrides to the default plugin settings. 6055 */ 6056 function Toggler(element, options) { 6057 _classCallCheck(this, Toggler); 6058 6059 this.$element = element; 6060 this.options = $.extend({}, Toggler.defaults, element.data(), options); 6061 this.className = ''; 6062 6063 this._init(); 6064 this._events(); 6065 6066 Foundation.registerPlugin(this, 'Toggler'); 6067 } 6068 6069 /** 6070 * Initializes the Toggler plugin by parsing the toggle class from data-toggler, or animation classes from data-animate. 6071 * @function 6072 * @private 6073 */ 6074 6075 6076 _createClass(Toggler, [{ 6077 key: '_init', 6078 value: function _init() { 6079 var input; 6080 // Parse animation classes if they were set 6081 if (this.options.animate) { 6082 input = this.options.animate.split(' '); 6083 6084 this.animationIn = input[0]; 6085 this.animationOut = input[1] || null; 6086 } 6087 // Otherwise, parse toggle class 6088 else { 6089 input = this.$element.data('toggler'); 6090 // Allow for a . at the beginning of the string 6091 this.className = input[0] === '.' ? input.slice(1) : input; 6092 } 6093 6094 // Add ARIA attributes to triggers 6095 var id = this.$element[0].id; 6096 $('[data-open="' + id + '"], [data-close="' + id + '"], [data-toggle="' + id + '"]').attr('aria-controls', id); 6097 // If the target is hidden, add aria-hidden 6098 this.$element.attr('aria-expanded', this.$element.is(':hidden') ? false : true); 6099 } 6100 6101 /** 6102 * Initializes events for the toggle trigger. 6103 * @function 6104 * @private 6105 */ 6106 6107 }, { 6108 key: '_events', 6109 value: function _events() { 6110 this.$element.off('toggle.zf.trigger').on('toggle.zf.trigger', this.toggle.bind(this)); 6111 } 6112 6113 /** 6114 * Toggles the target class on the target element. An event is fired from the original trigger depending on if the resultant state was "on" or "off". 6115 * @function 6116 * @fires Toggler#on 6117 * @fires Toggler#off 6118 */ 6119 6120 }, {
6121 key: 'toggle', 6122 value: function toggle() { 6123 this[this.options.animate ? '_toggleAnimate' : '_toggleClass'](); 6124 } 6125 }, { 6126 key: '_toggleClass', 6127 value: function _toggleClass() { 6128 this.$element.toggleClass(this.className); 6129 6130 var isOn = this.$element.hasClass(this.className); 6131 if (isOn) { 6132 /** 6133 * Fires if the target element has the class after a toggle. 6134 * @event Toggler#on 6135 */ 6136 this.$element.trigger('on.zf.toggler'); 6137 } else { 6138 /** 6139 * Fires if the target element does not have the class after a toggle. 6140 * @event Toggler#off 6141 */ 6142 this.$element.trigger('off.zf.toggler'); 6143 } 6144 6145 this._updateARIA(isOn); 6146 this.$element.find('[data-mutate]').trigger('mutateme.zf.trigger'); 6147 } 6148 }, { 6149 key: '_toggleAnimate', 6150 value: function _toggleAnimate() { 6151 var _this = this; 6152 6153 if (this.$element.is(':hidden')) { 6154 Foundation.Motion.animateIn(this.$element, this.animationIn, function () { 6155 _this._updateARIA(true); 6156 this.trigger('on.zf.toggler'); 6157 this.find('[data-mutate]').trigger('mutateme.zf.trigger'); 6158 }); 6159 } else { 6160 Foundation.Motion.animateOut(this.$element, this.animationOut, function () { 6161 _this._updateARIA(false); 6162 this.trigger('off.zf.toggler'); 6163 this.find('[data-mutate]').trigger('mutateme.zf.trigger'); 6164 }); 6165 } 6166 } 6167 }, { 6168 key: '_updateARIA', 6169 value: function _updateARIA(isOn) { 6170 this.$element.attr('aria-expanded', isOn ? true : false); 6171 } 6172 6173 /** 6174 * Destroys the instance of Toggler on the element. 6175 * @function 6176 */ 6177 6178 }, { 6179 key: 'destroy', 6180 value: function destroy() { 6181 this.$element.off('.zf.toggler'); 6182 Foundation.unregisterPlugin(this); 6183 } 6184 }]); 6185 6186 return Toggler; 6187 }(); 6188 6189 Toggler.defaults = { 6190 /** 6191 * Tells the plugin if the element should animated when toggled. 6192 * @option 6193 * @type {boolean} 6194 * @default false 6195 */ 6196 animate: false 6197 }; 6198 6199 // Window exports 6200 Foundation.plugin(Toggler, 'Toggler'); 6201}(jQuery); 6202/* 6203 * Lazy Load - jQuery plugin for lazy loading images 6204 * 6205 * Copyright (c) 2007-2013 Mika Tuupola 6206 * 6207 * Licensed under the MIT license: 6208 * http://www.opensource.org/licenses/mit-license.php 6209 * 6210 * Project home: 6211 * http://www.appelsiini.net/projects/lazyload 6212 * 6213 * Version: 1.9.1 6214 * 6215 */ 6216 6217(function($, window, document, undefined) { 6218 var $window = $(window); 6219 6220 $.fn.lazyload = function(options) { 6221 var elements = this; 6222 var $container; 6223 var settings = { 6224 threshold : 0, 6225 failure_limit : 0, 6226 event : "scroll", 6227 effect : "show", 6228 container : window, 6229 data_attribute : "original", 6230 skip_invisible : true, 6231 appear : null, 6232 load : null, 6233 placeholder : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" 6234 }; 6235 6236 function update() { 6237 var counter = 0; 6238 6239 elements.each(function() { 6240 var $this = $(this); 6241 if (settings.skip_invisible && !$this.is(":visible")) { 6242 return; 6243 } 6244 if ($.abovethetop(this, settings) || 6245 $.leftofbegin(this, settings)) { 6246 /* Nothing. */ 6247 } else if (!$.belowthefold(this, settings) && 6248 !$.rightoffold(this, settings)) { 6249 $this.trigger("appear"); 6250 /* if we found an image we'll load, reset the counter */ 6251 counter = 0; 6252 } else { 6253 if (++counter > settings.failure_limit) { 6254 return false;
vendor: 4,377 bytes, lines 6255-6372
6255 } 6256 } 6257 }); 6258 6259 } 6260 6261 if(options) { 6262 /* Maintain BC for a couple of versions. */ 6263 if (undefined !== options.failurelimit) { 6264 options.failure_limit = options.failurelimit; 6265 delete options.failurelimit; 6266 } 6267 if (undefined !== options.effectspeed) { 6268 options.effect_speed = options.effectspeed; 6269 delete options.effectspeed; 6270 } 6271 6272 $.extend(settings, options); 6273 } 6274 6275 /* Cache container as jQuery as object. */ 6276 $container = (settings.container === undefined || 6277 settings.container === window) ? $window : $(settings.container); 6278 6279 /* Fire one scroll event per scroll. Not one scroll event per image. */ 6280 if (0 === settings.event.indexOf("scroll")) { 6281 $container.bind(settings.event, function() { 6282 return update(); 6283 }); 6284 } 6285 6286 this.each(function() { 6287 var self = this; 6288 var $self = $(self); 6289 6290 self.loaded = false; 6291 6292 /* If no src attribute given use data:uri. */ 6293 if ($self.attr("src") === undefined || $self.attr("src") === false) { 6294 if ($self.is("img")) { 6295 $self.attr("src", settings.placeholder); 6296 } 6297 } 6298 6299 /* When appear is triggered load original image. */ 6300 $self.one("appear", function() { 6301 if (!this.loaded) { 6302 if (settings.appear) { 6303 var elements_left = elements.length; 6304 settings.appear.call(self, elements_left, settings); 6305 } 6306 $("<img />") 6307 .bind("load", function() { 6308 6309 var original = $self.attr("data-" + settings.data_attribute); 6310 $self.hide(); 6311 if ($self.is("img")) { 6312 $self.attr("src", original); 6313 } else { 6314 $self.css("background-image", "url('" + original + "')"); 6315 } 6316 $self[settings.effect](settings.effect_speed); 6317 6318 self.loaded = true; 6319 6320 /* Remove image from array so it is not looped next time. */ 6321 var temp = $.grep(elements, function(element) { 6322 return !element.loaded; 6323 }); 6324 elements = $(temp); 6325 6326 if (settings.load) { 6327 var elements_left = elements.length; 6328 settings.load.call(self, elements_left, settings); 6329 } 6330 }) 6331 .attr("src", $self.attr("data-" + settings.data_attribute)); 6332 } 6333 }); 6334 6335 /* When wanted event is triggered load original image */ 6336 /* by triggering appear. */ 6337 if (0 !== settings.event.indexOf("scroll")) { 6338 $self.bind(settings.event, function() { 6339 if (!self.loaded) { 6340 $self.trigger("appear"); 6341 } 6342 }); 6343 } 6344 }); 6345 6346 /* Check if something appears when window is resized. */ 6347 $window.bind("resize", function() { 6348 update(); 6349 }); 6350 6351 /* With IOS5 force loading images when navigating with back button. */ 6352 /* Non optimal workaround. */ 6353 if ((/(?:iphone|ipod|ipad).*os 5/gi).test(navigator.appVersion)) { 6354 $window.bind("pageshow", function(event) { 6355 if (event.originalEvent && event.originalEvent.persisted) { 6356 elements.each(function() { 6357 $(this).trigger("appear"); 6358 }); 6359 } 6360 }); 6361 } 6362 6363 /* Force initial check if images should appear. */ 6364 $(document).ready(function() { 6365 update(); 6366 }); 6367 6368 return this; 6369 }; 6370 6371 /* Convenience methods in jQuery namespace. */ 6372 /* Use as $.belowthefold(element, {threshold : 100, container : window}
6372) */ 6373 6374 $.belowthefold = function(element, settings) { 6375 var fold; 6376 6377 if (settings.container === undefined || settings.container === window) { 6378 fold = (window.innerHeight ? window.innerHeight : $window.height()) + $window.scrollTop(); 6379 } else { 6380 fold = $(settings.container).offset().top + $(settings.container).height(); 6381 } 6382 6383 return fold <= $(element).offset().top - settings.threshold; 6384 }; 6385 6386 $.rightoffold = function(element, settings) { 6387 var fold; 6388 6389 if (settings.container === undefined || settings.container === window) { 6390 fold = $window.width() + $window.scrollLeft(); 6391 } else { 6392 fold = $(settings.container).offset().left + $(settings.container).width(); 6393 } 6394 6395 return fold <= $(element).offset().left - settings.threshold; 6396 }; 6397 6398 $.abovethetop = function(element, settings) { 6399 var fold; 6400 6401 if (settings.container === undefined || settings.container === window) { 6402 fold = $window.scrollTop(); 6403 } else { 6404 fold = $(settings.container).offset().top; 6405 } 6406 6407 return fold >= $(element).offset().top + settings.threshold + $(element).height(); 6408 }; 6409 6410 $.leftofbegin = function(element, settings) { 6411 var fold; 6412 6413 if (settings.container === undefined || settings.container === window) { 6414 fold = $window.scrollLeft(); 6415 } else { 6416 fold = $(settings.container).offset().left; 6417 } 6418 6419 return fold >= $(element).offset().left + settings.threshold + $(element).width(); 6420 }; 6421 6422 $.inviewport = function(element, settings) { 6423 return !$.rightoffold(element, settings) && !$.leftofbegin(element, settings) && 6424 !$.belowthefold(element, settings) && !$.abovethetop(element, settings); 6425 }; 6426 6427 /* Custom selectors for your convenience. */ 6428 /* Use as $("img:below-the-fold").something() or */ 6429 /* $("img").filter(":below-the-fold").something() which is faster */ 6430 6431 $.extend($.expr[":"], { 6432 "below-the-fold" : function(a) { return $.belowthefold(a, {threshold : 0}); }, 6433 "above-the-top" : function(a) { return !$.belowthefold(a, {threshold : 0}); }, 6434 "right-of-screen": function(a) { return $.rightoffold(a, {threshold : 0}); }, 6435 "left-of-screen" : function(a) { return !$.rightoffold(a, {threshold : 0}); }, 6436 "in-viewport" : function(a) { return $.inviewport(a, {threshold : 0}); }, 6437 /* Maintain BC for couple of versions. */ 6438 "above-the-fold" : function(a) { return !$.belowthefold(a, {threshold : 0}); }, 6439 "right-of-fold" : function(a) { return $.rightoffold(a, {threshold : 0}); }, 6440 "left-of-fold" : function(a) { return !$.rightoffold(a, {threshold : 0}); } 6441 }); 6442 6443})(jQuery, window, document); 6444 6445/*! jQuery UI - v1.8.21 - 2012-06-05 6446* https://github.com/jquery/jquery-ui 6447* Includes: jquery.ui.core.js 6448* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ 6449(function(a,b){function c(b,c){var e=b.nodeName.toLowerCase();if("area"===e){var f=b.parentNode,g=f.name,h;return!b.href||!g||f.nodeName.toLowerCase()!=="map"?!1:(h=a("img[usemap=#"+g+"]")[0],!!h&&d(h))}return(/input|select|textarea|button|object/.test(e)?!b.disabled:"a"==e?b.href||c:c)&&d(b)}function d(b){return!a(b).parents().andSelf().filter(function(){return a.curCSS(this,"visibility")==="hidden"||a.expr.filters.hidden(this)}).length}a.ui=a.ui||{};if(a.ui.version)return;a.extend(a.ui,{version:"1.8.21",keyCode:{ALT:18,BACKSPACE:8,CAPS_LOCK:20,COMMA:188,COMMAND:91,COMMAND_LEFT:91,COMMAND_RIGHT:93,CONTROL:17,DELETE:46,DOWN:40,END:35,ENTER:13,ESCAPE:27,HOME:36,INSERT:45,LEFT:37,MENU:93,NUMPAD_ADD:107,NUMPAD_DECIMAL:110,NUMPAD_DIVIDE:111,NUMPAD_ENTER:108,NUMPAD_MULTIPLY:106,NUMPAD_SUBTRACT:109,PAGE_DOWN:34,PAGE_UP:33,PERIOD:190,RIGHT:39,SHIFT:16,SPACE:32,TAB:9,UP:38,WINDOWS:91}}),a.fn.extend({propAttr:a.fn.prop||a.fn.attr,_focus:a.fn.focus,focus:function(b,c){return typeof b=="number"?this.each(function(){var d=this;setTimeout(function(){a(d).focus(),c&&c.call(d)},b)}):this._focus.apply(this,arguments)},scrollParent:function(){var b;return a.browser.msie&&/(static|relative)/.test(this.css("position"))||/absolute/.test(this.css("position"))?b=this.parents().filter(function(){return/(relative|absolute|fixed)/.test(a.curCSS(this,"position",1))&&/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0):b=this.parents().filter(function(){return/(auto|scroll)/.test(a.curCSS(this,"overflow",1)+a.curCSS(this,"overflow-y",1)+a.curCSS(this,"overflow-x",1))}).eq(0),/fixed/.test(this.css("position"))||!b.length?a(document):b},zIndex:function(c){if(c!==b)return this.css("zIndex",c);if(this.length){var d=a(this[0]),e,f;while(d.length&&d[0]!==document){e=d.css("position");if(e==="absolute"||e==="relative"||e==="fixed"){f=parseInt(d.css("zIndex"),10);if(!isNaN(f)&&f!==0)return f}d=d.parent()}}return 0},disableSelection:function(){return this.bind((a.support.selectstart?"selectstart":"mousedown")+".ui-disableSelection",function(a){a.preventDefault()})},enableSelection:function(){return this.unbind(".ui-disableSelection")}}),a.each(["Width","Height"],function(c,d){function h(b,c,d,f){return a.each(e,function(){c-=parseFloat(a.curCSS(b,"padding"+this,!0))||0,d&&(c-=parseFloat(a.curCSS(b,"border"+this+"Width",!0))||0),f&&(c-=parseFloat(a.curCSS(b,"margin"+this,!0))||0)}),c}var e=d==="Width"?["Left","Right"]:["Top","Bottom"],f=d.toLowerCase(),g={innerWidth:a.fn.innerWidth,innerHeight:a.fn.innerHeight,outerWidth:a.fn.outerWidth,outerHeight:a.fn.outerHeight};a.fn["inner"+d]=function(c){return c===b?g["inner"+d].call(this):this.each(function(){a(this).css(f,h(this,c)+"px")})},a.fn["outer"+d]=function(b,c){return typeof b!="number"?g["outer"+d].call(this,b):this.each(function(){a(this).css(f,h(this,b,!0,c)+"px")})}}),a.extend(a.expr[":"],{data:function(b,c,d){return!!a.data(b,d[3])},focusable:function(b){return c(b,!isNaN(a.attr(b,"tabindex")))},tabbable:function(b){var d=a.attr(b,"tabindex"),e=isNaN(d);return(e||d>=0)&&c(b,!e)}}),a(function(){var b=document.body,c=b.appendChild(c=document.createElement("div"));c.offsetHeight,a.extend(c.style,{minHeight:"100px",height:"auto",padding:0,borderWidth:0}),a.support.minHeight=c.offsetHeight===100,a.support.selectstart="onselectstart"in c,b.removeChild(c).style.display="none"}),a.extend(a.ui,{plugin:{add:function(b,c,d){var e=a.ui[b].prototype;for(var f in d)e.plugins[f]=e.plugins[f]||[],e.plugins[f].push([c,d[f]])},call:function(a,b,c){var d=a.plugins[b];if(!d||!a.element[0].parentNode)return;for(var e=0;e<d.length;e++)a.options[d[e][0]]&&d[e][1].apply(a.element,c)}},contains:function(a,b){return document.compareDocumentPosition?a.compareDocumentPosition(b)&16:a!==b&&a.contains(b)},hasScroll:function(b,c){if(a(b).css("overflow")==="hidden")return!1;var d=c&&c==="left"?"scrollLeft":"scrollTop",e=!1;return b[d]>
64490?!0:(b[d]=1,e=b[d]>0,b[d]=0,e)},isOverAxis:function(a,b,c){return a>b&&a<b+c},isOver:function(b,c,d,e,f,g){return a.ui.isOverAxis(b,d,f)&&a.ui.isOverAxis(c,e,g)}})})(jQuery);;/*! jQuery UI - v1.8.21 - 2012-06-05 6450* https://github.com/jquery/jquery-ui 6451* Includes: jquery.ui.widget.js 6452* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ 6453(function(a,b){if(a.cleanData){var c=a.cleanData;a.cleanData=function(b){for(var d=0,e;(e=b[d])!=null;d++)try{a(e).triggerHandler("remove")}catch(f){}c(b)}}else{var d=a.fn.remove;a.fn.remove=function(b,c){return this.each(function(){return c||(!b||a.filter(b,[this]).length)&&a("*",this).add([this]).each(function(){try{a(this).triggerHandler("remove")}catch(b){}}),d.call(a(this),b,c)})}}a.widget=function(b,c,d){var e=b.split(".")[0],f;b=b.split(".")[1],f=e+"-"+b,d||(d=c,c=a.Widget),a.expr[":"][f]=function(c){return!!a.data(c,b)},a[e]=a[e]||{},a[e][b]=function(a,b){arguments.length&&this._createWidget(a,b)};var g=new c;g.options=a.extend(!0,{},g.options),a[e][b].prototype=a.extend(!0,g,{namespace:e,widgetName:b,widgetEventPrefix:a[e][b].prototype.widgetEventPrefix||b,widgetBaseClass:f},d),a.widget.bridge(b,a[e][b])},a.widget.bridge=function(c,d){a.fn[c]=function(e){var f=typeof e=="string",g=Array.prototype.slice.call(arguments,1),h=this;return e=!f&&g.length?a.extend.apply(null,[!0,e].concat(g)):e,f&&e.charAt(0)==="_"?h:(f?this.each(function(){var d=a.data(this,c),f=d&&a.isFunction(d[e])?d[e].apply(d,g):d;if(f!==d&&f!==b)return h=f,!1}):this.each(function(){var b=a.data(this,c);b?b.option(e||{})._init():a.data(this,c,new d(e,this))}),h)}},a.Widget=function(a,b){arguments.length&&this._createWidget(a,b)},a.Widget.prototype={widgetName:"widget",widgetEventPrefix:"",options:{disabled:!1},_createWidget:function(b,c){a.data(c,this.widgetName,this),this.element=a(c),this.options=a.extend(!0,{},this.options,this._getCreateOptions(),b);var d=this;this.element.bind("remove."+this.widgetName,function(){d.destroy()}),this._create(),this._trigger("create"),this._init()},_getCreateOptions:function(){return a.metadata&&a.metadata.get(this.element[0])[this.widgetName]},_create:function(){},_init:function(){},destroy:function(){this.element.unbind("."+this.widgetName).removeData(this.widgetName),this.widget().unbind("."+this.widgetName).removeAttr("aria-disabled").removeClass(this.widgetBaseClass+"-disabled "+"ui-state-disabled")},widget:function(){return this.element},option:function(c,d){var e=c;if(arguments.length===0)return a.extend({},this.options);if(typeof c=="string"){if(d===b)return this.options[c];e={},e[c]=d}return this._setOptions(e),this},_setOptions:function(b){var c=this;return a.each(b,function(a,b){c._setOption(a,b)}),this},_setOption:function(a,b){return this.options[a]=b,a==="disabled"&&this.widget()[b?"addClass":"removeClass"](this.widgetBaseClass+"-disabled"+" "+"ui-state-disabled").attr("aria-disabled",b),this},enable:function(){return this._setOption("disabled",!1)},disable:function(){return this._setOption("disabled",!0)},_trigger:function(b,c,d){var e,f,g=this.options[b];d=d||{},c=a.Event(c),c.type=(b===this.widgetEventPrefix?b:this.widgetEventPrefix+b).toLowerCase(),c.target=this.element[0],f=c.originalEvent;if(f)for(e in f)e in c||(c[e]=f[e]);return this.element.trigger(c,d),!(a.isFunction(g)&&g.call(this.element[0],c,d)===!1||c.isDefaultPrevented())}}})(jQuery);;/*! jQuery UI - v1.8.21 - 2012-06-05 6454* https://github.com/jquery/jquery-ui 6455* Includes: jquery.ui.mouse.js 6456* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ 6457(function(a,b){var c=!1;a(document).mouseup(function(a){c=!1}),a.widget("ui.mouse",{options:{cancel:":input,option",distance:1,delay:0},_mouseInit:function(){var b=this;this.element.bind("mousedown."+this.widgetName,function(a){return b._mouseDown(a)}).bind("click."+this.widgetName,function(c){if(!0===a.data(c.target,b.widgetName+".preventClickEvent"))return a.removeData(c.target,b.widgetName+".preventClickEvent"),c.stopImmediatePropagation(),!1}),this.started=!1},_mouseDestroy:function(){this.element.unbind("."+this.widgetName),a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate)},_mouseDown:function(b){if(c)return;this._mouseStarted&&this._mouseUp(b),this._mouseDownEvent=b;var d=this,e=b.which==1,f=typeof this.options.cancel=="string"&&b.target.nodeName?a(b.target).closest(this.options.cancel).length:!1;if(!e||f||!this._mouseCapture(b))return!0;this.mouseDelayMet=!this.options.delay,this.mouseDelayMet||(this._mouseDelayTimer=setTimeout(function(){d.mouseDelayMet=!0},this.options.delay));if(this._mouseDistanceMet(b)&&this._mouseDelayMet(b)){this._mouseStarted=this._mouseStart(b)!==!1;if(!this._mouseStarted)return b.preventDefault(),!0}return!0===a.data(b.target,this.widgetName+".preventClickEvent")&&a.removeData(b.target,this.widgetName+".preventClickEvent"),this._mouseMoveDelegate=function(a){return d._mouseMove(a)},this._mouseUpDelegate=function(a){return d._mouseUp(a)},a(document).bind("mousemove."+this.widgetName,this._mouseMoveDelegate).bind("mouseup."+this.widgetName,this._mouseUpDelegate),b.preventDefault(),c=!0,!0},_mouseMove:function(b){return!a.browser.msie||document.documentMode>=9||!!b.button?this._mouseStarted?(this._mouseDrag(b),b.preventDefault()):(this._mouseDistanceMet(b)&&this._mouseDelayMet(b)&&(this._mouseStarted=this._mouseStart(this._mouseDownEvent,b)!==!1,this._mouseStarted?this._mouseDrag(b):this._mouseUp(b)),!this._mouseStarted):this._mouseUp(b)},_mouseUp:function(b){return a(document).unbind("mousemove."+this.widgetName,this._mouseMoveDelegate).unbind("mouseup."+this.widgetName,this._mouseUpDelegate),this._mouseStarted&&(this._mouseStarted=!1,b.target==this._mouseDownEvent.target&&a.data(b.target,this.widgetName+".preventClickEvent",!0),this._mouseStop(b)),!1},_mouseDistanceMet:function(a){return Math.max(Math.abs(this._mouseDownEvent.pageX-a.pageX),Math.abs(this._mouseDownEvent.pageY-a.pageY))>=this.options.distance},_mouseDelayMet:function(a){return this.mouseDelayMet},_mouseStart:function(a){},_mouseDrag:function(a){},_mouseStop:function(a){},_mouseCapture:function(a){return!0}})})(jQuery);;/*! jQuery UI - v1.8.21 - 2012-06-05 6458* https://github.com/jquery/jquery-ui 6459* Includes: jquery.ui.position.js 6460* Copyright (c) 2012 AUTHORS.txt; Licensed MIT, GPL */ 6461(function(a,b){a.ui=a.ui||{};
6461var c=/left|center|right/,d=/top|center|bottom/,e="center",f={},g=a.fn.position,h=a.fn.offset;a.fn.position=function(b){if(!b||!b.of)return g.apply(this,arguments);b=a.extend({},b);var h=a(b.of),i=h[0],j=(b.collision||"flip").split(" "),k=b.offset?b.offset.split(" "):[0,0],l,m,n;return i.nodeType===9?(l=h.width(),m=h.height(),n={top:0,left:0}):i.setTimeout?(l=h.width(),m=h.height(),n={top:h.scrollTop(),left:h.scrollLeft()}):i.preventDefault?(b.at="left top",l=m=0,n={top:b.of.pageY,left:b.of.pageX}):(l=h.outerWidth(),m=h.outerHeight(),n=h.offset()),a.each(["my","at"],function(){var a=(b[this]||"").split(" ");a.length===1&&(a=c.test(a[0])?a.concat([e]):d.test(a[0])?[e].concat(a):[e,e]),a[0]=c.test(a[0])?a[0]:e,a[1]=d.test(a[1])?a[1]:e,b[this]=a}),j.length===1&&(j[1]=j[0]),k[0]=parseInt(k[0],10)||0,k.length===1&&(k[1]=k[0]),k[1]=parseInt(k[1],10)||0,b.at[0]==="right"?n.left+=l:b.at[0]===e&&(n.left+=l/2),b.at[1]==="bottom"?n.top+=m:b.at[1]===e&&(n.top+=m/2),n.left+=k[0],n.top+=k[1],this.each(function(){var c=a(this),d=c.outerWidth(),g=c.outerHeight(),h=parseInt(a.curCSS(this,"marginLeft",!0))||0,i=parseInt(a.curCSS(this,"marginTop",!0))||0,o=d+h+(parseInt(a.curCSS(this,"marginRight",!0))||0),p=g+i+(parseInt(a.curCSS(this,"marginBottom",!0))||0),q=a.extend({},n),r;b.my[0]==="right"?q.left-=d:b.my[0]===e&&(q.left-=d/2),b.my[1]==="bottom"?q.top-=g:b.my[1]===e&&(q.top-=g/2),f.fractions||(q.left=Math.round(q.left),q.top=Math.round(q.top)),r={left:q.left-h,top:q.top-i},a.each(["left","top"],function(c,e){a.ui.position[j[c]]&&a.ui.position[j[c]][e](q,{targetWidth:l,targetHeight:m,elemWidth:d,elemHeight:g,collisionPosition:r,collisionWidth:o,collisionHeight:p,offset:k,my:b.my,at:b.at})}),a.fn.bgiframe&&c.bgiframe(),c.offset(a.extend(q,{using:b.using}))})},a.ui.position={fit:{left:function(b,c){var d=a(window),e=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft();b.left=e>0?b.left-e:Math.max(b.left-c.collisionPosition.left,b.left)},top:function(b,c){var d=a(window),e=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop();b.top=e>0?b.top-e:Math.max(b.top-c.collisionPosition.top,b.top)}},flip:{left:function(b,c){if(c.at[0]===e)return;var d=a(window),f=c.collisionPosition.left+c.collisionWidth-d.width()-d.scrollLeft(),g=c.my[0]==="left"?-c.elemWidth:c.my[0]==="right"?c.elemWidth:0,h=c.at[0]==="left"?c.targetWidth:-c.targetWidth,i=-2*c.offset[0];b.left+=c.collisionPosition.left<0?g+h+i:f>0?g+h+i:0},top:function(b,c){if(c.at[1]===e)return;var d=a(window),f=c.collisionPosition.top+c.collisionHeight-d.height()-d.scrollTop(),g=c.my[1]==="top"?-c.elemHeight:c.my[1]==="bottom"?c.elemHeight:0,h=c.at[1]==="top"?c.targetHeight:-c.targetHeight,i=-2*c.offset[1];b.top+=c.collisionPosition.top<0?g+h+i:f>0?g+h+i:0}}},a.offset.setOffset||(a.offset.setOffset=function(b,c){/static/.test(a.curCSS(b,"position"))&&(b.style.position="relative");var d=a(b),e=d.offset(),f=parseInt(a.curCSS(b,"top",!0),10)||0,g=parseInt(a.curCSS(b,"left",!0),10)||0,h={top:c.top-e.top+f,left:c.left-e.left+g};"using"in c?c.using.call(b,h):d.css(h)},a.fn.offset=function(b){var c=this[0];return!c||!c.ownerDocument?null:b?a.isFunction(b)?this.each(function(c){a(this).offset(b.call(this,c,a(this).offset()))}):this.each(function(){a.offset.setOffset(this,b)}):h.call(this)}),function(){var b=document.getElementsByTagName("body")[0],c=document.createElement("div"),d,e,g,h,i;d=document.createElement(b?"div":"body"),g={visibility:"hidden",width:0,height:0,border:0,margin:0,background:"none"},b&&a.extend(g,{position:"absolute",left:"-1000px",top:"-1000px"});for(var j in g)d.style[j]=g[j];d.appendChild(c),e=b||document.documentElement,e.insertBefore(d,e.firstChild),c.style.cssText="position: absolute; left: 10.7432222px; top: 10.432325px; height: 30px; width: 201px;",h=a(c).offset(function(a,b){return b}).offset(),d.innerHTML="",e.removeChild(d),i=h.top+h.left+(b?2e3:0),f.fractions=i>21&&i<22}()})(jQuery);; 6462 6463var BW = BW || {}; 6464 6465/* 6466 Handels image changes and modal open in gallery DCE 6467 */ 6468BW.DceGallery = (function(){ 6469 6470 'use strict'; 6471 6472 var defaultConf = { 6473 galleryWrapperClass: 'bw-dce-gallery', 6474 switchTriggerSelector: '.bw-dce-gallery__switch', 6475 contentReplacements: [ 6476 { 6477 galleryElementSelector: '.gallery__image', 6478 galleryElementHTML: true,
6479 galleryElementCSS: false, 6480 galleryElementAttr: false, 6481 triggerElementSelectorr: '.gallery__preview', 6482 triggerElementAttribute: 'data-image', 6483 } 6484 ] 6485 }; 6486 6487 // placeholder for cached DOM elements 6488 var CONF = {}; 6489 var DOM = {}; 6490 6491 function cacheDOM(){ 6492 DOM.$galleries = $(CONF.galleryWrapperClass); 6493 $(DOM.$galleries).each(function(i, gallery){ 6494 DOM.$galleries[i].$switchTrigger = $(gallery).find(CONF.switchTrigger); 6495 DOM.$galleries[i].replacements = []; 6496 CONF.contentReplacements.forEach(function(e){ 6497 DOM.$galleries[i].replacements 6498 }); 6499 }); 6500 } 6501 6502 function initEvents(){ 6503 6504 } 6505 6506 /** 6507 * inits the BW.Paginate module 6508 * 6509 * @param {object} conf optional configuration override 6510 * @return {void} 6511 */ 6512 function init(conf){ 6513 6514 // @TODO: populate conf 6515 CONF = conf ? conf : defaultConf; 6516 6517 cacheDOM(); 6518 initEvents(); 6519 } 6520 6521 return { 6522 init: init 6523 } 6524 6525}()); 6526 6527var BW = BW || {}; 6528 6529/* 6530 Loads and displays dynamic content in Foundation Reveal Modal 6531 Requires: 6532 - Foundation Reveal (https://foundation.zurb.com/sites/docs/reveal.html) 6533 */ 6534BW.Modal = (function(){ 6535 6536 'use strict'; 6537 6538 // e.g. <a href="http://example.com/data.json" class="bw-modal" data-bw-modal-json="{data: }" 6539 var defaultConf = { 6540 dataType: 'text', 6541 triggerSelector: '.bw-modal', 6542 modalSelector: '#bwModal', 6543 modalContentWrapperSelector: '#bwModalContent', 6544 6545 urlAttr: 'href', 6546 saveAttr: 'data-bw-modal-json', 6547 }; 6548 6549 // placeholder for cached DOM elements 6550 var CONF = {}; 6551 var DOM = {}; 6552 6553 /** 6554 * Creates a new Foundation Reveal at the end of body 6555 * 6556 * @return {void} 6557 */ 6558 function createModal(){ 6559 DOM.$modal = $('<div>', { 6560 id: CONF.modalSelector, 6561 class: 'reveal reveal--bw-modal', 6562 dataReveal: '' 6563 }).append('<div>', { 6564 id: CONF.modalContentWrapperSelector 6565 }).appendTo('body'); 6566 } 6567 6568 /** 6569 * Save DOM elements to variables 6570 * 6571 * @return {void} 6572 */ 6573 function cacheDOM(){ 6574 DOM.$modal = $(CONF.modalSelector); 6575 if(!DOM.$modal) createModal(); 6576 DOM.$modalContent = DOM.$modal.find(CONF.modalContentWrapperSelector); 6577 DOM.$trigger = $(CONF.triggerSelector); 6578 } 6579 6580 /** 6581 * Add click event to all trigger elements 6582 * 6583 * @return {void} 6584 */ 6585 function initListener(){ 6586 DOM.$trigger.each(function(i, el){ 6587 $(el).on('click', function(event){ 6588 event.preventDefault(); 6589 onTriggerClick(el); 6590 }); 6591 }); 6592 } 6593 6594 /** 6595 * Click event function 6596 * 6597 * @param {JQuery} el element that holds data url and saved attr 6598 * @return {void} 6599 */ 6600 function onTriggerClick(el){ 6601 var savedData = $(el).attr(CONF.saveAttr); 6602 if(savedData){ 6603 openModal(savedData); 6604 } else { 6605 loadAndSaveElementData(el, openModal); 6606 } 6607 if($(el).attr('id')) { 6608 location.hash = $(el).attr('id'); 6609 } 6610 } 6611 6612 /** 6613 * Ajax load of element data + cache in data saveAttr 6614 * 6615 * @param {JQuery} el element that holds data url 6616 * @param {Function} cb callback function that gets executed after success 6617 * @return {void} 6618 */ 6619 function loadAndSaveElementData(el, cb){ 6620 $.ajax({ 6621 dataType: CONF.dataType, 6622 url: $(el).attr(CONF.urlAttr), 6623 success: function(data){ 6624 $(el).attr(CONF.saveAttr, data); 6625 cb(data); 6626 } 6627 }); 6628 } 6629 6630 /** 6631 * inserts html into modal and opens it 6632 * 6633 * @param {string} html content to show 6634 * @return {void} 6635 */ 6636 function openModal(html){ 6637 $(CONF.modalContentWrapperSelector).html(html); 6638 $(CONF.modalSelector).foundation('open'); 6639 } 6640 6641 /** 6642 * inits the BW.Modal module 6643 * 6644 * @param {object} conf optional configuration override 6645 * @return {void} 6646 */ 6647 function init(conf){ 6648 6649 // @TODO: populate conf 6650 CONF = conf ? conf : defaultConf; 6651 6652 cacheDOM(); 6653 initListener(); 6654 } 6655 6656 return { 6657 init: init 6658 } 6659 6660}()); 6661 6662var BW = BW || {}; 6663 6664/* 6665 Creates dynamic paginate navigation 6666 */ 6667BW.Paginate = (function(CONF){ 6668 6669 'use strict'; 6670 6671 var defaultConf = { 6672 itemsPerPage: 30, 6673 paginationSelector: '.bw-pagination', 6674 itemWrapperSelector: '.bw-pagination__items', 6675 itemSelectorClass: 'bw-pagination__items__item', 6676 itemHiddenClass: 'bw-pagination__items__item--hidden', 6677 itemIgnoreSelector: '', 6678 buttonClass: 'button', 6679 buttonPrevText: 'previous', 6680 buttonNextText: 'next', 6681 buttonActiveClass: 'active', 6682 buttonDisabledClass: 'disabled', 6683 scrollTopSelector: false 6684 }; 6685 6686 // placeholder for cached DOM elements 6687 var DOM = {}; 6688 // @TODO populate configuration 6689 var CONF = CONF ? CONF : defaultConf; 6690 6691 /** 6692 * Save DOM elements to variables 6693 * 6694 * @return {void} 6695 */ 6696 function cacheDOM(){ 6697 DOM.$pagers = $(CONF.paginationSelector); 6698 DOM.$itemWrappers = $(CONF.itemWrapperSelector); 6699 } 6700 6701 /** 6702 * Function called by click on pager button elements 6703 * 6704 * @param {integer} offset index of the clicked button element (0 - pagescount+2) 6705 * @param {JQuery} pager pager elment 6706 * @return {void} 6707 */ 6708 function onButtonClick(offset, pager){ 6709 6710 // abbort if first or last page and prev/1 or next/n is clicked 6711 if((offset <= 1 && pager.currentOffset==1) || (offset >= pager.pageCount && pager.currentOffset==pager.pageCount)) return false;
6712 6713 // navigate 6714 pager.navigate(offset); 6715 6716 // scroll to top 6717 if(CONF.scrollTopSelector) $('html,body').animate({scrollTop: $(CONF.scrollTopSelector).offset().top}); 6718 } 6719 6720 /** 6721 * returns the button text for pager buttons (useful for language overrides) 6722 * 6723 * @param {integer} i index of the button element 6724 * @param {integer} count count of button elements 6725 * @return {string} 6726 */ 6727 function getButtonText(i, count){ 6728 if(i == 0) return CONF.buttonPrevText; 6729 if(i == (count+1)) return CONF.buttonNextText; 6730 return i; 6731 } 6732 6733 /** 6734 * Add functionts to given pager 6735 * 6736 * @param {integer} i offset of the pager in DOM.$pagers 6737 * @return {void} 6738 */ 6739 function extendPagerFunctions(i){ 6740 6741 // clear pager content 6742 $(DOM.$pagers[i]).html(); 6743 6744 // cache elements 6745 DOM.$pagers[i].$itemWrapper = DOM.$itemWrappers[i]; 6746 DOM.$pagers[i].$buttonGroup = $('<ul>', {class:'pagination button-group'}).appendTo(DOM.$pagers[i]); 6747 6748 // clear all navigation buttons inside 6749 DOM.$pagers[i].removeButtons = function(){ 6750 $(this.$buttonGroup).html(''); 6751 } 6752 6753 DOM.$pagers[i].currentOffset = 1; 6754 6755 DOM.$pagers[i].createButtons = function() { 6756 6757 // Wir speichern den 'this'-Kontext (das Pager-Objekt) sofort in einer Variable. 6758 // Das löst alle Kontext-Probleme. 6759 var pager = this; 6760 6761 $(pager.$buttonGroup).empty(); 6762 6763 for (var j = 0; j < pager.pageCount + 2; j++) { 6764 6765 var listItem = $('<li>', { 6766 class: CONF.buttonClass 6767 }); 6768 6769 var linkElement = $('<a />', { 6770 class: 'page-link', 6771 href: '#', 6772 'aria-label': 'gehe zu Seite ' + getButtonText(j, pager.pageCount), 6773 text: getButtonText(j, pager.pageCount), 6774 'data-page': j, 6775 6776 click: function(event) { 6777 event.preventDefault(); 6778 var pageIndex = $(this).data('page'); 6779 6780 // Ruft die Kernfunktion mit den korrekten Argumenten auf. 6781 // 'pager' ist hier die Variable, die wir am Anfang der Funktion gespeichert haben. 6782 onButtonClick(pageIndex, pager, event); 6783 } 6784 }); 6785 6786 listItem.append(linkElement); 6787 $(pager.$buttonGroup).append(listItem); 6788 } 6789 }; 6790 6791 // sets active and disabled classes for pager buttons 6792 DOM.$pagers[i].setButtonClasses = function(offset){ 6793 // remove active & disabled classes 6794 $('li', this.$buttonGroup).removeClass(CONF.buttonActiveClass).removeClass(CONF.buttonDisabledClass); 6795 6796 // add active class 6797 $('li:nth-child('+(offset+1)+')', this.$buttonGroup).addClass(CONF.buttonActiveClass); 6798 6799 // add disabled class 6800 if(offset==1) $('li:first-child', this.$buttonGroup).addClass(CONF.buttonDisabledClass); 6801 if(offset==this.pageCount) $('li:last-child', this.$buttonGroup).addClass(CONF.buttonDisabledClass); 6802 } 6803 6804 // starts the filtering of pager items 6805 DOM.$pagers[i].navigate = function(offset){ 6806 6807 // set offset (from clicked prev/next buttons) 6808 if(offset==0) offset = this.currentOffset==1 ? 1 : this.currentOffset-1; 6809 if(offset==this.pageCount+1) offset = this.currentOffset==this.pageCount ? this.pageCount : this.currentOffset+1; 6810 6811 this.setButtonClasses(offset); 6812 6813 // hide items from other pages 6814 $(this.$items).addClass(CONF.itemHiddenClass); 6815 for(var j=CONF.itemsPerPage*(offset-1); j<(CONF.itemsPerPage*offset); j++){ 6816 $(this.$items[j]).removeClass(CONF.itemHiddenClass); 6817 } 6818 6819 this.currentOffset = offset; 6820 } 6821 6822 /** 6823 * setup pager buttons 6824 * 6825 * @param {integer} i offset of the pager in DOM.$pagers 6826 * @return {void} 6827 */ 6828 DOM.$pagers[i].refresh = function(){ 6829 this.$items = $('.'+CONF.itemSelectorClass, this.$itemWrapper).not(CONF.itemIgnoreSelector); 6830 this.pageCount = Math.ceil(this.$items.length / CONF.itemsPerPage); 6831 this.removeButtons(); 6832 6833 // cancel if only one page 6834 if(this.pageCount < 2) return false; 6835 6836 this.createButtons(); 6837 } 6838 6839 } 6840 6841 /** 6842 * triggers refresh of a single pager 6843 * 6844 * @param {integer} index global offset of pages in DOM.$pagers 6845 * @return {void} 6846 */ 6847 function refreshPager(index){ 6848 if (!DOM.$pagers || !DOM.$pagers[index]) return; 6849 DOM.$pagers[index].refresh(); 6850 DOM.$pagers[index].navigate(1); 6851 } 6852 6853 /** 6854 * [initAllPagers description] 6855 * 6856 * @return {void} 6857 */ 6858 function initAllPagers(){ 6859 DOM.$pagers.each(function(i,e){ 6860 // add methods to every pager
6861 extendPagerFunctions(i); 6862 6863 // refresh every pager and navigate to page 1 6864 DOM.$pagers[i].refresh(); 6865 DOM.$pagers[i].navigate(1); 6866 }); 6867 } 6868 6869 /** 6870 * inits the BW.Paginate module 6871 * 6872 * @param {object} conf optional configuration override 6873 * @return {void} 6874 */ 6875 function init(){ 6876 6877 cacheDOM(); 6878 initAllPagers(); 6879 } 6880 6881 return { 6882 CONF: CONF, 6883 init: init, 6884 refreshPager: refreshPager 6885 } 6886 6887}); 6888 6889var BW = BW || {}; 6890 6891/* 6892 Creates dynamic paginate navigation 6893 */ 6894BW.Filter = (function(CONF){ 6895 6896 'use strict'; 6897 6898 var defaultConf = { 6899 searchContentSelector: '.bw-filter__item', 6900 filtersWrapperSelector: '.bw-filter', 6901 itemWrapperSelector: '.bw-pagination__items', 6902 itemSelectorClass: 'bw-pagination__items__item', 6903 textFilterSelector: '.bw-filter__text', 6904 selectFilterSelector: '.bw-filter__select', 6905 textFilterHiddenClass: 'bw-filter__item--hiddenByText', 6906 selectFilterHiddenClass: 'bw-filter__item--hiddenBySelect', 6907 callback: null, 6908 BwPaginateArray: [] 6909 }; 6910 6911 // placeholder for cached DOM elements 6912 var DOM = {}; 6913 // @TODO: populate conf 6914 var CONF = CONF ? CONF : defaultConf; 6915 6916 function cacheDOM(){ 6917 DOM.$filters = $(CONF.filtersWrapperSelector); 6918 DOM.$filters.each(function(i, e){ 6919 DOM.$filters[i].$textFilter = $(this).find(CONF.textFilterSelector); 6920 DOM.$filters[i].$selectFilter = $(this).find(CONF.selectFilterSelector); 6921 }); 6922 DOM.$itemWrappers = $(CONF.itemWrapperSelector); 6923 DOM.$itemWrappers.each(function(i, e){ 6924 DOM.$itemWrappers[i].$items = $(this).find('.'+CONF.itemSelectorClass); 6925 }); 6926 } 6927 6928 function refreshPagers(offset){ 6929 for (var i = 0; i < CONF.BwPaginateArray.length; i++){ 6930 CONF.BwPaginateArray[i].refreshPager(offset); 6931 } 6932 } 6933 6934 function hasPager(){ 6935 return CONF.BwPaginateArray && CONF.BwPaginateArray.length; 6936 } 6937 6938 function getHiddenClassesFromPagers(){ 6939 var classNames = ''; 6940 for (var i = 0; i < CONF.BwPaginateArray.length; i++) { 6941 classNames += CONF.BwPaginateArray[i].itemHiddenClass + ' '; 6942 } 6943 return classNames; 6944 } 6945 6946 function onTextFilterKeyUp(offset){ 6947 textFilter(offset); 6948 if (CONF.BwPaginateArray.length) refreshPagers(offset); 6949 if(CONF.callback) CONF.callback(); 6950 } 6951 6952 function onSelectFilterChange(offset){ 6953 selectFilter(offset); 6954 if (hasPager()) refreshPagers(offset); 6955 if(CONF.callback) CONF.callback(); 6956 } 6957 6958 function textFilter(offset){ 6959 DOM.$filters[offset].$textFilter.each(function(i, filterEl){ 6960 var textboxVal = $(filterEl).val().toLowerCase(); 6961 6962 $(DOM.$itemWrappers[i].$items).each(function(j, itemEl) { 6963 // to slow for people list 6964 // var listVal = $(itemEl).find($(CONF.searchContentSelector)).text().toLowerCase().replace("fachbereich", ""); 6965 var listVal = $(CONF.searchContentSelector, itemEl).text().toLowerCase().replace("fachbereich", ""); 6966 if(listVal.indexOf(textboxVal) >= 0) { 6967 $(itemEl).removeClass(CONF.textFilterHiddenClass); 6968 if(hasPager()) $(itemEl).removeClass(getHiddenClassesFromPagers()); 6969 } else { 6970 $(itemEl).addClass(CONF.textFilterHiddenClass); 6971 } 6972 }); 6973 }); 6974 6975 } 6976 6977 function selectFilter(offset){ 6978 $(DOM.$itemWrappers[offset].$items).addClass(CONF.selectFilterHiddenClass); 6979 if(hasPager()) $(DOM.$itemWrappers[offset].$items).removeClass(getHiddenClassesFromPagers()); 6980 6981 var filterSelector = ''; 6982 $(DOM.$filters[offset].$selectFilter).each(function(i, e){ 6983 var field = $(e).attr('data-field'); 6984 var value = $('option:selected', e).attr('value'); 6985 if(value) filterSelector += '[data-'+field+'*="uid-'+value+'-end"]'; 6986 }); 6987 $(DOM.$itemWrappers[offset]).find('.'+CONF.itemSelectorClass + filterSelector).removeClass(CONF.selectFilterHiddenClass); 6988 } 6989 6990 function initEvents(){ 6991 DOM.$filters.each(function(i, filterEl){ 6992 // text filter 6993 DOM.$filters[i].$textFilter.each(function(j, textEl){ 6994 $(textEl).keyup(onTextFilterKeyUp.bind(null, i)); 6995 }); 6996 6997 // select filter 6998 DOM.$filters[i].$selectFilter.each(function(j, selectEl){ 6999 $(selectEl).on('change', onSelectFilterChange.bind(null, i)); 7000 }); 7001 }); 7002 } 7003 7004 /** 7005 * inits the CONF.BwFilter module 7006 * 7007 * @param {object} conf optional configuration override 7008 * @return {void} 7009 */ 7010 function init(conf){ 7011 7012 cacheDOM(); 7013 initEvents(); 7014 } 7015 7016 return { 7017 init: init 7018 } 7019 7020}); 7021 7022$(document).ready(function () { 7023 var curLang = $('html').attr('lang'); 7024 $("select").each(function () { 7025 $(this).val($(this).find('option[selected]').val()); 7026 }); 7027 7028 // hide #back-top first 7029 $("#back-top").hide(); 7030 7031 // fade in #back-top 7032 $(function () { 7033 $(window).scroll(function () { 7034 if ($(this).scrollTop() > 100) { 7035 $(window).trigger('load.zf.sticky'); 7036 $('#back-top').fadeIn(); 7037 } else { 7038 $('#back-top').fadeOut(); 7039 } 7040 }); 7041 7042 // scroll body to 0px on click 7043 $('#back-top a').click(function () { 7044 $('body,html').animate({ 7045 scrollTop: 0 7046 }, 800); 7047 return false;
7048 }); 7049 }); 7050 7051 //$(window).trigger('load'); 7052 $(window).trigger('load.zf.sticky'); 7053}); 7054 7055$(function() { 7056 var curLang = $('html').attr('lang'); 7057 $(document).foundation(); 7058 7059 // tt_content Element "Verkürzt" 7060 $('.ce-textpic--short__toggle').on('click', function (e) { 7061 e.preventDefault(); 7062 $(this).parent().find('.ce-textpic--short').toggleClass('ce-textpic--short-hidden'); 7063 }); 7064 7065 // Tabs Modul 7066 $('ul[data-tabs] a').on('click', function (e) { 7067 e.preventDefault(); 7068 var ul = $(this).parent().parent(); 7069 $('a', ul).removeClass('active'); 7070 $(this).addClass('active'); 7071 var panel = $('#' + $(ul).attr('data-tabs-target')); 7072 $('div[data-panel]', panel).removeClass('active'); 7073 $('div[data-panel="' + $(this).attr('href').substr(1) + '"]', panel).addClass('active'); 7074 }); 7075 7076 // Touch fix for main menu 7077 /*$('#mainmenu > li > a').click(function (e) { 7078 if (whatInput.ask() === 'touch') { 7079 e.preventDefault(); 7080 } 7081 });*/ 7082 7083 // Keyboard accessibility: open submenu on focus (desktop only) 7084 $('#mainmenu > li > a').each(function () { 7085 var $link = $(this); 7086 var $li = $link.parent(); 7087 var $submenu = $li.find('> ul'); 7088 7089 if (!$submenu.length) return; 7090 7091 $link.attr('aria-haspopup', 'true').attr('aria-expanded', 'false'); 7092 7093 $link.on('focus', function () { 7094 if (Foundation.MediaQuery.atLeast('medium')) { 7095 $link.attr('aria-expanded', 'true'); 7096 $li.addClass('is-keyboard-focused'); 7097 } 7098 }); 7099 7100 $li.on('focusout', function (e) { 7101 if (!$li[0].contains(e.relatedTarget)) { 7102 $link.attr('aria-expanded', 'false'); 7103 $li.removeClass('is-keyboard-focused'); 7104 } 7105 }); 7106 7107 $li.on('keydown', function (e) { 7108 if (e.key === 'Escape') { 7109 $link.attr('aria-expanded', 'false'); 7110 $li.removeClass('is-keyboard-focused'); 7111 $link.focus(); 7112 } 7113 }); 7114 }); 7115 7116 // search reveal button 7117 $('.openSearchModal').on('click', function (e) { 7118 e.preventDefault(); 7119 $('#searchModal') 7120 .foundation('open') 7121 .find('input[type="text"]').focus(); 7122 }); 7123 7124 function isInViewport(element, toleranceTop, toleranceBottom) { 7125 if (toleranceTop === undefined) { 7126 toleranceTop = 0; 7127 } 7128 if (toleranceBottom === undefined) { 7129 toleranceBottom = 0; 7130 } 7131 var rect = element.getBoundingClientRect(); 7132 var html = document.documentElement; 7133 return ( 7134 rect.top >= (0 - toleranceTop) && 7135 rect.left >= 0 && 7136 rect.bottom <= ((window.innerHeight + toleranceBottom) || (html.clientHeight + toleranceBottom)) && 7137 rect.right <= (window.innerWidth || html.clientWidth) 7138 ); 7139 } 7140 7141 var ScrollLock = false; 7142 var runOnScroll = function (evt) { 7143 if (ScrollLock) { 7144 return; 7145 } 7146 ScrollLock = true; 7147 7148 checkViewportForNumberElements(); 7149 7150 ScrollLock = false; 7151 }; 7152 7153 function checkViewportForNumberElements() { 7154 numbersElements.each(function () { 7155 if (isInViewport(this, 0, 300)) { 7156 $(this).removeClass('numbers--not-in-viewport'); 7157 } else { 7158 $(this).addClass('numbers--not-in-viewport'); 7159 } 7160 }); 7161 } 7162 7163 // numbers animation 7164 var numbersElements = $('section.numbers'); 7165 if (numbersElements.length) { 7166 checkViewportForNumberElements(); 7167 window.addEventListener("scroll", runOnScroll); 7168 } 7169 7170 $('#topbar') 7171 .on('sticky.zf.stuckto:top', function () { 7172 $('body').addClass('topbar-is-stuck'); 7173 }) 7174 .on('sticky.zf.unstuckfrom:top', function () { 7175 $('body').removeClass('topbar-is-stuck'); 7176 }); 7177 $('#topbarMobile') 7178 .on('sticky.zf.stuckto:top', function () { 7179 $('body').addClass('topbar-is-stuck'); 7180 }) 7181 .on('sticky.zf.unstuckfrom:top', function () { 7182 $('body').removeClass('topbar-is-stuck'); 7183 }); 7184 7185 // allgemeines js fuer modal 7186 var modalConf = { 7187 dataType: 'text', 7188 triggerSelector: '.hsa__item', 7189 modalSelector: '#hsaModal', 7190 modalContentWrapperSelector: '.hsaModal__wrapper', 7191 7192 urlAttr: 'data-hsa-detail', 7193 saveAttr: 'data-hsa-json' 7194 }; 7195 BW.Modal.init(modalConf); 7196 7197 BW.DceGallery.init({ 7198 galleryWrapperClass: 'bw-dce-gallery', 7199 switchTriggerSelector: '.bw-dce-gallery__switch', 7200 contentReplacements: [ 7201 { 7202 galleryElementSelector: '.gallery__image',
7203 galleryElementHTML: false, 7204 galleryElementCSS: 'background-image', 7205 galleryElementAttr: false, 7206 triggerElementSelectorr: '.gallery__preview', 7207 triggerElementAttribute: 'data-image' 7208 }, 7209 { 7210 galleryElementSelector: '.gallery__image', 7211 galleryElementHTML: false, 7212 galleryElementCSS: false, 7213 galleryElementAttr: 'data-video', 7214 triggerElementSelectorr: '.gallery__preview', 7215 triggerElementAttribute: 'data-video' 7216 }, 7217 { 7218 galleryElementSelector: '.gallery__image a', 7219 galleryElementHTML: false, 7220 galleryElementCSS: false, 7221 galleryElementAttr: 'data-video', 7222 triggerElementSelectorr: '.gallery__preview', 7223 triggerElementAttribute: 'data-video' 7224 }, 7225 { 7226 galleryElementSelector: '.gallery__header1', 7227 galleryElementHTML: true, 7228 galleryElementCSS: false, 7229 galleryElementAttr: false, 7230 triggerElementSelectorr: '.gallery__preview', 7231 triggerElementAttribute: 'data-gallery__header1' 7232 }, 7233 { 7234 galleryElementSelector: '.gallery__header2', 7235 galleryElementHTML: true, 7236 galleryElementCSS: false, 7237 galleryElementAttr: false, 7238 triggerElementSelectorr: '.gallery__preview', 7239 triggerElementAttribute: 'data-gallery__header2' 7240 }, 7241 { 7242 galleryElementSelector: '.gallery__header3', 7243 galleryElementHTML: true, 7244 galleryElementCSS: false, 7245 galleryElementAttr: false, 7246 triggerElementSelectorr: '.gallery__preview', 7247 triggerElementAttribute: 'data-gallery__header3' 7248 } 7249 ] 7250 }); 7251 7252 // gallery dce 7253 var _this = this; 7254 7255 $('section.gallery').each(function () { 7256 var galleryNmb = $(this).attr('data-gallery-uid'); 7257 var gallery = $('section.gallery[data-gallery-uid="'+ galleryNmb +'"]'); 7258 gallery.find('.gallery__nav a').on('click', function (e) { 7259 e.preventDefault(); 7260 // change active status 7261 gallery.find('.gallery__nav a').removeClass('active'); 7262 $(this).addClass('active'); 7263 7264 // change large image content 7265 gallery.find('.gallery__image') 7266 .attr('style', 'background-image:url(' + gallery.find('a.active .gallery__preview').attr('data-image') + ')') 7267 .attr('data-video', $('.gallery__preview', this).attr('data-video')) 7268 .find('a').attr('data-gallery', 'c'+ galleryNmb +'gallery'+$(this).parent().index()) 7269 .find('.gallery__header1') 7270 .html($('.gallery__preview', this).attr('data-gallery__header1')) 7271 .next().html($('.gallery__preview', this).attr('data-gallery__header2')) 7272 .next().html($('.gallery__preview', this).attr('data-gallery__header3')); 7273 }); 7274 7275 gallery.find('.gallery__image a').on('click', function (e) { 7276 e.preventDefault(); 7277 $('#' + $(this).attr('data-gallery')).foundation('open'); 7278 }); 7279 7280 function reAddVideoSrc(arr) { 7281 video = arr[0]; 7282 videoSRC = arr[1]; 7283 if(videoSRC) $(video).attr('src', videoSRC); 7284 } 7285 7286 // on lightbox close 7287 $(window).on('closed.zf.reveal', function (e) { 7288 var video = e.target; 7289 video = $(video).find('iframe'); 7290 7291 if(!video.length) return; 7292 var videoSRC = $(video).attr('src'); 7293 7294 $(video).attr('src', ''); 7295 setTimeout(reAddVideoSrc.bind(null, [video, videoSRC]), 100); 7296 }); 7297 7298 // überprüfe alle slider auf videos 7299 $('.orbit.orbit--textmedia').each(function (i, e) { 7300 if ($(e).find('iframe').length) { 7301 $(e).addClass('contains-video'); 7302 if ($(e).find('.orbit-slide.is-active iframe').length) { 7303 $(e).attr('data-active-video', '0'); 7304 } 7305 } 7306 }); 7307 7308 // bei slider change 7309 $(window).on('slidechange.zf.orbit', function (e){ 7310 // exit if orbit slider has no video 7311 if(!$(e.target).hasClass('contains-video')) return; 7312 7313 // kill video if slide exits from active video 7314 if ($(e.target)[0].hasAttribute('data-active-video')) { 7315 var video = $(e.target).find('li[data-slide="' + $(e.target).attr('data-active-video') + '"] iframe'); 7316 var videoSRC = $(video).attr('src'); 7317 $(video).attr('src', ''); 7318 setTimeout(function(){ $(video).attr('src', videoSRC); }, 100); 7319 } 7320 7321 // falls die nächste (aktuelle) slide ein video enthält 7322 if ($(e.target).find('li.is-active iframe').length) { 7323 var slideId = $(e.target).find('li.is-active iframe').closest('li').attr('data-sli
7323de'); 7324 $(e.target).attr('data-active-video', slideId); 7325 } else { 7326 $(e.target).removeAttr('data-active-video'); 7327 } 7328 }); 7329 }); 7330 7331 switch (curLang) { 7332 case 'de': 7333 // start pagination plugin 7334 var bwPaginateDefault = BW.Paginate({ 7335 itemsPerPage: 30, 7336 paginationSelector: '.hsa__pagination', 7337 itemWrapperSelector: '.searchresults', 7338 itemSelectorClass: 'list__item', 7339 itemHiddenClass: 'list__item--hiddenByPagination', 7340 itemIgnoreSelector: '.list__item--hiddenByFilter,.list__item--hiddenBySearch', 7341 buttonClass: 'button third', 7342 buttonPrevText: 'zurück', 7343 buttonNextText: 'vor', 7344 buttonActiveClass: 'active', 7345 buttonDisabledClass: 'disabled', 7346 scrollTopSelector: 'h1' 7347 }); 7348 bwPaginateDefault.init(); 7349 7350 // galerie CE 7351 var bwPaginateImageGallery = BW.Paginate({ 7352 itemsPerPage: 25, 7353 paginationSelector: '.hsa__pagination-gallery', 7354 itemWrapperSelector: '.searchresults-gallery', 7355 itemSelectorClass: 'list__item', 7356 itemHiddenClass: 'list__item--hiddenByPagination', 7357 itemIgnoreSelector: '.list__item--hiddenByFilter,.list__item--hiddenBySearch', 7358 buttonClass: 'button third', 7359 buttonPrevText: 'zurück', 7360 buttonNextText: 'vor', 7361 buttonActiveClass: 'active', 7362 buttonDisabledClass: 'disabled', 7363 scrollTopSelector: '.searchresults-gallery' 7364 }); 7365 bwPaginateImageGallery.init(); 7366 7367 // cal listview 7368 var bwPaginateCal = BW.Paginate({ 7369 itemsPerPage: 9, 7370 paginationSelector: '.hsa__pagination-cal', 7371 itemWrapperSelector: '.searchresults', 7372 itemSelectorClass: 'list__item', 7373 itemHiddenClass: 'list__item--hiddenByPagination', 7374 itemIgnoreSelector: '.list__item--hiddenByFilter,.list__item--hiddenBySearch', 7375 buttonClass: 'button third', 7376 buttonPrevText: 'zurück', 7377 buttonNextText: 'vor', 7378 buttonActiveClass: 'active', 7379 buttonDisabledClass: 'disabled', 7380 scrollTopSelector: '.tx-cal-controller' 7381 }); 7382 bwPaginateCal.init(); 7383 break; 7384 default: 7385 // start pagination plugin 7386 var bwPaginateDefault = BW.Paginate({ 7387 itemsPerPage: 30, 7388 paginationSelector: '.hsa__pagination', 7389 itemWrapperSelector: '.searchresults', 7390 itemSelectorClass: 'list__item', 7391 itemHiddenClass: 'list__item--hiddenByPagination', 7392 itemIgnoreSelector: '.list__item--hiddenByFilter,.list__item--hiddenBySearch', 7393 buttonClass: 'button third', 7394 buttonPrevText: 'previous', 7395 buttonNextText: 'next', 7396 buttonActiveClass: 'active', 7397 buttonDisabledClass: 'disabled', 7398 scrollTopSelector: 'h1' 7399 }); 7400 bwPaginateDefault.init(); 7401 7402 // galerie CE 7403 var bwPaginateImageGallery = BW.Paginate({ 7404 itemsPerPage: 25, 7405 paginationSelector: '.hsa__pagination-gallery', 7406 itemWrapperSelector: '.searchresults-gallery', 7407 itemSelectorClass: 'list__item', 7408 itemHiddenClass: 'list__item--hiddenByPagination', 7409 itemIgnoreSelector: '.list__item--hiddenByFilter,.list__item--hiddenBySearch', 7410 buttonClass: 'button third', 7411 buttonPrevText: 'previous', 7412 buttonNextText: 'next', 7413 buttonActiveClass: 'active', 7414 buttonDisabledClass: 'disabled', 7415 scrollTopSelector: '.searchresults-gallery' 7416 }); 7417 bwPaginateImageGallery.init(); 7418 7419 // cal listview 7420 var bwPaginateCal = BW.Paginate({ 7421 itemsPerPage: 9, 7422 paginationSelector: '.hsa__pagination-cal', 7423 itemWrapperSelector: '.searchresults', 7424 itemSelectorClass: 'list__item', 7425 itemHiddenClass: 'list__item--hiddenByPagination', 7426 itemIgnoreSelector: '.list__item--hiddenByFilter,.list__item--hiddenBySearch', 7427 buttonClass: 'button third', 7428 buttonPrevText: 'previous', 7429 buttonNextText: 'next', 7430 buttonActiveClass: 'active', 7431 buttonDisabledClass: 'disabled', 7432 scrollTopSelector: '.tx-cal-controller' 7433 }); 7434 bwPaginateCal.init(); 7435 } 7436 7437 7438 // start filter plugin 7439 var bwFilterDefault = BW.Filter({ 7440 searchContentSelector: '.searchcontent', 7441 filtersWrapperSelector: '.hsa__filter', 7442 itemWrapperSelector: '.searchresults', 7443 itemSelectorClass: 'list__item', 7444 textFilterSelector: '#filter', 7445 selectFilterSelector: 'select', 7446 textFilterHiddenClass: 'list__item--hiddenBySearch', 7447 selectFilterHiddenClass: 'list__item--hiddenByFilter', 7448 callback: function () { 7449 $('.lazyimg').lazyload({ 7450 effect : "fadeIn", 7451 effect_speed: 500, 7452 load: function (elements_left, settings){ 7453 } 7454 }); 7455 }, 7456 BwPaginateArray: [bwPaginateDefault, bwPaginateCal] 7457 }); 7458 bwFilterDefault.init(); 7459 7460 // restart Orbit in revealPopUp, für cal, showroom, news usw. (EVI) 7461 $(window).on('open.zf.reveal', function (e) { 7462 $('.orbit').foundation(); 7463 $('#content').addClass("hide-for-print"); 7464 $('footer').addClass("hide-for-print"); 7465 //$('#content').fadeOut(); 7466 //$('footer').fadeOut(); 7467 7468 $('.accordion').foundation(); 7469 }); 7470 7471 // fuer print um content unter dem popup nicht zu drucken 7472 $(window).on('closed.zf.reveal', function (e) { 7473 $('#content').removeClass("hide-for-print"); 7474 $('footer').removeClass("hide-for-print"); 7475 //$('#content').fadeIn(); 7476 //$('footer').fadeIn(); 7477 7478 $('section.gallery').each(function () { 7479 var galleryNmb = $(this).attr('data-gallery-uid'); 7480 var gallery = $('section.gallery[data-gallery-uid="' + galleryNmb + '"]'); 7481 gallery.find('.gallery__image').attr('style', 'background-image:url(' + gallery.find('a.active .gallery__preview').attr('data-image') + ')'); 7482 }); 7483 }); 7484 7485 // lazy loading for Images (EVI) 7486 $('.lazyimg').lazyload({ 7487 effect : "fadeIn", 7488 effect_speed: 500, 7489 load: function(elements_left, settings){ 7490 } 7491 }); 7492
7493 // equalizer in tabs bugfix 7494 $(".tabcontent .tabs").on("change.zf.tabs", function (e) { 7495 var newId = $(e.target).find('li.tabs-title.is-active a').attr('aria-controls'); 7496 var currentScrollTop = document.documentElement.scrollTop; 7497 window.location.hash = newId; 7498 window.scrollTo(0, currentScrollTop); 7499 $('html,body').animate({scrollTop: $(e.target).offset().top - 100}, 'slow'); 7500 if ($('[data-equalizer]').length) { 7501 Foundation.reInit('equalizer'); 7502 } 7503 if ($('[data-orbit]').length) { 7504 Foundation.reInit('orbit'); 7505 } 7506 }); 7507 $("#studiengang-tabs").on("change.zf.tabs", function (e) { 7508 var newId = $(e.target).find('li.tabs-title.is-active a').attr('aria-controls'); 7509 window.location.hash = newId; 7510 window.scrollTo(0, 0); 7511 if ($('[data-equalizer]').length) { 7512 Foundation.reInit('equalizer'); 7513 } 7514 if ($('[data-orbit]').length) { 7515 Foundation.reInit('orbit'); 7516 } 7517 }); 7518 7519 if (window.location.hash) { 7520 var f6dl_url = window.location.hash; 7521 var f6dl_hash = f6dl_url.substring(f6dl_url.indexOf("#") + 1); 7522 if($('#' + f6dl_hash).length) { 7523 var f6dl_ulid = 'tabs-title'; 7524 $('.' + f6dl_ulid).find('a').each(function (e) { 7525 var f6dl_href = $(this).attr('href'); 7526 if (f6dl_href.substring(f6dl_href.indexOf("#") + 1) == f6dl_hash) { 7527 // Click the link to activate the tab 7528 $(this).click(); 7529 } 7530 }); 7531 // open modal with anchor in uri 7532 var f6dl_ulid = 'list__item'; 7533 $('.' + f6dl_ulid).find('.hsa__item').each(function (e) { 7534 var f6dl_id = $(this).attr('id'); 7535 if (f6dl_id == f6dl_hash) { 7536 $(this).click(); 7537 } 7538 }); 7539 } 7540 } 7541 // https://varvy.com/pagespeed/defer-videos.html 7542 $(window).on('open.zf.reveal', function (e) { 7543 $('.lazyimg').lazyload(); 7544 var vidDefer = document.getElementsByTagName('iframe'); 7545 for (var i=0; i<vidDefer.length; i++) { 7546 if(vidDefer[i].getAttribute('data-src')) { 7547 vidDefer[i].setAttribute('src',vidDefer[i].getAttribute('data-src')); 7548 } 7549 } 7550 }); 7551 7552}); 7553 7554/*neu um den orbit slider auf der startseite vom alten foundation zu lösen*/ 7555 7556document.addEventListener('DOMContentLoaded', () => { 7557 const sliderRoot = document.querySelector('#hero .custom-hero-slider'); 7558 if (!sliderRoot) return; 7559 7560 const slides = sliderRoot.querySelectorAll('.custom-slider-item'); 7561 const dots = sliderRoot.querySelectorAll('[data-custom-dot]'); 7562 const prevBtn = sliderRoot.querySelector('.hero__arrow--prev'); 7563 const nextBtn = sliderRoot.querySelector('.hero__arrow--next'); 7564 7565 if (slides.length === 0) return; 7566 7567 const intervalTime = parseInt(sliderRoot.getAttribute('data-custom-timer'), 10) || 8000; 7568 let currentIndex = 0; 7569 let sliderInterval = null; 7570 7571 // Weist den Slides automatisch die Indizes passend zu den Fluid-Buttons zu 7572 slides.forEach((slide, i) => { 7573 slide.setAttribute('data-custom-slide', i); 7574 }); 7575 7576 function showSlide(index) { 7577 if (index >= slides.length) currentIndex = 0; 7578 else if (index < 0) currentIndex = slides.length - 1; 7579 else currentIndex = index; 7580 7581 // Slides toggeln 7582 slides.forEach((slide, i) => { 7583 if (i === currentIndex) { 7584 slide.classList.add('is-active'); 7585 slide.setAttribute('aria-live', 'polite'); 7586 } else { 7587 slide.classList.remove('is-active'); 7588 slide.removeAttribute('aria-live'); 7589 } 7590 }); 7591 7592 // Fluid-Dots toggeln 7593 dots.forEach((dot, i) => { 7594 if (i === currentIndex) { 7595 dot.classList.add('is-active'); 7596 } else { 7597 dot.classList.remove('is-active'); 7598 } 7599 }); 7600 } 7601 7602 function nextSlide() { showSlide(currentIndex + 1); } 7603 function prevSlide() { showSlide(currentIndex - 1); } 7604 7605 function startAutoplay() { 7606 stopAutoplay(); 7607 sliderInterval = setInterval(nextSlide, intervalTime); 7608 } 7609 7610 function stopAutoplay() { 7611 if (sliderInterval) clearInterval(sliderInterval); 7612 } 7613 7614 // Event-Listener für Pfeile 7615 if (nextBtn) { 7616 nextBtn.addEventListener('click', (e) => { 7617 e.preventDefault(); nextSlide(); startAutoplay(); 7618 }); 7619 } 7620 7621 if (prevBtn) { 7622 prevBtn.addEventListener('click', (e) => { 7623 e.preventDefault(); prevSlide(); startAutoplay(); 7624 }); 7625 } 7626 7627 // Event-Listener für deine Fluid-Buttons
7628 dots.forEach(dot => { 7629 dot.addEventListener('click', (e) => { 7630 e.preventDefault(); 7631 const targetIndex = parseInt(e.target.getAttribute('data-custom-dot'), 10); 7632 showSlide(targetIndex); 7633 startAutoplay(); 7634 }); 7635 }); 7636 7637 // Hover-Pause & Tastatur 7638 sliderRoot.addEventListener('mouseenter', stopAutoplay); 7639 sliderRoot.addEventListener('mouseleave', startAutoplay); 7640 7641 sliderRoot.addEventListener('keydown', (e) => { 7642 if (e.key === 'ArrowRight') { nextSlide(); startAutoplay(); } 7643 if (e.key === 'ArrowLeft') { prevSlide(); startAutoplay(); } 7644 }); 7645 7646 // Initialer Start (Zustand 0) 7647 showSlide(currentIndex); 7648 startAutoplay(); 7649});
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.