1 2// Document ready jquery 3$(document).ready(function() { 4 // Unslider 5 $('#toggleSearch').click(function(e) { 6 e.preventDefault(); 7 e.stopPropagation(); 8 $('.hiddenSearch').toggleClass('active'); 9 }); 10 11 12 $('#closeSearch').click(function(e) { 13 e.preventDefault(); 14 e.stopPropagation(); 15 $('.hiddenSearch').removeClass('active'); 16 }); 17 18setTimeout(function(){ 19 if($('.unslider').length < 1 && $('.has_ae_slider').length < 1 && $('.main-image').length < 1){ 20 $('.logoContainer').addClass('logoContainer-unslider'); 21 } 22}, 750); 23 // Toggle Mobile Menu 24 25 $('#toggleMobileMenu').click(function(e) { 26 e.preventDefault(); 27 e.stopPropagation(); 28 $('.mobileMenuActive').addClass('active'); 29 $(this).css('display', 'none'); 30 $('#toggleMobileMenuClose').css('display', 'block'); 31 }); 32 33 $('#toggleMobileMenuClose').click(function(e) { 34 e.preventDefault(); 35 e.stopPropagation(); 36 $('.mobileMenuActive').removeClass('active'); 37 $(this).css('display', 'none'); 38 $('#toggleMobileMenu').css('display', 'block'); 39 }); 40 41 42 // Click outside 43 44 // Add icon to .menu-item-has-children 45 $('.menu-item-has-children > a').append('<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 320 512"><!--! Font Awesome Pro 6.1.1 by @fontawesome - https://fontawesome.com License - https://fontawesome.com/license (Commercial License) Copyright 2022 Fonticons, Inc. --><path d="M310.6 246.6l-127.1 128C176.4 380.9 168.2 384 160 384s-16.38-3.125-22.63-9.375l-127.1-128C.2244 237.5-2.516 223.7 2.438 211.8S19.07 192 32 192h255.1c12.94 0 24.62 7.781 29.58 19.75S319.8 237.5 310.6 246.6z"/></svg>'); 46 47 // $('.menu-item-has-children > .sub-menu').prepend( 48 // $('.menu-item-has-children > a').clone() 49 // ); 50 51 $('.menu-item-has-children').each(function() { 52 // Prepend text "Heading" to each menu item with children 53 $(this).find('.sub-menu').prepend(
54 "<div class=\"sub-menu-heading\">" + $(this).children('a').first().text() + "</div>" 55 ); 56 }); 57 58 59 $('#nav_menu .menu-item-has-children > a').click(function(e) { 60 e.preventDefault(); 61 e.stopPropagation(); 62 if($(this).parent().children('.sub-menu').hasClass('active')){ 63 $(this).parent().children('.sub-menu').removeClass('active'); 64 } else { 65 $('.sub-menu').removeClass('active'); 66 $(this).parent().children('.sub-menu').addClass('active'); 67 } 68 }); 69 70 // Click outside 71 $(document).click(function(e) { 72 $('.sub-menu').removeClass('active'); 73 74 $('.sub-menu').click(function(e) { 75 e.stopPropagation(); 76 return; 77 }); 78 79 }); 80 81}); 82 83 84/** 85 * Unslider 86 * version 2.0 87 * by @idiot and friends 88 */ 89 90(function(factory) { 91 if (typeof module === 'object' && typeof module.exports === 'object') { 92 factory(require('jquery')); 93 } else if (typeof define === 'function' && define.amd) { 94 // AMD. Register as an anonymous module. 95 define([], factory(window.jQuery)); 96 } else { 97 factory(window.jQuery); 98 } 99}(function($) { 100 // Don't throw any errors when jQuery 101 if(!$) { 102 return console.warn('Unslider needs jQuery'); 103 } 104 105 $.Unslider = function(context, options) { 106 var self = this; 107 108 // Create an Unslider reference we can use everywhere 109 self._ = 'unslider'; 110 111 // Store our default options in here 112 // Everything will be overwritten by the jQuery plugin though 113 self.defaults = { 114 // Should the slider move on its own or only when 115 // you interact with the nav/arrows? 116 // Only accepts boolean true/false. 117 autoplay: false, 118 119 // 3 second delay between slides moving, pass 120 // as a number in milliseconds. 121 delay: 3000, 122 123 // Animation speed in millseconds 124 speed: 750, 125 126 // An easing string to use. If you're using Velocity, use a 127 // Velocity string otherwise you can use jQuery/jQ UI options. 128 easing: 'swing', // [.42, 0, .58, 1], 129 130 // Does it support keyboard arrows? 131 // Can pass either true or false - 132 // or an object with the keycodes, like so: 133 // { 134 // prev: 37, 135 // next: 39 136 // } 137 // You can call any internal method name 138 // before the keycode and it'll be called. 139 keys: { 140 prev: 37, 141 next: 39 142 }, 143 144 // Do you want to generate clickable navigation 145 // to skip to each slide? Accepts boolean true/false or 146 // a callback function per item to generate. 147 nav: true, 148 149 // Should there be left/right arrows to go back/forth? 150 // -> This isn't keyboard support. 151 // Either set true/false, or an object with the HTML 152 // elements for each arrow like below: 153 arrows: { 154 prev: '<a class="' + self._ + '-arrow prev">Prev</a>', 155 next: '<a class="' + self._ + '-arrow next">Next</a>' 156 }, 157 158 // How should Unslider animate? 159 // It can do one of the following types: 160 // "fade": each slide fades in to each other 161 // "horizontal": each slide moves from left to right 162 // "vertical": each slide moves from top to bottom 163 animation: 'horizontal', 164 165 // If you don't want to use a list to display your slides, 166 // you can change it here. Not recommended and you'll need 167 // to adjust the CSS accordingly. 168 selectors: { 169 container: 'ul:first', 170 slides: 'li' 171 }, 172 173 // Do you want to animate the heights of each slide as 174 // it moves 175 animateHeight: false, 176 177 // Active class for the nav 178 activeClass: self._ + '-active', 179 180 // Have swipe support? 181 // You can set this here with a boolean and always use 182 // initSwipe/destroySwipe later on. 183 swipe: true, 184 // Swipe threshold - 185 // lower float for enabling short swipe 186 swipeThreshold: 0.2 187 }; 188 189 // Set defaults 190 self.$context = context; 191 self.options = {}; 192 193 // Leave our elements blank for now 194 // Since they get changed by the options, we'll need to 195 // set them in the init method. 196 self.$parent = null; 197 self.$container = null; 198 self.$slides = null; 199 self.$nav = null; 200 self.$arrows = []; 201 202 // Set our indexes and totals 203 self.total = 0; 204 self.current = 0; 205 206 // Generate a specific random ID so we don't dupe events 207 self.prefix = self._ + '-'; 208 self.eventSuffix = '.' + self.prefix + ~~(Math.random() * 2e3); 209 210 // In case we're going to use the autoplay 211 self.interval = []; 212 213 // Get everything set up innit 214 self.init = function(options) { 215 // Set up our options inside here so we can re-init at 216 // any time 217 self.options = $.extend({}, self.defaults, options); 218 219 // Our elements 220 self.$container = self.$context.find(self.options.selectors.container).addClass(self.prefix + 'wrap'); 221 self.$slides = self.$container.children(self.options.selectors.slides); 222 223 // We'll manually init the container 224 self.setup(); 225 226 // We want to keep this script as small as possible 227 // so we'll optimise some checks
228 $.each(['nav', 'arrows', 'keys', 'infinite'], function(index, module) { 229 self.options[module] && self['init' + $._ucfirst(module)](); 230 }); 231 232 // Add swipe support 233 if(jQuery.event.special.swipe && self.options.swipe) { 234 self.initSwipe(); 235 } 236 237 // If autoplay is set to true, call self.start() 238 // to start calling our timeouts 239 self.options.autoplay && self.start(); 240 241 // We should be able to recalculate slides at will 242 self.calculateSlides(); 243 244 // Listen to a ready event 245 self.$context.trigger(self._ + '.ready'); 246 247 // Everyday I'm chainin' 248 return self.animate(self.options.index || self.current, 'init'); 249 }; 250 251 self.setup = function() { 252 // Add a CSS hook to the main element 253 self.$context.addClass(self.prefix + self.options.animation).wrap('<div class="' + self._ + '" />'); 254 self.$parent = self.$context.parent('.' + self._); 255 256 // We need to manually check if the container is absolutely 257 // or relatively positioned 258 var position = self.$context.css('position'); 259 260 // If we don't already have a position set, we'll 261 // automatically set it ourselves 262 if(position === 'static') { 263 self.$context.css('position', 'relative'); 264 } 265 266 self.$context.css('overflow', 'hidden'); 267 }; 268 269 // Set up the slide widths to animate with 270 // so the box doesn't float over 271 self.calculateSlides = function() { 272 // update slides before recalculating the total 273 self.$slides = self.$container.children(self.options.selectors.slides); 274 275 self.total = self.$slides.length; 276 277 // Set the total width 278 if(self.options.animation !== 'fade') { 279 var prop = 'width'; 280 281 if(self.options.animation === 'vertical') { 282 prop = 'height'; 283 } 284 285 self.$container.css(prop, (self.total * 100) + '%').addClass(self.prefix + 'carousel'); 286 self.$slides.css(prop, (100 / self.total) + '%'); 287 } 288 }; 289 290 291 // Start our autoplay 292 self.start = function() { 293 self.interval.push(setTimeout(function() { 294 // Move on to the next slide 295 self.next(); 296 297 // If we've got autoplay set up 298 // we don't need to keep starting 299 // the slider from within our timeout 300 // as .animate() calls it for us 301 }, self.options.delay)); 302 303 return self; 304 }; 305 306 // And pause our timeouts 307 // and force stop the slider if needed 308 self.stop = function() { 309 var timeout; 310 while(timeout = self.interval.pop()) { 311 clearTimeout(timeout); 312 } 313 314 return self; 315 }; 316 317 318 // Set up our navigation 319 self.initNav = function() { 320 var $nav = $('<nav class="' + self.prefix + 'nav"><ol /></nav>'); 321 322 // Build our click navigation item-by-item 323 self.$slides.each(function(key) { 324 // If we've already set a label, let's use that 325 // instead of generating one 326 var label = this.getAttribute('data-nav') || key + 1; 327 328 // Listen to any callback functions 329 if($.isFunction(self.options.nav)) { 330 label = self.options.nav.call(self.$slides.eq(key), key, label); 331 } 332 333 // And add it to our navigation item 334 $nav.children('ol').append('<li data-slide="' + key + '">' + label + '</li>'); 335 }); 336 337 // Keep a copy of the nav everywhere so we can use it 338 self.$nav = $nav.insertAfter(self.$context); 339 340 // Now our nav is built, let's add it to the slider and bind 341 // for any click events on the generated links 342 self.$nav.find('li').on('click' + self.eventSuffix, function() { 343 // Cache our link and set it to be active 344 var $me = $(this).addClass(self.options.activeClass); 345 346 // Set the right active class, remove any other ones 347 $me.siblings().removeClass(self.options.activeClass); 348 349 // Move the slide 350 self.animate($me.attr('data-slide')); 351 }); 352 }; 353 354 355 // Set up our left-right arrow navigation 356 // (Not keyboard arrows, prev/next buttons) 357 self.initArrows = function() { 358 if(self.options.arrows === true) { 359 self.options.arrows = self.defaults.arrows; 360 } 361 362 // Loop our options object and bind our events 363 $.each(self.options.arrows, function(key, val) { 364 // Add our arrow HTML and bind it 365 self.$arrows.push(
366 $(val).insertAfter(self.$context).on('click' + self.eventSuffix, self[key]) 367 ); 368 }); 369 }; 370 371 372 // Set up our keyboad navigation 373 // Allow binding to multiple keycodes 374 self.initKeys = function() { 375 if(self.options.keys === true) { 376 self.options.keys = self.defaults.keys; 377 } 378 379 $(document).on('keyup' + self.eventSuffix, function(e) { 380 $.each(self.options.keys, function(key, val) { 381 if(e.which === val) { 382 $.isFunction(self[key]) && self[key].call(self); 383 } 384 }); 385 }); 386 }; 387 388 // Requires jQuery.event.swipe 389 // -> stephband.info/jquery.event.swipe 390 self.initSwipe = function() { 391 var width = self.$slides.width(); 392 393 // We don't want to have a tactile swipe in the slider 394 // in the fade animation, as it can cause some problems 395 // with layout, so we'll just disable it. 396 if(self.options.animation !== 'fade') { 397 398 self.$container.on({ 399 400 movestart: function(e) { 401 // If the movestart heads off in a upwards or downwards 402 // direction, prevent it so that the browser scrolls normally. 403 if((e.distX > e.distY && e.distX < -e.distY) || (e.distX < e.distY && e.distX > -e.distY)) { 404 return !!e.preventDefault(); 405 } 406 407 self.$container.css('position', 'relative'); 408 }, 409 410 move: function(e) { 411 self.$container.css('left', -(100 * self.current) + (100 * e.distX / width) + '%'); 412 }, 413 414 moveend: function(e) { 415 // Check if swiped distance is greater than threshold. 416 // If yes slide to next/prev slide. If not animate to 417 // starting point. 418 419 if((Math.abs(e.distX) / width) > self.options.swipeThreshold) { 420 421 self[e.distX < 0 ? 'next' : 'prev'](); 422 } 423 else { 424 425 self.$container.animate({left: -(100 * self.current) + '%' }, self.options.speed / 2 ); 426 } 427 } 428 }); 429 } 430 }; 431 432 // Infinite scrolling is a massive pain in the arse 433 // so we need to create a whole bloody function to set 434 // it up. Argh. 435 self.initInfinite = function() { 436 var pos = ['first', 'last']; 437 438 $.each(pos, function(index, item) { 439 self.$slides.push.apply( 440 self.$slides, 441 442 // Exclude all cloned slides and call .first() or .last() 443 // depending on what `item` is. 444 self.$slides.filter(':not(".' + self._ + '-clone")')[item]() 445 446 // Make a copy of it and identify it as a clone 447 .clone().addClass(self._ + '-clone') 448 449 // Either insert before or after depending on whether we're 450 // the first or last clone 451 ['insert' + (index === 0 ? 'After' : 'Before')]( 452 // Return the other element in the position array 453 // if item = first, return "last" 454 self.$slides[pos[~~!index]]() 455 ) 456 ); 457 }); 458 }; 459 460 // Remove any trace of arrows 461 // Loop our array of arrows and use jQuery to remove 462 // It'll unbind any event handlers for us 463 self.destroyArrows = function() { 464 $.each(self.$arrows, function(i, $arrow) { 465 $arrow.remove(); 466 }); 467 }; 468 469 // Remove any swipe events and reset the position 470 self.destroySwipe = function() { 471 // We bind to 4 events, so we'll unbind those 472 self.$container.off('movestart move moveend'); 473 }; 474 475 // Unset the keyboard navigation 476 // Remove the handler 477 self.destroyKeys = function() { 478 // Remove the event handler 479 $(document).off('keyup' + self.eventSuffix); 480 }; 481 482 self.setIndex = function(to) { 483 if(to < 0) { 484 to = self.total - 1; 485 } 486 487 self.current = Math.min(Math.max(0, to), self.total - 1); 488 489 if(self.options.nav) { 490 self.$nav.find('[data-slide="' + self.current + '"]')._active(self.options.activeClass); 491 } 492 493 self.$slides.eq(self.current)._active(self.options.activeClass); 494 495 return self; 496 }; 497 498 // Despite the name, this doesn't do any animation - since there's 499 // now three different types of animation, we let this method delegate 500 // to the right type, keeping the name for backwards compat. 501 self.animate = function(to, dir) { 502 // Animation shortcuts 503 // Instead of passing a number index, we can now 504 // use .data('unslider').animate('last'); 505 // or .unslider('animate:last') 506 // to go to the very last slide 507 if(to === 'first') to = 0; 508 if(to === 'last') to = self.total; 509 510 // Don't animate if it's not a valid index 511 if(isNaN(to)) { 512 return self; 513 } 514 515 if(self.options.autoplay) { 516 self.stop().start(); 517 } 518 519 self.setIndex(to); 520 521 // Add a callback method to do stuff with 522 self.$context.trigger(self._ + '.change', [to, self.$slides.eq(to)]); 523
524 // Delegate the right method - everything's named consistently 525 // so we can assume it'll be called "animate" + 526 var fn = 'animate' + $._ucfirst(self.options.animation); 527 528 // Make sure it's a valid animation method, otherwise we'll get 529 // a load of bug reports that'll be really hard to report 530 if($.isFunction(self[fn])) { 531 self[fn](self.current, dir); 532 } 533 534 return self; 535 }; 536 537 538 // Shortcuts for animating if we don't know what the current 539 // index is (i.e back/forward) 540 // For moving forward we need to make sure we don't overshoot. 541 self.next = function() { 542 var target = self.current + 1; 543 544 // If we're at the end, we need to move back to the start 545 if(target >= self.total) { 546 if(self.options.noloop && !self.options.infinite) { 547 target = self.total - 1; 548 } else { 549 target = 0; 550 } 551 } 552 553 return self.animate(target, 'next'); 554 }; 555 556 // The same as next, but the opposite :) 557 self.prev = function() { 558 var target = self.current - 1; 559 560 // If we're at the first, we need to move forward to the end 561 if(target < 0) { 562 if(self.options.noloop && !self.options.infinite) { 563 target = 0; 564 } else { 565 target = self.total - 1; 566 } 567 } 568 569 return self.animate(target, 'prev'); 570 }; 571 572 573 // Our default animation method, the old-school left-to-right 574 // horizontal animation 575 self.animateHorizontal = function(to) { 576 var prop = 'left'; 577 578 // Add RTL support, slide the slider 579 // the other way if the site is right-to-left 580 if(self.$context.attr('dir') === 'rtl') { 581 prop = 'right'; 582 } 583 584 if(self.options.infinite) { 585 // So then we need to hide the first slide 586 self.$container.css('margin-' + prop, '-100%'); 587 } 588 589 return self.slide(prop, to); 590 }; 591 592 // The same animation methods, but vertical support 593 // RTL doesn't affect the vertical direction so we 594 // can just call as is 595 self.animateVertical = function(to) { 596 self.options.animateHeight = true; 597 598 // Normal infinite CSS fix doesn't work for 599 // vertical animation so we need to manually set it 600 // with pixels. Ah well. 601 if(self.options.infinite) { 602 self.$container.css('margin-top', -self.$slides.outerHeight()); 603 } 604 605 return self.slide('top', to); 606 }; 607 608 // Actually move the slide now 609 // We have to pass a property to animate as there's 610 // a few different directions it can now move, but it's 611 // otherwise unchanged from before. 612 self.slide = function(prop, to) { 613 // If we want to change the height of the slider 614 // to match the current slide, you can set 615 // {animateHeight: true} 616 self.animateHeight(to); 617 618 // For infinite sliding we add a dummy slide at the end and start 619 // of each slider to give the appearance of being infinite 620 if(self.options.infinite) { 621 var dummy; 622 623 // Going backwards to last slide 624 if(to === self.total - 1) { 625 // We're setting a dummy position and an actual one 626 // the dummy is what the index looks like 627 // (and what we'll silently update to afterwards), 628 // and the actual is what makes it not go backwards 629 dummy = self.total - 3; 630 to = -1; 631 } 632 633 // Going forwards to first slide 634 if(to === self.total - 2) { 635 dummy = 0; 636 to = self.total - 2; 637 } 638 639 // If it's a number we can safely set it 640 if(typeof dummy === 'number') { 641 self.setIndex(dummy); 642 643 // Listen for when the slide's finished transitioning so 644 // we can silently move it into the right place and clear 645 // this whole mess up. 646 self.$context.on(self._ + '.moved', function() { 647 if(self.current === dummy) { 648 self.$container.css(prop, -(100 * dummy) + '%').off(self._ + '.moved'); 649 } 650 }); 651 } 652 } 653 654 // We need to create an object to store our property in 655 // since we don't know what it'll be. 656 var obj = {}; 657 658 // Manually create it here 659 obj[prop] = -(100 * to) + '%'; 660 661 // And animate using our newly-created object 662 return self._move(self.$container, obj); 663 }; 664 665 666 // Fade between slides rather than, uh, sliding it 667 self.animateFade = function(to) { 668 // If we want to change the height of the slider 669 // to match the current slide, you can set 670 // {animateHeight: true} 671 self.animateHeight(to); 672 673 var $active = self.$slides.eq(to).addClass(self.options.activeClass); 674 675 // Toggle our classes 676 self._move($active.siblings().removeClass(self.options.activeClass), {opacity: 0}); 677 self._move($active, {opacity: 1}, false); 678 }; 679 680 // Animate height of slider 681 self.animateHeight = function(to) { 682 // If we want to change the height of the slider 683 // to match the current slide, you can set 684 // {animateHeight: true} 685 if (self.options.animateHeight) { 686 self._move(self.$context, {height: self.$slides.eq(to).outerHeight()}, false); 687 } 688 }; 689
690 self._move = function($el, obj, callback, speed) { 691 if(callback !== false) { 692 callback = function() { 693 self.$context.trigger(self._ + '.moved'); 694 }; 695 } 696 697 return $el._move(obj, speed || self.options.speed, self.options.easing, callback); 698 }; 699 700 // Allow daisy-chaining of methods 701 return self.init(options); 702 }; 703 704 // Internal (but global) jQuery methods 705 // They're both just helpful types of shorthand for 706 // anything that might take too long to write out or 707 // something that might be used more than once. 708 $.fn._active = function(className) { 709 return this.addClass(className).siblings().removeClass(className); 710 }; 711 712 // The equivalent to PHP's ucfirst(). Take the first 713 // character of a string and make it uppercase. 714 // Simples. 715 $._ucfirst = function(str) { 716 // Take our variable, run a regex on the first letter 717 return (str + '').toLowerCase().replace(/^./, function(match) { 718 // And uppercase it. Simples. 719 return match.toUpperCase(); 720 }); 721 }; 722 723 $.fn._move = function() { 724 this.stop(true, true); 725 return $.fn[$.fn.velocity ? 'velocity' : 'animate'].apply(this, arguments); 726 }; 727 728 // And set up our jQuery plugin 729 $.fn.unslider = function(opts) { 730 return this.each(function(index,elem) { 731 var $this = $(elem); 732 var unslider = $(elem).data('unslider'); 733 if(unslider instanceof $.Unslider) { 734 return; 735 } 736 // Allow usage of .unslider('function_name') 737 // as well as using .data('unslider') to access the 738 // main Unslider object 739 if(typeof opts === 'string' && $this.data('unslider')) { 740 opts = opts.split(':'); 741 742 var call = $this.data('unslider')[opts[0]]; 743 744 // Do we have arguments to pass to the string-function? 745 if($.isFunction(call)) { 746 return call.apply($this, opts[1] ? opts[1].split(',') : null); 747 } 748 } 749 750 return $this.data('unslider', new $.Unslider($this, opts)); 751 }); 752 }; 753 754}));
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.