1jQuery(document).ready(function($){ 2 // Autohide header 3 var hiddenClass = 'header-hidden'; 4 var header = $('#header') 5 var lastY; 6 7 $(window).bind('touchmove scroll', function (e){ 8 var currentY = $(window).scrollTop();; 9 10 if( currentY > lastY && currentY > 100 ){ 11 // moved down 12 header.addClass( hiddenClass ); 13 } else if( currentY < lastY ){ 14 // moved up 15 header.removeClass( hiddenClass ); 16 } 17 lastY = currentY; 18 }); 19 20 // Carousel 21 if( $('.bxslider').children().length > 1){ 22 23 $('.bxslider').bxSlider({ 24 mode: 'horizontal', 25 slideMargin: 10, 26 pagerCustom: '#bx-pager', 27 captions: true, 28 controls: false, 29 responsive: true, 30 useCSS: false, 31 auto: true, 32 }); 33 } 34 35 var sliderArray = new Array(); 36 function initMediaSliders(){ 37 $('.media-slider').each( function(){ 38 sliderArray.push($(this).bxSlider({ 39 mode: 'horizontal', 40 slideMargin: 10, 41 captions: true, 42 responsive: true, 43 useCSS: false, 44 auto: false, 45 pager: false, 46 nextText: ' ', 47 prevText: ' ' 48 })); 49 }); 50 } 51 52 initMediaSliders(); 53 // Media Gallery section 54 $('.link-list li').eq(0).addClass('active'); 55 $('.media-gallery .slider').not('.media-gallery .slider:first-child').hide(); 56 57 $('.link-list a').click(function(){ 58 if(!$(this).parent('li').hasClass('active')){ 59 // Get height 60 $('.slider').css("height", $('.timeline-detail').height() + 'px' ); 61 62 $('.link-list li').removeClass('active'); 63 $(this).parent('li').addClass('active'); 64 65 var index = $(this).data('tab'); 66 // Make disappear 67 $('.media-gallery .slider').not($('.tab-' + index)).css('position','absolute').fadeOut('slow',function(){ 68 $('.tab-' + index).addClass('active').fadeIn('slow',function(){ 69 $('.media-gallery .slider').css('height','auto'); 70 $('.media-slider').each(function(){ 71 $.each(sliderArray, function(index, value){ 72 value.reloadSlider(); 73 }); 74 }); 75 }); 76 }); 77 } 78 return false; 79 }); 80 81 // Generic load more 82 $('.load-more').click( function(){ 83 84 // Set up items 85 button = $(this).addClass('active'); 86 containerId = '#' + $(this).data('target'); 87 container = $(containerId); 88 89 // Increment the page 90 amount = container.attr('data-amount'); 91 page = parseInt(container.attr('data-page')) + 1; 92 container.attr('data-page', page); 93 94 // Query 95 queryString = 'ajax=1&paged=' + page; 96 if($('.filter-form') && $('.filter-form').serialize() != ''){ 97 queryString = queryString + '&' + $('.filter-form').serialize(); 98 } 99 100 // Ajax call 101 $.get( '', queryString , function(data){ 102 103 // Append data 104 newData = $(data).find(containerId + ' > div'); 105 newData.hide().fadeIn(1000).css('display','inline-block'); 106 newData.appendTo( container ); 107 initSameHeight(); 108 // Append data 109 button.removeClass('active'); 110 if(newData.length < amount){ 111 button.fadeOut(500); 112 } 113 114 }); 115 return false; 116 }); 117 118 // Toggle the map 119 $('.show-map').click( function(){ 120 $(this).toggleClass('active'); 121 $(".acf-map").toggle(); 122 google.maps.event.trigger( map, 'resize' ); 123 map.setZoom( map.getZoom() ); 124 center_map( map ); 125 126 return false; 127 }); 128 129 // Find all iframes 130 var $iframes = $( "#content iframe" ); 131 132 // Find & save the aspect ratio for all iframes 133 $iframes.each(function () { 134 $( this ).data( "ratio", this.height / this.width ) 135 // Remove the hardcoded width & height attributes 136 .removeAttr( "width" ) 137 .removeAttr( "height" ); 138 }); 139 140 // Resize the iframes when the window is resized 141 $( window ).resize( function () { 142 $iframes.each( function() { 143 // Get the parent container's width 144 var width = $( this ).parent().width(); 145 $( this ).width( width ) 146 .height( width * $( this ).data( "ratio" ) ); 147 }); 148 // Resize to fix all iframes on page load. 149 }).resize(); 150 151 /* 152 * new_map 153 * 154 * This function will render a Google Map onto the selected jQuery element 155 * 156 * @type function 157 * @date 8/11/2013 158 * @since 4.3.0 159 * 160 * @param $el (jQuery element) 161 * @return n/a 162 */ 163 function new_map( $el ) { 164 // var 165 var $markers = $el.find('.marker'); 166 // vars 167 var args = { 168 zoom : 16, 169 center : new google.maps.LatLng(0, 0), 170 mapTypeId : google.maps.MapTypeId.ROADMAP, 171 scrollwheel : false, 172 }; 173 174 // create map 175 var map = new google.maps.Map( $el[0], args); 176 // add a markers reference 177 map.markers = []; 178 // add markers 179 $markers.each(function(){ 180 add_marker( $(this), map ); 181 }); 182 // center map 183 center_map( map ); 184 // return 185 return map; 186 } 187 188 189 /* 190 * add_marker 191 * 192 * This function will add a marker to the selected Google Map 193 * 194 * @type function 195 * @date 8/11/2013 196 * @since 4.3.0 197 * 198 * @param $marker (jQuery element) 199 * @param map (Google Map object) 200 * @return n/a 201 */ 202 203 function add_marker( $marker, map ) { 204 205 // var 206 var latlng = new google.maps.LatLng( $marker.attr('data-lat'), $marker.attr('data-lng') ); 207 208 // create marker 209 var marker = new google.maps.Marker({ 210 position : latlng, 211 map : map 212 }); 213 214 // add to array 215 map.markers.push( marker ); 216 217 // if marker contains HTML, add it to an infoWindow 218 if( $marker.html() ) 219 {
220 // create info window 221 var infowindow = new google.maps.InfoWindow({ 222 content : $marker.html() 223 }); 224 225 // show info window when marker is clicked 226 google.maps.event.addListener(marker, 'click', function() { 227 228 infowindow.open( map, marker ); 229 230 }); 231 } 232 233 } 234 /* 235 * center_map 236 * 237 * This function will center the map, showing all markers attached to this map 238 * 239 * @type function 240 * @date 8/11/2013 241 * @since 4.3.0 242 * 243 * @param map (Google Map object) 244 * @return n/a 245 */ 246 function center_map( map ) { 247 // vars 248 var bounds = new google.maps.LatLngBounds(); 249 250 // loop through all markers and create bounds 251 $.each( map.markers, function( i, marker ){ 252 253 var latlng = new google.maps.LatLng( marker.position.lat(), marker.position.lng() ); 254 255 bounds.extend( latlng ); 256 257 }); 258 259 // only 1 marker? 260 if( map.markers.length == 1 ) 261 { 262 // set center of map 263 map.setCenter( bounds.getCenter() ); 264 map.setZoom( 16 ); 265 } 266 else 267 { 268 // fit to bounds 269 map.fitBounds( bounds ); 270 } 271 272 } 273 274 $('.acf-map').each(function(){ 275 // create map 276 map = new_map( $(this) ); 277 }); 278}); 279 280// page init 281jQuery(function(){ 282 initCustomForms(); 283 initTouchNav(); 284 initMobileNav(); 285 initSameHeight();
286 initDropDownClasses(); 287 initRetinaCover(); 288}); 289 290// initialize custom form elements 291function initCustomForms() { 292 jcf.setOptions('Select', { 293 wrapNative: false, 294 wrapNativeOnMobile: false 295 }); 296 jcf.replaceAll(); 297} 298 299 300 301function initRetinaCover() { 302 jQuery('.bg-stretch').retinaCover(); 303} 304 305 306// mobile menu init 307function initMobileNav() { 308 jQuery('body').mobileNav({ 309 hideOnClickOutside: true, 310 menuActiveClass: 'nav-active', 311 menuOpener: '.nav-opener', 312 menuDrop: '.nav-drop' 313 }); 314 jQuery('body').mobileNav({ 315 hideOnClickOutside: true, 316 menuActiveClass: 'link-active', 317 menuOpener: '.link-opener', 318 menuDrop: '.link-drop' 319 }); 320 jQuery('.filter').mobileNav({ 321 hideOnClickOutside: false, 322 menuActiveClass: 'filter-active', 323 menuOpener: '.filter-opener', 324 menuDrop: '.filter-drop' 325 }); 326} 327 328// align blocks height 329function initSameHeight() { 330 jQuery('.row').sameHeight({ 331 elements: '.person-block', 332 flexible: true, 333 multiLine: true 334 }); 335 jQuery('.row').sameHeight({ 336 elements: '.stock a', 337 flexible: true, 338 multiLine: true 339 }); 340 jQuery('.row').sameHeight({ 341 elements: '.item-block a .text', 342 flexible: true, 343 multiLine: true 344 }); 345 jQuery('.row').sameHeight({ 346 elements: '.calendar', 347 flexible: true, 348 multiLine: true 349 }); 350 // jQuery('.row').sameHeight({ 351 // elements: '.event a', 352 // flexible: true, 353 // multiLine: true 354 // }); 355 jQuery('.twitter-feeds').sameHeight({ 356 elements: '.twitter-feed .img', 357 flexible: true, 358 multiLine: true 359 }); 360 jQuery('.text-area').sameHeight({ 361 elements: '.article .news-title', 362 flexible: true, 363 multiLine: true, 364 biggestHeight: true 365 }); 366 jQuery('.text-area').sameHeight({ 367 elements: '.col', 368 flexible: true, 369 multiLine: true 370 }); 371 jQuery('.section.blue .row').sameHeight({ 372 elements: '.col-4', 373 flexible: true, 374 multiLine: true 375 }); 376} 377 378// handle dropdowns on mobile devices 379function initTouchNav() { 380 jQuery('#nav').each(function(){ 381 new TouchNav({ 382 navBlock: this 383 }); 384 }); 385} 386 387// add classes if item has dropdown
388function initDropDownClasses() { 389 jQuery('#nav li').each(function() { 390 var item = jQuery(this); 391 var drop = item.find('ul, form'); 392 var link = item.find('a').eq(0); 393 if(drop.length && !item.hasClass('no-dropdown')) { 394 item.addClass('has-drop-down'); 395 if(link.length) link.addClass('has-drop-down-a'); 396 } 397 }); 398} 399 400/* 401 * Simple Mobile Navigation 402 */ 403 ;(function($) { 404 function MobileNav(options) { 405 this.options = $.extend({ 406 container: null, 407 hideOnClickOutside: false, 408 menuActiveClass: 'nav-active', 409 menuOpener: '.nav-opener', 410 menuDrop: '.nav-drop', 411 toggleEvent: 'click', 412 outsideClickEvent: 'click touchstart pointerdown MSPointerDown' 413 }, options); 414 this.initStructure(); 415 this.attachEvents(); 416 } 417 MobileNav.prototype = { 418 initStructure: function() { 419 this.page = $('html'); 420 this.container = $(this.options.container); 421 this.opener = this.container.find(this.options.menuOpener); 422 this.drop = this.container.find(this.options.menuDrop); 423 }, 424 attachEvents: function() { 425 var self = this; 426 427 if(activateResizeHandler) { 428 activateResizeHandler(); 429 activateResizeHandler = null; 430 } 431 432 this.outsideClickHandler = function(e) { 433 if(self.isOpened()) { 434 var target = $(e.target); 435 if(!target.closest(self.opener).length && !target.closest(self.drop).length) { 436 self.hide(); 437 } 438 } 439 }; 440 441 this.openerClickHandler = function(e) { 442 e.preventDefault(); 443 self.toggle(); 444 }; 445 446 this.opener.on(this.options.toggleEvent, this.openerClickHandler); 447 }, 448 isOpened: function() { 449 return this.container.hasClass(this.options.menuActiveClass); 450 }, 451 show: function() { 452 this.container.addClass(this.options.menuActiveClass); 453 if(this.options.hideOnClickOutside) { 454 this.page.on(this.options.outsideClickEvent, this.outsideClickHandler); 455 } 456 }, 457 hide: function() { 458 this.container.removeClass(this.options.menuActiveClass); 459 if(this.options.hideOnClickOutside) { 460 this.page.off(this.options.outsideClickEvent, this.outsideClickHandler); 461 } 462 }, 463 toggle: function() { 464 if(this.isOpened()) { 465 this.hide(); 466 } else { 467 this.show(); 468 } 469 }, 470 destroy: function() { 471 this.container.removeClass(this.options.menuActiveClass); 472 this.opener.off(this.options.toggleEvent, this.clickHandler); 473 this.page.off(this.options.outsideClickEvent, this.outsideClickHandler); 474 } 475 }; 476 477 var activateResizeHandler = function() { 478 var win = $(window), 479 doc = $('html'), 480 resizeClass = 'resize-active', 481 flag, timer; 482 var removeClassHandler = function() { 483 flag = false; 484 doc.removeClass(resizeClass); 485 }; 486 var resizeHandler = function() { 487 if(!flag) { 488 flag = true; 489 doc.addClass(resizeClass); 490 } 491 clearTimeout(timer); 492 timer = setTimeout(removeClassHandler, 500); 493 }; 494 win.on('resize orientationchange', resizeHandler); 495 }; 496 497 $.fn.mobileNav = function(options) { 498 return this.each(function() { 499 var params = $.extend({}, options, {container: this}), 500 instance = new MobileNav(params); 501 $.data(this, 'MobileNav', instance); 502 }); 503 }; 504 }(jQuery)); 505 506/* 507 * jQuery SameHeight plugin 508 */ 509 ;(function($){ 510 $.fn.sameHeight = function(opt) { 511 var options = $.extend({ 512 skipClass: 'same-height-ignore', 513 leftEdgeClass: 'same-height-left', 514 rightEdgeClass: 'same-height-right', 515 elements: '>*', 516 flexible: false, 517 multiLine: false, 518 useMinHeight: false, 519 biggestHeight: false 520 },opt); 521 return this.each(function(){ 522 var holder = $(this), postResizeTimer, ignoreResize; 523 var elements = holder.find(options.elements).not('.' + options.skipClass); 524 if(!elements.length) return; 525 526 // resize handler 527 function doResize() { 528 elements.css(options.useMinHeight && supportMinHeight ? 'minHeight' : 'height', ''); 529 if(options.multiLine) { 530 // resize elements row by row 531 resizeElementsByRows(elements, options); 532 } else { 533 // resize elements by holder 534 resizeElements(elements, holder, options); 535 } 536 } 537 doResize(); 538 539 // handle flexible layout / font resize 540 var delayedResizeHandler = function() { 541 if(!ignoreResize) { 542 ignoreResize = true; 543 doResize(); 544 clearTimeout(postResizeTimer); 545 postResizeTimer = setTimeout(function() { 546 doResize(); 547 setTimeout(function(){ 548 ignoreResize = false;
549 }, 10); 550 }, 100); 551 } 552 }; 553 554 // handle flexible/responsive layout 555 if(options.flexible) { 556 $(window).bind('resize orientationchange fontresize', delayedResizeHandler); 557 } 558 559 // handle complete page load including images and fonts 560 $(window).bind('load', delayedResizeHandler); 561 }); 562 }; 563 564 // detect css min-height support 565 var supportMinHeight = typeof document.documentElement.style.maxHeight !== 'undefined'; 566 567 // get elements by rows 568 function resizeElementsByRows(boxes, options) { 569 var currentRow = $(), maxHeight, maxCalcHeight = 0, firstOffset = boxes.eq(0).offset().top; 570 boxes.each(function(ind){ 571 var curItem = $(this); 572 if(curItem.offset().top === firstOffset) { 573 currentRow = currentRow.add(this); 574 } else { 575 maxHeight = getMaxHeight(currentRow); 576 maxCalcHeight = Math.max(maxCalcHeight, resizeElements(currentRow, maxHeight, options)); 577 currentRow = curItem; 578 firstOffset = curItem.offset().top; 579 } 580 }); 581 if(currentRow.length) { 582 maxHeight = getMaxHeight(currentRow); 583 maxCalcHeight = Math.max(maxCalcHeight, resizeElements(currentRow, maxHeight, options)); 584 } 585 if(options.biggestHeight) { 586 boxes.css(options.useMinHeight && supportMinHeight ? 'minHeight' : 'height', maxCalcHeight); 587 } 588 } 589 590 // calculate max element height 591 function getMaxHeight(boxes) { 592 var maxHeight = 0; 593 boxes.each(function(){ 594 maxHeight = Math.max(maxHeight, $(this).outerHeight()); 595 }); 596 return maxHeight; 597 } 598 599 // resize helper function 600 function resizeElements(boxes, parent, options) { 601 var calcHeight; 602 var parentHeight = typeof parent === 'number' ? parent : parent.height(); 603 boxes.removeClass(options.leftEdgeClass).removeClass(options.rightEdgeClass).each(function(i){ 604 var element = $(this); 605 var depthDiffHeight = 0; 606 var isBorderBox = element.css('boxSizing') === 'border-box' || element.css('-moz-box-sizing') === 'border-box' || element.css('-webkit-box-sizing') === 'border-box'; 607 608 if(typeof parent !== 'number') { 609 element.parents().each(function(){ 610 var tmpParent = $(this); 611 if(parent.is(this)) { 612 return false; 613 } else { 614 depthDiffHeight += tmpParent.outerHeight() - tmpParent.height(); 615 } 616 }); 617 } 618 calcHeight = parentHeight - depthDiffHeight; 619 calcHeight -= isBorderBox ? 0 : element.outerHeight() - element.height(); 620 621 if(calcHeight > 0) { 622 element.css(options.useMinHeight && supportMinHeight ? 'minHeight' : 'height', calcHeight); 623 } 624 }); 625 boxes.filter(':first').addClass(options.leftEdgeClass); 626 boxes.filter(':last').addClass(options.rightEdgeClass); 627 return calcHeight; 628 } 629}(jQuery)); 630 631/* 632 * jQuery FontResize Event 633 */ 634 jQuery.onFontResize = (function($) { 635 $(function() { 636 var randomID = 'font-resize-frame-' + Math.floor(Math.random() * 1000); 637 var resizeFrame = $('<iframe>').attr('id', randomID).addClass('font-resize-helper'); 638 639 // required styles 640 resizeFrame.css({ 641 width: '100em', 642 height: '10px', 643 position: 'absolute', 644 borderWidth: 0, 645 top: '-9999px', 646 left: '-9999px' 647 }).appendTo('body'); 648 649 // use native IE resize event if possible 650 if (window.attachEvent && !window.addEventListener) { 651 resizeFrame.bind('resize', function () { 652 $.onFontResize.trigger(resizeFrame[0].offsetWidth / 100); 653 }); 654 } 655 // use script inside the iframe to detect resize for other browsers 656 else { 657 var doc = resizeFrame[0].contentWindow.document; 658 doc.open(); 659 doc.write('<scri' + 'pt>window.onload = function(){var em = parent.jQuery("#' + randomID + '")[0];window.onresize = function(){if(parent.jQuery.onFontResize){parent.jQuery.onFontResize.trigger(em.offsetWidth / 100);}}};</scri' + 'pt>'); 660 doc.close(); 661 }
662 jQuery.onFontResize.initialSize = resizeFrame[0].offsetWidth / 100; 663 }); 664 return { 665 // public method, so it can be called from within the iframe 666 trigger: function (em) { 667 $(window).trigger("fontresize", [em]); 668 } 669 }; 670}(jQuery)); 671 672/*! 673 * JavaScript Custom Forms 674 * 675 * Copyright 2014-2015 PSD2HTML - http://psd2html.com/jcf 676 * Released under the MIT license (LICENSE.txt) 677 * 678 * Version: 1.1.3 679 */ 680 ;(function(root, factory) { 681 'use strict'; 682 if (typeof define === 'function' && define.amd) { 683 define(['jquery'], factory); 684 } else if (typeof exports === 'object') { 685 module.exports = factory(require('jquery')); 686 } else { 687 root.jcf = factory(jQuery); 688 } 689 }(this, function($) { 690 'use strict'; 691 692 // define version 693 var version = '1.1.3'; 694 695 // private variables 696 var customInstances = []; 697 698 // default global options 699 var commonOptions = { 700 optionsKey: 'jcf', 701 dataKey: 'jcf-instance', 702 rtlClass: 'jcf-rtl', 703 focusClass: 'jcf-focus', 704 pressedClass: 'jcf-pressed', 705 disabledClass: 'jcf-disabled', 706 hiddenClass: 'jcf-hidden', 707 resetAppearanceClass: 'jcf-reset-appearance', 708 unselectableClass: 'jcf-unselectable' 709 }; 710 711 // detect device type 712 var isTouchDevice = ('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch, 713 isWinPhoneDevice = /Windows Phone/.test(navigator.userAgent); 714 commonOptions.isMobileDevice = !!(isTouchDevice || isWinPhoneDevice); 715 716 // create global stylesheet if custom forms are used 717 var createStyleSheet = function() { 718 var styleTag = $('<style>').appendTo('head'), 719 styleSheet = styleTag.prop('sheet') || styleTag.prop('styleSheet'); 720 721 // crossbrowser style handling 722 var addCSSRule = function(selector, rules, index) { 723 if( typeof index == 'undefined' ) index = 0; 724 725 if (styleSheet.insertRule) { 726 styleSheet.insertRule(selector + '{' + rules + '}', index); 727 } else { 728 styleSheet.addRule(selector, rules, index); 729 } 730 }; 731 732 // add special rules 733 addCSSRule('.' + commonOptions.hiddenClass, 'position:absolute !important;left:-9999px !important;height:1px !important;width:1px !important;margin:0 !important;border-width:0 !important;-webkit-appearance:none;-moz-appearance:none;appearance:none'); 734 addCSSRule('.' + commonOptions.rtlClass + ' .' + commonOptions.hiddenClass, 'right:-9999px !important; left: auto !important'); 735 addCSSRule('.' + commonOptions.unselectableClass, '-webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; -webkit-tap-highlight-color: rgba(0,0,0,0);'); 736 addCSSRule('.' + commonOptions.resetAppearanceClass, 'background: none; border: none; -webkit-appearance: none; appearance: none; opacity: 0; filter: alpha(opacity=0);'); 737 738 // detect rtl pages 739 var html = $('html'), body = $('body'); 740 if (html.css('direction') === 'rtl' || body.css('direction') === 'rtl') { 741 html.addClass(commonOptions.rtlClass); 742 } 743 744 // handle form reset event 745 html.on('reset', function() { 746 setTimeout(function() { 747 api.refreshAll(); 748 }, 0); 749 }); 750 751 // mark stylesheet as created 752 commonOptions.styleSheetCreated = true; 753 }; 754 755 // simplified pointer events handler 756 (function() { 757 var pointerEventsSupported = navigator.pointerEnabled || navigator.msPointerEnabled, 758 touchEventsSupported = ('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch, 759 eventList, eventMap = {}, eventPrefix = 'jcf-'; 760 761 // detect events to attach 762 if (pointerEventsSupported) { 763 eventList = { 764 pointerover: navigator.pointerEnabled ? 'pointerover' : 'MSPointerOver', 765 pointerdown: navigator.pointerEnabled ? 'pointerdown' : 'MSPointerDown', 766 pointermove: navigator.pointerEnabled ? 'pointermove' : 'MSPointerMove', 767 pointerup: navigator.pointerEnabled ? 'pointerup' : 'MSPointerUp' 768 }; 769 } else { 770 eventList = { 771 pointerover: 'mouseover', 772 pointerdown: 'mousedown' + (touchEventsSupported ? ' touchstart' : ''), 773 pointermove: 'mousemove' + (touchEventsSupported ? ' touchmove' : ''), 774 pointerup: 'mouseup' + (touchEventsSupported ? ' touchend' : '') 775 }; 776 } 777 778 // create event map 779 $.each(eventList, function(targetEventName, fakeEventList) { 780 $.each(fakeEventList.split(' '), function(index, fakeEventName) { 781 eventMap[fakeEventName] = targetEventName; 782 }); 783 }); 784 785 // jQuery event hooks 786 $.each(eventList, function(eventName, eventHandlers) { 787 eventHandlers = eventHandlers.split(' '); 788 $.event.special[eventPrefix + eventName] = { 789 setup: function() { 790 var self = this; 791 $.each(eventHandlers, function(index, fallbackEvent) { 792 if (self.addEventListener) self.addEventListener(fallbackEvent, fixEvent, false); 793 else self['on' + fallbackEvent] = fixEvent; 794 }); 795 }, 796 teardown: function() { 797 var self = this; 798 $.each(eventHandlers, function(index, fallbackEvent) { 799 if (self.addEventListener) self.removeEventListener(fallbackEvent, fixEvent, false); 800 else self['on' + fallbackEvent] = null; 801 }); 802 } 803 }; 804 }); 805 806 // check that mouse event are not simulated by mobile browsers 807 var lastTouch = null; 808 var mouseEventSimulated = function(e) { 809 var dx = Math.abs(e.pageX - lastTouch.x), 810 dy = Math.abs(e.pageY - lastTouch.y), 811 rangeDistance = 25; 812 813 if (dx <= rangeDistance && dy <= rangeDistance) { 814 return true; 815 } 816 }; 817 818 // normalize event 819 var fixEvent = function(e) { 820 var origEvent = e || window.event, 821 touchEventData = null, 822 targetEventName = eventMap[origEvent.type]; 823 824 e = $.event.fix(origEvent); 825 e.type = eventPrefix + targetEventName; 826 827 if (origEvent.pointerType) { 828 switch (origEvent.pointerType) { 829 case 2: e.pointerType = 'touch'; break; 830 case 3: e.pointerType = 'pen'; break; 831 case 4: e.pointerType = 'mouse'; break; 832 default: e.pointerType = origEvent.pointerType; 833 } 834 } else { 835 e.pointerType = origEvent.type.substr(0, 5); // "mouse" or "touch" word length 836 } 837 838 if (!e.pageX && !e.pageY) { 839 touchEventData = origEvent.changedTouches ? origEvent.changedTouches[0] : origEvent; 840 e.pageX = touchEventData.pageX; 841 e.pageY = touchEventData.pageY; 842 } 843 844 if (origEvent.type === 'touchend') { 845 lastTouch = { x: e.pageX, y: e.pageY }; 846 } 847 if (e.pointerType === 'mouse' && lastTouch && mouseEventSimulated(e)) { 848 return; 849 } else { 850 return ($.event.dispatch || $.event.handle).call(this, e); 851 } 852 }; 853 }()); 854 855 // custom mousewheel/trackpad handler 856 (function() { 857 var wheelEvents = ('onwheel' in document || document.documentMode >= 9 ? 'wheel' : 'mousewheel DOMMouseScroll').split(' '), 858 shimEventName = 'jcf-mousewheel'; 859 860 $.event.special[shimEventName] = { 861 setup: function() { 862 var self = this; 863 $.each(wheelEvents, function(index, fallbackEvent) { 864 if (self.addEventListener) self.addEventListener(fallbackEvent, fixEvent, false); 865 else self['on' + fallbackEvent] = fixEvent; 866 }); 867 }, 868 teardown: function() { 869 var self = this; 870 $.each(wheelEvents, function(index, fallbackEvent) { 871 if (self.addEventListener) self.removeEventListener(fallbackEvent, fixEvent, false); 872 else self['on' + fallbackEvent] = null; 873 }); 874 } 875 }; 876 877 var fixEvent = function(e) { 878 var origEvent = e || window.event; 879 e = $.event.fix(origEvent); 880 e.type = shimEventName; 881 882 // old wheel events handler 883 if ('detail' in origEvent) { e.deltaY = -origEvent.detail; } 884 if ('wheelDelta' in origEvent) { e.deltaY = -origEvent.wheelDelta; } 885 if ('wheelDeltaY' in origEvent) { e.deltaY = -origEvent.wheelDeltaY; } 886 if ('wheelDeltaX' in origEvent) { e.deltaX = -origEvent.wheelDeltaX; } 887 888 // modern wheel event handler 889 if ('deltaY' in origEvent) { 890 e.deltaY = origEvent.deltaY; 891 } 892 if ('deltaX' in origEvent) { 893 e.deltaX = origEvent.deltaX; 894 } 895 896 // handle deltaMode for mouse wheel 897 e.delta = e.deltaY || e.deltaX; 898 if (origEvent.deltaMode === 1) { 899 var lineHeight = 16; 900 e.delta *= lineHeight; 901 e.deltaY *= lineHeight; 902 e.deltaX *= lineHeight; 903 } 904 905 return ($.event.dispatch || $.event.handle).call(this, e); 906 }; 907 }()); 908 909 // extra module methods 910 var moduleMixin = { 911 // provide function for firing native events 912 fireNativeEvent: function(elements, eventName) { 913 $(elements).each(function() { 914 var element = this, eventObject; 915 if (element.dispatchEvent) { 916 eventObject = document.createEvent('HTMLEvents'); 917 eventObject.initEvent(eventName, true, true); 918 element.dispatchEvent(eventObject); 919 } else if (document.createEventObject) { 920 eventObject = document.createEventObject(); 921 eventObject.target = element; 922 element.fireEvent('on' + eventName, eventObject); 923 } 924 }); 925 }, 926 // bind event handlers for module instance (functions beggining with "on") 927 bindHandlers: function() { 928 var self = this; 929 $.each(self, function(propName, propValue) { 930 if (propName.indexOf('on') === 0 && $.isFunction(propValue)) { 931 // dont use $.proxy here because it doesn't create unique handler 932 self[propName] = function() { 933 return propValue.apply(self, arguments); 934 }; 935 } 936 }); 937 } 938 }; 939 940 // public API 941 var api = { 942 version: version, 943 modules: {}, 944 getOptions: function() { 945 return $.extend({}, commonOptions); 946 }, 947 setOptions: function(moduleName, moduleOptions) { 948 if (arguments.length > 1) { 949 // set module options 950 if (this.modules[moduleName]) { 951 $.extend(this.modules[moduleName].prototype.options, moduleOptions); 952 } 953 } else { 954 // set common options 955 $.extend(commonOptions, moduleName); 956 } 957 }, 958 addModule: function(proto) { 959 // add module to list 960 var Module = function(options) { 961 // save instance to collection 962 if (!options.element.data(commonOptions.dataKey)) { 963 options.element.data(commonOptions.dataKey, this); 964 } 965 customInstances.push(this); 966 967 // save options 968 this.options = $.extend({}, commonOptions, this.options, getInlineOptions(options.element), options); 969 970 // bind event handlers to instance 971 this.bindHandlers(); 972 973 // call constructor 974 this.init.apply(this, arguments); 975 }; 976 977 // parse options from HTML attribute 978 var getInlineOptions = function(element) { 979 var dataOptions = element.data(commonOptions.optionsKey), 980 attrOptions = element.attr(commonOptions.optionsKey); 981 982 if (dataOptions) { 983 return dataOptions; 984 } else if (attrOptions) { 985 try { 986 return $.parseJSON(attrOptions); 987 } catch (e) { 988 // ignore invalid attributes 989 } 990 } 991 }; 992 993 // set proto as prototype for new module 994 Module.prototype = proto; 995 996 // add mixin methods to module proto 997 $.extend(proto, moduleMixin); 998 if (proto.plugins) { 999 $.each(proto.plugins, function(pluginName, plugin) { 1000 $.extend(plugin.prototype, moduleMixin); 1001 }); 1002 } 1003 1004 // override destroy method 1005 var originalDestroy = Module.prototype.destroy; 1006 Module.prototype.destroy = function() { 1007 this.options.element.removeData(this.options.dataKey); 1008 1009 for (var i = customInstances.length - 1; i >= 0; i--) { 1010 if (customInstances[i] === this) { 1011 customInstances.splice(i, 1); 1012 break; 1013 } 1014 } 1015 1016 if (originalDestroy) { 1017 originalDestroy.apply(this, arguments); 1018 } 1019 }; 1020 1021 // save module to list 1022 this.modules[proto.name] = Module; 1023 }, 1024 getInstance: function(element) { 1025 return $(element).data(commonOptions.dataKey); 1026 }, 1027 replace: function(elements, moduleName, customOptions) { 1028 var self = this, 1029 instance; 1030 1031 if (!commonOptions.styleSheetCreated) { 1032 createStyleSheet(); 1033 } 1034 1035 $(elements).each(function() { 1036 var moduleOptions, 1037 element = $(this); 1038 1039 instance = element.data(commonOptions.dataKey); 1040 if (instance) { 1041 instance.refresh(); 1042 } else { 1043 if (!moduleName) { 1044 $.each(self.modules, function(currentModuleName, module) { 1045 if (module.prototype.matchElement.call(module.prototype, element)) { 1046 moduleName = currentModuleName; 1047 return false;
1048 } 1049 }); 1050 } 1051 if (moduleName) { 1052 moduleOptions = $.extend({ element: element }, customOptions); 1053 instance = new self.modules[moduleName](moduleOptions); 1054 } 1055 } 1056 }); 1057 return instance; 1058 }, 1059 refresh: function(elements) { 1060 $(elements).each(function() { 1061 var instance = $(this).data(commonOptions.dataKey); 1062 if (instance) { 1063 instance.refresh(); 1064 } 1065 }); 1066 }, 1067 destroy: function(elements) { 1068 $(elements).each(function() { 1069 var instance = $(this).data(commonOptions.dataKey); 1070 if (instance) { 1071 instance.destroy(); 1072 } 1073 }); 1074 }, 1075 replaceAll: function(context) { 1076 var self = this; 1077 $.each(this.modules, function(moduleName, module) { 1078 $(module.prototype.selector, context).each(function() { 1079 if (this.className.indexOf('jcf-ignore') < 0) { 1080 self.replace(this, moduleName); 1081 } 1082 }); 1083 }); 1084 }, 1085 refreshAll: function(context) { 1086 if (context) { 1087 $.each(this.modules, function(moduleName, module) { 1088 $(module.prototype.selector, context).each(function() { 1089 var instance = $(this).data(commonOptions.dataKey); 1090 if (instance) { 1091 instance.refresh(); 1092 } 1093 }); 1094 }); 1095 } else { 1096 for (var i = customInstances.length - 1; i >= 0; i--) { 1097 customInstances[i].refresh(); 1098 } 1099 } 1100 }, 1101 destroyAll: function(context) { 1102 if (context) { 1103 $.each(this.modules, function(moduleName, module) { 1104 $(module.prototype.selector, context).each(function(index, element) { 1105 var instance = $(element).data(commonOptions.dataKey); 1106 if (instance) { 1107 instance.destroy(); 1108 } 1109 }); 1110 }); 1111 } else { 1112 while (customInstances.length) { 1113 customInstances[0].destroy(); 1114 } 1115 } 1116 } 1117 }; 1118 1119 // always export API to the global window object 1120 window.jcf = api; 1121 1122 return api; 1123})); 1124 1125/*! 1126 * JavaScript Custom Forms : Select Module 1127 * 1128 * Copyright 2014-2015 PSD2HTML - http://psd2html.com/jcf 1129 * Released under the MIT license (LICENSE.txt) 1130 * 1131 * Version: 1.1.3 1132 */ 1133 ;(function($, window) { 1134 'use strict'; 1135 1136 jcf.addModule({ 1137 name: 'Select', 1138 selector: 'select', 1139 options: { 1140 element: null, 1141 multipleCompactStyle: false 1142 }, 1143 plugins: { 1144 ListBox: ListBox, 1145 ComboBox: ComboBox, 1146 SelectList: SelectList 1147 }, 1148 matchElement: function(element) { 1149 return element.is('select'); 1150 }, 1151 init: function() { 1152 this.element = $(this.options.element); 1153 this.createInstance(); 1154 }, 1155 isListBox: function() { 1156 return this.element.is('[size]:not([jcf-size]), [multiple]'); 1157 }, 1158 createInstance: function() { 1159 if (this.instance) { 1160 this.instance.destroy(); 1161 } 1162 if (this.isListBox() && !this.options.multipleCompactStyle) { 1163 this.instance = new ListBox(this.options); 1164 } else { 1165 this.instance = new ComboBox(this.options); 1166 } 1167 }, 1168 refresh: function() { 1169 var typeMismatch = (this.isListBox() && this.instance instanceof ComboBox) || 1170 (!this.isListBox() && this.instance instanceof ListBox); 1171 1172 if (typeMismatch) { 1173 this.createInstance(); 1174 } else { 1175 this.instance.refresh(); 1176 } 1177 }, 1178 destroy: function() { 1179 this.instance.destroy(); 1180 } 1181 }); 1182 1183 // combobox module 1184 function ComboBox(options) { 1185 this.options = $.extend({ 1186 wrapNative: true, 1187 wrapNativeOnMobile: true, 1188 fakeDropInBody: true, 1189 useCustomScroll: true, 1190 flipDropToFit: true, 1191 maxVisibleItems: 10, 1192 fakeAreaStructure: '<span class="jcf-select"><span class="jcf-select-text"></span><span class="jcf-select-opener"></span></span>', 1193 fakeDropStructure: '<div class="jcf-select-drop"><div class="jcf-select-drop-content"></div></div>', 1194 optionClassPrefix: 'jcf-option-', 1195 selectClassPrefix: 'jcf-select-', 1196 dropContentSelector: '.jcf-select-drop-content', 1197 selectTextSelector: '.jcf-select-text', 1198 dropActiveClass: 'jcf-drop-active', 1199 flipDropClass: 'jcf-drop-flipped' 1200 }, options); 1201 this.init(); 1202 } 1203 $.extend(ComboBox.prototype, { 1204 init: function() { 1205 this.initStructure(); 1206 this.bindHandlers(); 1207 this.attachEvents(); 1208 this.refresh(); 1209 }, 1210 initStructure: function() { 1211 // prepare structure 1212 this.win = $(window); 1213 this.doc = $(document); 1214 this.realElement = $(this.options.element); 1215 this.fakeElement = $(this.options.fakeAreaStructure).insertAfter(this.realElement); 1216 this.selectTextContainer = this.fakeElement.find(this.options.selectTextSelector); 1217 this.selectText = $('<span></span>').appendTo(this.selectTextContainer); 1218 makeUnselectable(this.fakeElement); 1219 1220 // copy classes from original select
1221 this.fakeElement.addClass(getPrefixedClasses(this.realElement.prop('className'), this.options.selectClassPrefix)); 1222 1223 // handle compact multiple style 1224 if (this.realElement.prop('multiple')) { 1225 this.fakeElement.addClass('jcf-compact-multiple'); 1226 } 1227 1228 // detect device type and dropdown behavior 1229 if (this.options.isMobileDevice && this.options.wrapNativeOnMobile && !this.options.wrapNative) { 1230 this.options.wrapNative = true; 1231 } 1232 1233 if (this.options.wrapNative) { 1234 // wrap native select inside fake block 1235 this.realElement.prependTo(this.fakeElement).css({ 1236 position: 'absolute', 1237 height: '100%', 1238 width: '100%' 1239 }).addClass(this.options.resetAppearanceClass); 1240 } else { 1241 // just hide native select 1242 this.realElement.addClass(this.options.hiddenClass); 1243 this.fakeElement.attr('title', this.realElement.attr('title')); 1244 this.fakeDropTarget = this.options.fakeDropInBody ? $('body') : this.fakeElement; 1245 } 1246 }, 1247 attachEvents: function() { 1248 // delayed refresh handler 1249 var self = this; 1250 this.delayedRefresh = function() { 1251 setTimeout(function() { 1252 self.refresh(); 1253 if (self.list) { 1254 self.list.refresh(); 1255 self.list.scrollToActiveOption(); 1256 } 1257 }, 1); 1258 }; 1259 1260 // native dropdown event handlers 1261 if (this.options.wrapNative) { 1262 this.realElement.on({ 1263 focus: this.onFocus, 1264 change: this.onChange, 1265 click: this.onChange, 1266 keydown: this.onChange 1267 }); 1268 } else { 1269 // custom dropdown event handlers 1270 this.realElement.on({ 1271 focus: this.onFocus, 1272 change: this.onChange, 1273 keydown: this.onKeyDown 1274 }); 1275 this.fakeElement.on({ 1276 'jcf-pointerdown': this.onSelectAreaPress 1277 }); 1278 } 1279 }, 1280 onKeyDown: function(e) { 1281 if (e.which === 13) { 1282 this.toggleDropdown(); 1283 } else if (this.dropActive) { 1284 this.delayedRefresh(); 1285 } 1286 }, 1287 onChange: function() { 1288 this.refresh(); 1289 }, 1290 onFocus: function() { 1291 if (!this.pressedFlag || !this.focusedFlag) { 1292 this.fakeElement.addClass(this.options.focusClass); 1293 this.realElement.on('blur', this.onBlur); 1294 this.toggleListMode(true); 1295 this.focusedFlag = true; 1296 } 1297 }, 1298 onBlur: function() { 1299 if (!this.pressedFlag) { 1300 this.fakeElement.removeClass(this.options.focusClass); 1301 this.realElement.off('blur', this.onBlur); 1302 this.toggleListMode(false); 1303 this.focusedFlag = false; 1304 } 1305 }, 1306 onResize: function() { 1307 if (this.dropActive) { 1308 this.hideDropdown(); 1309 } 1310 }, 1311 onSelectDropPress: function() { 1312 this.pressedFlag = true; 1313 }, 1314 onSelectDropRelease: function(e, pointerEvent) { 1315 this.pressedFlag = false; 1316 if (pointerEvent.pointerType === 'mouse') { 1317 this.realElement.focus(); 1318 } 1319 }, 1320 onSelectAreaPress: function(e) { 1321 // skip click if drop inside fake element or real select is disabled 1322 var dropClickedInsideFakeElement = !this.options.fakeDropInBody && $(e.target).closest(this.dropdown).length; 1323 if (dropClickedInsideFakeElement || e.button > 1 || this.realElement.is(':disabled')) { 1324 return; 1325 } 1326 1327 // toggle dropdown visibility 1328 this.selectOpenedByEvent = e.pointerType; 1329 this.toggleDropdown(); 1330 1331 // misc handlers 1332 if (!this.focusedFlag) { 1333 if (e.pointerType === 'mouse') { 1334 this.realElement.focus(); 1335 } else { 1336 this.onFocus(e); 1337 } 1338 } 1339 this.pressedFlag = true; 1340 this.fakeElement.addClass(this.options.pressedClass); 1341 this.doc.on('jcf-pointerup', this.onSelectAreaRelease); 1342 }, 1343 onSelectAreaRelease: function(e) { 1344 if (this.focusedFlag && e.pointerType === 'mouse') { 1345 this.realElement.focus(); 1346 } 1347 this.pressedFlag = false; 1348 this.fakeElement.removeClass(this.options.pressedClass); 1349 this.doc.off('jcf-pointerup', this.onSelectAreaRelease); 1350 }, 1351 onOutsideClick: function(e) { 1352 var target = $(e.target), 1353 clickedInsideSelect = target.closest(this.fakeElement).length || target.closest(this.dropdown).length; 1354 1355 if (!clickedInsideSelect) { 1356 this.hideDropdown(); 1357 } 1358 }, 1359 onSelect: function() { 1360 this.refresh(); 1361 1362 if (this.realElement.prop('multiple')) { 1363 this.repositionDropdown(); 1364 } else { 1365 this.hideDropdown(); 1366 } 1367 1368 this.fireNativeEvent(this.realElement, 'change'); 1369 }, 1370 toggleListMode: function(state) { 1371 if (!this.options.wrapNative) { 1372 if (state) { 1373 // temporary change select to list to avoid appearing of native dropdown 1374 this.realElement.attr({ 1375 size: 4, 1376 'jcf-size': '' 1377 }); 1378 } else { 1379 // restore select from list mode to dropdown select 1380 if (!this.options.wrapNative) { 1381 this.realElement.removeAttr('size jcf-size'); 1382 } 1383 } 1384 } 1385 }, 1386 createDropdown: function() { 1387 // destroy previous dropdown if needed 1388 if (this.dropdown) { 1389 this.list.destroy(); 1390 this.dropdown.remove(); 1391 } 1392 1393 // create new drop container 1394 this.dropdown = $(this.options.fakeDropStructure).appendTo(this.fakeDropTarget);
1395 this.dropdown.addClass(getPrefixedClasses(this.realElement.prop('className'), this.options.selectClassPrefix)); 1396 makeUnselectable(this.dropdown); 1397 1398 // handle compact multiple style 1399 if (this.realElement.prop('multiple')) { 1400 this.dropdown.addClass('jcf-compact-multiple'); 1401 } 1402 1403 // set initial styles for dropdown in body 1404 if (this.options.fakeDropInBody) { 1405 this.dropdown.css({ 1406 position: 'absolute', 1407 top: -9999 1408 }); 1409 } 1410 1411 // create new select list instance 1412 this.list = new SelectList({ 1413 useHoverClass: true, 1414 handleResize: false, 1415 alwaysPreventMouseWheel: true, 1416 maxVisibleItems: this.options.maxVisibleItems, 1417 useCustomScroll: this.options.useCustomScroll, 1418 holder: this.dropdown.find(this.options.dropContentSelector), 1419 multipleSelectWithoutKey: this.realElement.prop('multiple'), 1420 element: this.realElement 1421 }); 1422 $(this.list).on({ 1423 select: this.onSelect, 1424 press: this.onSelectDropPress, 1425 release: this.onSelectDropRelease 1426 }); 1427 }, 1428 repositionDropdown: function() { 1429 var selectOffset = this.fakeElement.offset(), 1430 selectWidth = this.fakeElement.outerWidth(), 1431 selectHeight = this.fakeElement.outerHeight(), 1432 dropHeight = this.dropdown.css('width', selectWidth).outerHeight(), 1433 winScrollTop = this.win.scrollTop(), 1434 winHeight = this.win.height(), 1435 calcTop, calcLeft, bodyOffset, needFlipDrop = false; 1436 1437 // check flip drop position 1438 if (selectOffset.top + selectHeight + dropHeight > winScrollTop + winHeight && selectOffset.top - dropHeight > winScrollTop) { 1439 needFlipDrop = true; 1440 } 1441 1442 if (this.options.fakeDropInBody) { 1443 bodyOffset = this.fakeDropTarget.css('position') !== 'static' ? this.fakeDropTarget.offset().top : 0; 1444 if (this.options.flipDropToFit && needFlipDrop) { 1445 // calculate flipped dropdown position 1446 calcLeft = selectOffset.left; 1447 calcTop = selectOffset.top - dropHeight - bodyOffset; 1448 } else { 1449 // calculate default drop position 1450 calcLeft = selectOffset.left; 1451 calcTop = selectOffset.top + selectHeight - bodyOffset; 1452 } 1453 1454 // update drop styles 1455 this.dropdown.css({ 1456 width: selectWidth, 1457 left: calcLeft, 1458 top: calcTop 1459 }); 1460 } 1461 1462 // refresh flipped class 1463 this.dropdown.add(this.fakeElement).toggleClass(this.options.flipDropClass, this.options.flipDropToFit && needFlipDrop); 1464 }, 1465 showDropdown: function() { 1466 // do not show empty custom dropdown 1467 if (!this.realElement.prop('options').length) { 1468 return; 1469 } 1470 1471 // create options list if not created 1472 if (!this.dropdown) { 1473 this.createDropdown(); 1474 } 1475 1476 // show dropdown 1477 this.dropActive = true; 1478 this.dropdown.appendTo(this.fakeDropTarget); 1479 this.fakeElement.addClass(this.options.dropActiveClass); 1480 this.refreshSelectedText(); 1481 this.repositionDropdown(); 1482 this.list.setScrollTop(this.savedScrollTop); 1483 this.list.refresh(); 1484 1485 // add temporary event handlers 1486 this.win.on('resize', this.onResize); 1487 this.doc.on('jcf-pointerdown', this.onOutsideClick); 1488 }, 1489 hideDropdown: function() { 1490 if (this.dropdown) { 1491 this.savedScrollTop = this.list.getScrollTop(); 1492 this.fakeElement.removeClass(this.options.dropActiveClass + ' ' + this.options.flipDropClass); 1493 this.dropdown.removeClass(this.options.flipDropClass).detach(); 1494 this.doc.off('jcf-pointerdown', this.onOutsideClick); 1495 this.win.off('resize', this.onResize); 1496 this.dropActive = false; 1497 if (this.selectOpenedByEvent === 'touch') { 1498 this.onBlur(); 1499 } 1500 } 1501 }, 1502 toggleDropdown: function() { 1503 if (this.dropActive) { 1504 this.hideDropdown(); 1505 } else { 1506 this.showDropdown(); 1507 } 1508 }, 1509 refreshSelectedText: function() { 1510 // redraw selected area 1511 var selectedIndex = this.realElement.prop('selectedIndex'), 1512 selectedOption = this.realElement.prop('options')[selectedIndex], 1513 selectedOptionImage = selectedOption ? selectedOption.getAttribute('data-image') : null, 1514 selectedOptionText = '', 1515 selectedOptionClasses, 1516 self = this; 1517 1518 if (this.realElement.prop('multiple')) { 1519 $.each(this.realElement.prop('options'), function(index, option) { 1520 if (option.selected) {
1521 selectedOptionText += (selectedOptionText ? ', ' : '') + option.innerHTML; 1522 } 1523 }); 1524 if (!selectedOptionText) { 1525 selectedOptionText = self.realElement.attr('placeholder') || ''; 1526 } 1527 this.selectText.removeAttr('class').html(selectedOptionText); 1528 } else if (!selectedOption) { 1529 if (this.selectImage) { 1530 this.selectImage.hide(); 1531 } 1532 this.selectText.removeAttr('class').empty(); 1533 } else if (this.currentSelectedText !== selectedOption.innerHTML || this.currentSelectedImage !== selectedOptionImage) { 1534 selectedOptionClasses = getPrefixedClasses(selectedOption.className, this.options.optionClassPrefix); 1535 this.selectText.attr('class', selectedOptionClasses).html(selectedOption.innerHTML); 1536 1537 if (selectedOptionImage) { 1538 if (!this.selectImage) { 1539 this.selectImage = $('<img>').prependTo(this.selectTextContainer).hide(); 1540 } 1541 this.selectImage.attr('src', selectedOptionImage).show(); 1542 } else if (this.selectImage) { 1543 this.selectImage.hide(); 1544 } 1545 1546 this.currentSelectedText = selectedOption.innerHTML; 1547 this.currentSelectedImage = selectedOptionImage; 1548 } 1549 }, 1550 refresh: function() { 1551 // refresh fake select visibility 1552 if (this.realElement.prop('style').display === 'none') { 1553 this.fakeElement.hide(); 1554 } else { 1555 this.fakeElement.show(); 1556 } 1557 1558 // refresh selected text 1559 this.refreshSelectedText(); 1560 1561 // handle disabled state 1562 this.fakeElement.toggleClass(this.options.disabledClass, this.realElement.is(':disabled')); 1563 }, 1564 destroy: function() { 1565 // restore structure 1566 if (this.options.wrapNative) { 1567 this.realElement.insertBefore(this.fakeElement).css({ 1568 position: '', 1569 height: '', 1570 width: '' 1571 }).removeClass(this.options.resetAppearanceClass); 1572 } else { 1573 this.realElement.removeClass(this.options.hiddenClass); 1574 if (this.realElement.is('[jcf-size]')) { 1575 this.realElement.removeAttr('size jcf-size'); 1576 } 1577 } 1578 1579 // removing element will also remove its event handlers 1580 this.fakeElement.remove(); 1581 1582 // remove other event handlers 1583 this.doc.off('jcf-pointerup', this.onSelectAreaRelease); 1584 this.realElement.off({ 1585 focus: this.onFocus 1586 }); 1587 } 1588 }); 1589 1590 // listbox module 1591 function ListBox(options) { 1592 this.options = $.extend({ 1593 wrapNative: true, 1594 useCustomScroll: true, 1595 fakeStructure: '<span class="jcf-list-box"><span class="jcf-list-wrapper"></span></span>', 1596 selectClassPrefix: 'jcf-select-', 1597 listHolder: '.jcf-list-wrapper' 1598 }, options); 1599 this.init(); 1600 } 1601 $.extend(ListBox.prototype, { 1602 init: function() { 1603 this.bindHandlers(); 1604 this.initStructure(); 1605 this.attachEvents(); 1606 }, 1607 initStructure: function() { 1608 this.realElement = $(this.options.element); 1609 this.fakeElement = $(this.options.fakeStructure).insertAfter(this.realElement); 1610 this.listHolder = this.fakeElement.find(this.options.listHolder); 1611 makeUnselectable(this.fakeElement); 1612 1613 // copy classes from original select 1614 this.fakeElement.addClass(getPrefixedClasses(this.realElement.prop('className'), this.options.selectClassPrefix)); 1615 this.realElement.addClass(this.options.hiddenClass); 1616 1617 this.list = new SelectList({ 1618 useCustomScroll: this.options.useCustomScroll, 1619 holder: this.listHolder, 1620 selectOnClick: false, 1621 element: this.realElement 1622 }); 1623 }, 1624 attachEvents: function() { 1625 // delayed refresh handler 1626 var self = this; 1627 this.delayedRefresh = function(e) { 1628 if (e && e.which === 16) { 1629 // ignore SHIFT key 1630 return; 1631 } else { 1632 clearTimeout(self.refreshTimer); 1633 self.refreshTimer = setTimeout(function() { 1634 self.refresh(); 1635 self.list.scrollToActiveOption(); 1636 }, 1); 1637 } 1638 }; 1639 1640 // other event handlers 1641 this.realElement.on({ 1642 focus: this.onFocus, 1643 click: this.delayedRefresh, 1644 keydown: this.delayedRefresh 1645 }); 1646 1647 // select list event handlers 1648 $(this.list).on({ 1649 select: this.onSelect, 1650 press: this.onFakeOptionsPress, 1651 release: this.onFakeOptionsRelease 1652 }); 1653 }, 1654 onFakeOptionsPress: function(e, pointerEvent) { 1655 this.pressedFlag = true; 1656 if (pointerEvent.pointerType === 'mouse') { 1657 this.realElement.focus(); 1658 } 1659 }, 1660 onFakeOptionsRelease: function(e, pointerEvent) { 1661 this.pressedFlag = false;
1662 if (pointerEvent.pointerType === 'mouse') { 1663 this.realElement.focus(); 1664 } 1665 }, 1666 onSelect: function() { 1667 this.fireNativeEvent(this.realElement, 'change'); 1668 this.fireNativeEvent(this.realElement, 'click'); 1669 }, 1670 onFocus: function() { 1671 if (!this.pressedFlag || !this.focusedFlag) { 1672 this.fakeElement.addClass(this.options.focusClass); 1673 this.realElement.on('blur', this.onBlur); 1674 this.focusedFlag = true; 1675 } 1676 }, 1677 onBlur: function() { 1678 if (!this.pressedFlag) { 1679 this.fakeElement.removeClass(this.options.focusClass); 1680 this.realElement.off('blur', this.onBlur); 1681 this.focusedFlag = false; 1682 } 1683 }, 1684 refresh: function() { 1685 this.fakeElement.toggleClass(this.options.disabledClass, this.realElement.is(':disabled')); 1686 this.list.refresh(); 1687 }, 1688 destroy: function() { 1689 this.list.destroy(); 1690 this.realElement.insertBefore(this.fakeElement).removeClass(this.options.hiddenClass); 1691 this.fakeElement.remove(); 1692 } 1693 }); 1694 1695 // options list module 1696 function SelectList(options) { 1697 this.options = $.extend({ 1698 holder: null, 1699 maxVisibleItems: 10, 1700 selectOnClick: true, 1701 useHoverClass: false, 1702 useCustomScroll: false, 1703 handleResize: true, 1704 multipleSelectWithoutKey: false, 1705 alwaysPreventMouseWheel: false, 1706 indexAttribute: 'data-index', 1707 cloneClassPrefix: 'jcf-option-', 1708 containerStructure: '<span class="jcf-list"><span class="jcf-list-content"></span></span>', 1709 containerSelector: '.jcf-list-content', 1710 captionClass: 'jcf-optgroup-caption', 1711 disabledClass: 'jcf-disabled', 1712 optionClass: 'jcf-option', 1713 groupClass: 'jcf-optgroup', 1714 hoverClass: 'jcf-hover', 1715 selectedClass: 'jcf-selected', 1716 scrollClass: 'jcf-scroll-active' 1717 }, options); 1718 this.init(); 1719 } 1720 $.extend(SelectList.prototype, { 1721 init: function() { 1722 this.initStructure(); 1723 this.refreshSelectedClass(); 1724 this.attachEvents(); 1725 }, 1726 initStructure: function() { 1727 this.element = $(this.options.element); 1728 this.indexSelector = '[' + this.options.indexAttribute + ']'; 1729 this.container = $(this.options.containerStructure).appendTo(this.options.holder); 1730 this.listHolder = this.container.find(this.options.containerSelector); 1731 this.lastClickedIndex = this.element.prop('selectedIndex'); 1732 this.rebuildList(); 1733 }, 1734 attachEvents: function() { 1735 this.bindHandlers(); 1736 this.listHolder.on('jcf-pointerdown', this.indexSelector, this.onItemPress); 1737 this.listHolder.on('jcf-pointerdown', this.onPress); 1738 1739 if (this.options.useHoverClass) { 1740 this.listHolder.on('jcf-pointerover', this.indexSelector, this.onHoverItem); 1741 } 1742 }, 1743 onPress: function(e) { 1744 $(this).trigger('press', e); 1745 this.listHolder.on('jcf-pointerup', this.onRelease); 1746 }, 1747 onRelease: function(e) { 1748 $(this).trigger('release', e); 1749 this.listHolder.off('jcf-pointerup', this.onRelease); 1750 }, 1751 onHoverItem: function(e) { 1752 var hoverIndex = parseFloat(e.currentTarget.getAttribute(this.options.indexAttribute)); 1753 this.fakeOptions.removeClass(this.options.hoverClass).eq(hoverIndex).addClass(this.options.hoverClass); 1754 }, 1755 onItemPress: function(e) { 1756 if (e.pointerType === 'touch' || this.options.selectOnClick) { 1757 // select option after "click" 1758 this.tmpListOffsetTop = this.list.offset().top; 1759 this.listHolder.on('jcf-pointerup', this.indexSelector, this.onItemRelease); 1760 } else { 1761 // select option immediately 1762 this.onSelectItem(e); 1763 } 1764 }, 1765 onItemRelease: function(e) { 1766 // remove event handlers and temporary data 1767 this.listHolder.off('jcf-pointerup', this.indexSelector, this.onItemRelease); 1768 1769 // simulate item selection 1770 if (this.tmpListOffsetTop === this.list.offset().top) { 1771 this.listHolder.on('click', this.indexSelector, { savedPointerType: e.pointerType }, this.onSelectItem); 1772 } 1773 delete this.tmpListOffsetTop; 1774 }, 1775 onSelectItem: function(e) { 1776 var clickedIndex = parseFloat(e.currentTarget.getAttribute(this.options.indexAttribute)), 1777 pointerType = e.data && e.data.savedPointerType || e.pointerType || 'mouse', 1778 range; 1779 1780 // remove click event handler 1781 this.listHolder.off('click', this.indexSelector, this.onSelectItem); 1782 1783 // ignore clicks on disabled options 1784 if (e.button > 1 || this.realOptions[clickedIndex].disabled) { 1785 return; 1786 } 1787 1788 if (this.element.prop('multiple')) { 1789 if (e.metaKey || e.ctrlKey || pointerType === 'touch' || this.options.multipleSelectWithoutKey) { 1790 // if CTRL/CMD pressed or touch devices - toggle selected option 1791 this.realOptions[clickedIndex].selected = !this.realOptions[clickedIndex].selected; 1792 } else if (e.shiftKey) { 1793 // if SHIFT pressed - update selection 1794 range = [this.lastClickedIndex, clickedIndex].sort(function(a, b) { 1795 return a - b; 1796 }); 1797 this.realOptions.each(function(index, option) { 1798 option.selected = (index >= range[0] && index <= range[1]); 1799 }); 1800 } else { 1801 // set single selected index 1802 this.element.prop('selectedIndex', clickedIndex); 1803 } 1804 } else { 1805 this.element.prop('selectedIndex', clickedIndex); 1806 } 1807 1808 // save last clicked option 1809 if (!e.shiftKey) { 1810 this.lastClickedIndex = clickedIndex; 1811 } 1812 1813 // refresh classes 1814 this.refreshSelectedClass(); 1815 1816 // scroll to active item in desktop browsers 1817 if (pointerType === 'mouse') { 1818 this.scrollToActiveOption(); 1819 } 1820 1821 // make callback when item selected 1822 $(this).trigger('select'); 1823 }, 1824 rebuildList: function() { 1825 // rebuild options 1826 var self = this, 1827 rootElement = this.element[0]; 1828 1829 // recursively create fake options 1830 this.storedSelectHTML = rootElement.innerHTML; 1831 this.optionIndex = 0; 1832 this.list = $(this.createOptionsList(rootElement)); 1833 this.listHolder.empty().append(this.list); 1834 this.realOptions = this.element.find('option'); 1835 this.fakeOptions = this.list.find(this.indexSelector); 1836 this.fakeListItems = this.list.find('.' + this.options.captionClass + ',' + this.indexSelector); 1837 delete this.optionIndex; 1838 1839 // detect max visible items 1840 var maxCount = this.options.maxVisibleItems, 1841 sizeValue = this.element.prop('size'); 1842 if (sizeValue > 1 && !this.element.is('[jcf-size]')) { 1843 maxCount = sizeValue; 1844 } 1845 1846 // handle scrollbar 1847 var needScrollBar = this.fakeOptions.length > maxCount; 1848 this.container.toggleClass(this.options.scrollClass, needScrollBar); 1849 if (needScrollBar) { 1850 // change max-height 1851 this.listHolder.css({ 1852 maxHeight: this.getOverflowHeight(maxCount), 1853 overflow: 'auto' 1854 }); 1855 1856 if (this.options.useCustomScroll && jcf.modules.Scrollable) { 1857 // add custom scrollbar if specified in options 1858 jcf.replace(this.listHolder, 'Scrollable', { 1859 handleResize: this.options.handleResize, 1860 alwaysPreventMouseWheel: this.options.alwaysPreventMouseWheel 1861 }); 1862 return; 1863 } 1864 } 1865 1866 // disable edge wheel scrolling 1867 if (this.options.alwaysPreventMouseWheel) { 1868 this.preventWheelHandler = function(e) { 1869 var currentScrollTop = self.listHolder.scrollTop(), 1870 maxScrollTop = self.listHolder.prop('scrollHeight') - self.listHolder.innerHe
1870ight(); 1871 1872 // check edge cases 1873 if ((currentScrollTop <= 0 && e.deltaY < 0) || (currentScrollTop >= maxScrollTop && e.deltaY > 0)) { 1874 e.preventDefault(); 1875 } 1876 }; 1877 this.listHolder.on('jcf-mousewheel', this.preventWheelHandler); 1878 } 1879 }, 1880 refreshSelectedClass: function() { 1881 var self = this, 1882 selectedItem, 1883 isMultiple = this.element.prop('multiple'), 1884 selectedIndex = this.element.prop('selectedIndex'); 1885 1886 if (isMultiple) { 1887 this.realOptions.each(function(index, option) { 1888 self.fakeOptions.eq(index).toggleClass(self.options.selectedClass, !!option.selected); 1889 }); 1890 } else { 1891 this.fakeOptions.removeClass(this.options.selectedClass + ' ' + this.options.hoverClass); 1892 selectedItem = this.fakeOptions.eq(selectedIndex).addClass(this.options.selectedClass); 1893 if (this.options.useHoverClass) { 1894 selectedItem.addClass(this.options.hoverClass); 1895 } 1896 } 1897 }, 1898 scrollToActiveOption: function() { 1899 // scroll to target option 1900 var targetOffset = this.getActiveOptionOffset(); 1901 if (typeof targetOffset === 'number') { 1902 this.listHolder.prop('scrollTop', targetOffset); 1903 } 1904 }, 1905 getSelectedIndexRange: function() { 1906 var firstSelected = -1, lastSelected = -1; 1907 this.realOptions.each(function(index, option) { 1908 if (option.selected) { 1909 if (firstSelected < 0) { 1910 firstSelected = index; 1911 } 1912 lastSelected = index; 1913 } 1914 }); 1915 return [firstSelected, lastSelected]; 1916 }, 1917 getChangedSelectedIndex: function() { 1918 var selectedIndex = this.element.prop('selectedIndex'), 1919 targetIndex; 1920 1921 if (this.element.prop('multiple')) { 1922 // multiple selects handling 1923 if (!this.previousRange) { 1924 this.previousRange = [selectedIndex, selectedIndex]; 1925 } 1926 this.currentRange = this.getSelectedIndexRange(); 1927 targetIndex = this.currentRange[this.currentRange[0] !== this.previousRange[0] ? 0 : 1]; 1928 this.previousRange = this.currentRange; 1929 return targetIndex; 1930 } else { 1931 // single choice selects handling 1932 return selectedIndex; 1933 } 1934 }, 1935 getActiveOptionOffset: function() { 1936 // calc values 1937 var dropHeight = this.listHolder.height(), 1938 dropScrollTop = this.listHolder.prop('scrollTop'), 1939 currentIndex = this.getChangedSelectedIndex(), 1940 fakeOption = this.fakeOptions.eq(currentIndex), 1941 fakeOptionOffset = fakeOption.offset().top - this.list.offset().top, 1942 fakeOptionHeight = fakeOption.innerHeight(); 1943 1944 // scroll list 1945 if (fakeOptionOffset + fakeOptionHeight >= dropScrollTop + dropHeight) { 1946 // scroll down (always scroll to option) 1947 return fakeOptionOffset - dropHeight + fakeOptionHeight; 1948 } else if (fakeOptionOffset < dropScrollTop) { 1949 // scroll up to option 1950 return fakeOptionOffset; 1951 } 1952 }, 1953 getOverflowHeight: function(sizeValue) { 1954 var item = this.fakeListItems.eq(sizeValue - 1), 1955 listOffset = this.list.offset().top, 1956 itemOffset = item.offset().top, 1957 itemHeight = item.innerHeight(); 1958 1959 return itemOffset + itemHeight - listOffset; 1960 }, 1961 getScrollTop: function() { 1962 return this.listHolder.scrollTop(); 1963 }, 1964 setScrollTop: function(value) { 1965 this.listHolder.scrollTop(value); 1966 }, 1967 createOption: function(option) { 1968 var newOption = document.createElement('span'); 1969 newOption.className = this.options.optionClass; 1970 newOption.innerHTML = option.innerHTML; 1971 newOption.setAttribute(this.options.indexAttribute, this.optionIndex++); 1972 1973 var optionImage, optionImageSrc = option.getAttribute('data-image'); 1974 if (optionImageSrc) { 1975 optionImage = document.createElement('img'); 1976 optionImage.src = optionImageSrc; 1977 newOption.insertBefore(optionImage, newOption.childNodes[0]); 1978 } 1979 if (option.disabled) { 1980 newOption.className += ' ' + this.options.disabledClass; 1981 } 1982 if (option.className) { 1983 newOption.className += ' ' + getPrefixedClasses(option.className, this.options.cloneClassPrefix); 1984 } 1985 return newOption; 1986 }, 1987 createOptGroup: function(optgroup) { 1988 var optGroupContainer = document.createElement('span'), 1989 optGroupName = optgroup.getAttribute('label'), 1990 optGroupCaption, optGroupList; 1991 1992 // create caption 1993 optGroupCaption = document.createElement('span'); 1994 optGroupCaption.className = this.options.captionClass; 1995 optGroupCaption.innerHTML = optGroupName; 1996 optGroupContainer.appendChild(optGroupCaption); 1997 1998 // create list of options 1999 if (optgroup.children.length) { 2000 optGroupList = this.createOptionsList(optgroup); 2001 optGroupContainer.appendChild(optGroupList); 2002 } 2003 2004 optGroupContainer.className = this.options.groupClass; 2005 return optGroupContainer; 2006 }, 2007 createOptionContainer: function() { 2008 var optionContainer = document.createElement('li'); 2009 return optionContainer; 2010 }, 2011 createOptionsList: function(container) { 2012 var self = this, 2013 list = document.createElement('ul'); 2014 2015 $.each(container.children, function(index, currentNode) { 2016 var item = self.createOptionContainer(currentNode), 2017 newNode; 2018 2019 switch (currentNode.tagName.toLowerCase()) { 2020 case 'option': newNode = self.createOption(currentNode); break; 2021 case 'optgroup': newNode = self.createOptGroup(currentNode); break; 2022 } 2023 list.appendChild(item).appendChild(newNode); 2024 }); 2025 return list; 2026 }, 2027 refresh: function() { 2028 // check for select innerHTML changes 2029 if (this.storedSelectHTML !== this.element.prop('innerHTML')) { 2030 this.rebuildList(); 2031 } 2032 2033 // refresh custom scrollbar 2034 var scrollInstance = jcf.getInstance(this.listHolder); 2035 if (scrollInstance) { 2036 scrollInstance.refresh(); 2037 } 2038 2039 // refresh selectes classes 2040 this.refreshSelectedClass(); 2041 }, 2042 destroy: function() { 2043 this.listHolder.off('jcf-mousewheel', this.preventWheelHandler); 2044 this.listHolder.off('jcf-pointerdown', this.indexSelector, this.onSelectItem); 2045 this.listHolder.off('jcf-pointerover', this.indexSelector, this.onHoverItem); 2046 this.listHolder.off('jcf-pointerdown', this.onPress); 2047 } 2048 }); 2049 2050 // helper functions
2051 var getPrefixedClasses = function(className, prefixToAdd) { 2052 return className ? className.replace(/[\s]*([\S]+)+[\s]*/gi, prefixToAdd + '$1 ') : ''; 2053 }; 2054 var makeUnselectable = (function() { 2055 var unselectableClass = jcf.getOptions().unselectableClass; 2056 function preventHandler(e) { 2057 e.preventDefault(); 2058 } 2059 return function(node) { 2060 node.addClass(unselectableClass).on('selectstart', preventHandler); 2061 }; 2062 }()); 2063 2064}(jQuery, this)); 2065 2066 2067// navigation accesibility module 2068function TouchNav(opt) { 2069 this.options = { 2070 hoverClass: 'hover', 2071 menuItems: 'li', 2072 menuOpener: 'a', 2073 menuDrop: 'ul, form', 2074 navBlock: null 2075 }; 2076 for(var p in opt) { 2077 if(opt.hasOwnProperty(p)) { 2078 this.options[p] = opt[p]; 2079 } 2080 } 2081 this.init(); 2082} 2083TouchNav.isActiveOn = function(elem) { 2084 return elem && elem.touchNavActive; 2085}; 2086TouchNav.prototype = { 2087 init: function() { 2088 if(typeof this.options.navBlock === 'string') { 2089 this.menu = document.getElementById(this.options.navBlock); 2090 } else if(typeof this.options.navBlock === 'object') { 2091 this.menu = this.options.navBlock; 2092 } 2093 if(this.menu) { 2094 this.addEvents(); 2095 } 2096 }, 2097 addEvents: function() { 2098 // attach event handlers 2099 var self = this; 2100 var touchEvent = (navigator.pointerEnabled && 'pointerdown') || (navigator.msPointerEnabled && 'MSPointerDown') || (this.isTouchDevice && 'touchstart'); 2101 this.menuItems = lib.queryElementsBySelector(this.options.menuItems, this.menu); 2102 2103 var initMenuItem = function(item) { 2104 var currentDrop = lib.queryElementsBySelector(self.options.menuDrop, item)[0], 2105 currentOpener = lib.queryElementsBySelector(self.options.menuOpener, item)[0]; 2106 2107 // only for touch input devices 2108 if( currentDrop && currentOpener && (self.isTouchDevice || self.isPointerDevice) ) { 2109 lib.event.add(currentOpener, 'click', lib.bind(self.clickHandler, self)); 2110 lib.event.add(currentOpener, 'mousedown', lib.bind(self.mousedownHandler, self)); 2111 lib.event.add(currentOpener, touchEvent, function(e){ 2112 if( !self.isTouchPointerEvent(e) ) { 2113 self.preventCurrentClick = false; 2114 return; 2115 } 2116 self.touchFlag = true; 2117 self.currentItem = item; 2118 self.currentLink = currentOpener; 2119 self.pressHandler.apply(self, arguments); 2120 }); 2121 } 2122 // for desktop computers and touch devices 2123 jQuery(item).bind('mouseenter', function(){ 2124 if(!self.touchFlag) { 2125 self.currentItem = item; 2126 self.mouseoverHandler(); 2127 } 2128 }); 2129 jQuery(item).bind('mouseleave', function(){ 2130 if(!self.touchFlag) { 2131 self.currentItem = item; 2132 self.mouseoutHandler(); 2133 } 2134 }); 2135 item.touchNavActive = true; 2136 }; 2137 2138 // addd handlers for all menu items 2139 for(var i = 0; i < this.menuItems.length; i++) { 2140 initMenuItem(self.menuItems[i]); 2141 } 2142 2143 // hide dropdowns when clicking outside navigation 2144 if(this.isTouchDevice || this.isPointerDevice) { 2145 lib.event.add(document.documentElement, 'mousedown', lib.bind(this.clickOutsideHandler, this)); 2146 lib.event.add(document.documentElement, touchEvent, lib.bind(this.clickOutsideHandler, this)); 2147 } 2148 }, 2149 mousedownHandler: function(e) { 2150 if(this.touchFlag) { 2151 e.preventDefault(); 2152 this.touchFlag = false; 2153 this.preventCurrentClick = false; 2154 } 2155 }, 2156 mouseoverHandler: function() { 2157 lib.addClass(this.currentItem, this.options.hoverClass); 2158 jQuery(this.currentItem).trigger('itemhover'); 2159 }, 2160 mouseoutHandler: function() { 2161 lib.removeClass(this.currentItem, this.options.hoverClass); 2162 jQuery(this.currentItem).trigger('itemleave'); 2163 }, 2164 hideActiveDropdown: function() { 2165 for(var i = 0; i < this.menuItems.length; i++) { 2166 if(lib.hasClass(this.menuItems[i], this.options.hoverClass)) { 2167 lib.removeClass(this.menuItems[i], this.options.hoverClass); 2168 jQuery(this.menuItems[i]).trigger('itemleave'); 2169 } 2170 } 2171 this.activeParent = null; 2172 }, 2173 pressHandler: function(e) { 2174 // hide previous drop (if active) 2175 if(this.currentItem !== this.activeParent) { 2176 if(this.activeParent && this.currentItem.parentNode === this.activeParent.parentNode) { 2177 lib.removeClass(this.activeParent, this.options.hoverClass); 2178 } else if(!this.isParent(this.activeParent, this.currentLink)) { 2179 this.hideActiveDropdown(); 2180 } 2181 } 2182 // handle current drop 2183 this.activeParent = this.currentItem; 2184 if(lib.hasClass(this.currentItem, this.options.hoverClass)) { 2185 this.preventCurrentClick = false;
2186 } else { 2187 e.preventDefault(); 2188 this.preventCurrentClick = true; 2189 lib.addClass(this.currentItem, this.options.hoverClass); 2190 jQuery(this.currentItem).trigger('itemhover'); 2191 } 2192 }, 2193 clickHandler: function(e) { 2194 // prevent first click on link 2195 if(this.preventCurrentClick) { 2196 e.preventDefault(); 2197 } 2198 }, 2199 clickOutsideHandler: function(event) { 2200 var e = event.changedTouches ? event.changedTouches[0] : event; 2201 if(this.activeParent && !this.isParent(this.menu, e.target)) { 2202 this.hideActiveDropdown(); 2203 this.touchFlag = false; 2204 } 2205 }, 2206 isParent: function(parent, child) { 2207 while(child.parentNode) { 2208 if(child.parentNode == parent) { 2209 return true; 2210 } 2211 child = child.parentNode; 2212 } 2213 return false; 2214 }, 2215 isTouchPointerEvent: function(e) { 2216 return (e.type.indexOf('touch') > -1) || 2217 (navigator.pointerEnabled && e.pointerType === 'touch') || 2218 (navigator.msPointerEnabled && e.pointerType == e.MSPOINTER_TYPE_TOUCH); 2219 }, 2220 isPointerDevice: (function() { 2221 return !!(navigator.pointerEnabled || navigator.msPointerEnabled); 2222 }()), 2223 isTouchDevice: (function() { 2224 return !!(('ontouchstart' in window) || window.DocumentTouch && document instanceof DocumentTouch); 2225 }()) 2226}; 2227 2228/* 2229 * Utility module 2230 */ 2231 lib = { 2232 hasClass: function(el,cls) { 2233 return el && el.className ? el.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)')) : false; 2234 }, 2235 addClass: function(el,cls) { 2236 if (el && !this.hasClass(el,cls)) el.className += " "+cls; 2237 }, 2238 removeClass: function(el,cls) { 2239 if (el && this.hasClass(el,cls)) {el.className=el.className.replace(new RegExp('(\\s|^)'+cls+'(\\s|$)'),' ');} 2240 }, 2241 extend: function(obj) { 2242 for(var i = 1; i < arguments.length; i++) { 2243 for(var p in arguments[i]) { 2244 if(arguments[i].hasOwnProperty(p)) { 2245 obj[p] = arguments[i][p]; 2246 } 2247 } 2248 } 2249 return obj; 2250 }, 2251 each: function(obj, callback) { 2252 var property, len; 2253 if(typeof obj.length === 'number') { 2254 for(property = 0, len = obj.length; property < len; property++) { 2255 if(callback.call(obj[property], property, obj[property]) === false) { 2256 break; 2257 } 2258 } 2259 } else { 2260 for(property in obj) { 2261 if(obj.hasOwnProperty(property)) { 2262 if(callback.call(obj[property], property, obj[property]) === false) { 2263 break; 2264 } 2265 } 2266 } 2267 } 2268 }, 2269 event: (function() { 2270 var fixEvent = function(e) { 2271 e = e || window.event; 2272 if(e.isFixed) return e; else e.isFixed = true; 2273 if(!e.target) e.target = e.srcElement; 2274 e.preventDefault = e.preventDefault || function() {this.returnValue = false;}; 2275 e.stopPropagation = e.stopPropagation || function() {this.cancelBubble = true;}; 2276 return e; 2277 }; 2278 return { 2279 add: function(elem, event, handler) { 2280 if(!elem.events) { 2281 elem.events = {}; 2282 elem.handle = function(e) { 2283 var ret, handlers = elem.events[e.type]; 2284 e = fixEvent(e); 2285 for(var i = 0, len = handlers.length; i < len; i++) { 2286 if(handlers[i]) { 2287 ret = handlers[i].call(elem, e); 2288 if(ret === false) { 2289 e.preventDefault(); 2290 e.stopPropagation(); 2291 } 2292 } 2293 } 2294 }; 2295 } 2296 if(!elem.events[event]) { 2297 elem.events[event] = []; 2298 if(elem.addEventListener) elem.addEventListener(event, elem.handle, false); 2299 else if(elem.attachEvent) elem.attachEvent('on'+event, elem.handle); 2300 } 2301 elem.events[event].push(handler); 2302 }, 2303 remove: function(elem, event, handler) { 2304 var handlers = elem.events[event]; 2305 for(var i = handlers.length - 1; i >= 0; i--) { 2306 if(handlers[i] === handler) { 2307 handlers.splice(i,1); 2308 } 2309 } 2310 if(!handlers.length) { 2311 delete elem.events[event]; 2312 if(elem.removeEventListener) elem.removeEventListener(event, elem.handle, false); 2313 else if(elem.detachEvent) elem.detachEvent('on'+event, elem.handle); 2314 } 2315 } 2316 }; 2317 }()), 2318 queryElementsBySelector: function(selector, scope) { 2319 scope = scope || document; 2320 if(!selector) return []; 2321 if(selector === '>*') return scope.children; 2322 if(typeof document.querySelectorAll === 'function') { 2323 return scope.querySelectorAll(selector); 2324 } 2325 var selectors = selector.split(','); 2326 var resultList = []; 2327 for(var s = 0; s < selectors.length; s++) { 2328 var currentContext = [scope || document]; 2329 var tokens = selectors[s].replace(/^\s+/,'').replace(/\s+$/,'').split(' '); 2330 for (var i = 0; i < tokens.length; i++) { 2331 token = tokens[i].replace(/^\s+/,'').replace(/\s+$/,''); 2332 if (token.indexOf('#') > -1) { 2333 var bits = token.split('#'), tagName = bits[0], id = bits[1]; 2334 var element = document.getElementById(id); 2335 if (element && tagName && element.nodeName.toLowerCase() != tagName) { 2336 return []; 2337 } 2338 currentContext = element ? [element] : []; 2339 continue; 2340 } 2341 if (token.indexOf('.') > -1) { 2342 var bits = token.split('.'), tagName = bits[0] || '*', className = bits[1], found = [], foundCount = 0; 2343 for (var h = 0; h < currentContext.length; h++) { 2344 var elements; 2345 if (tagName == '*') { 2346 elements = currentContext[h].getElementsByTagName('*'); 2347 } else { 2348 elements = currentContext[h].getElementsByTagName(tagName); 2349 } 2350 for (var j = 0; j < elements.length; j++) { 2351 found[foundCount++] = elements[j]; 2352 } 2353 } 2354 currentContext = []; 2355 var currentContextIndex = 0; 2356 for (var k = 0; k < found.length; k++) { 2357 if (found[k].className && found[k].className.match(new RegExp('(\\s|^)'+className+'(\\s|$)'))) { 2358 currentContext[currentContextIndex++] = found[k]; 2359 } 2360 } 2361 continue; 2362 } 2363 if (token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)) { 2364 var tagName = RegExp.$1 || '*', attrName = RegExp.$2, attrOperator = RegExp.$3, attrValue = RegExp.$4; 2365 if(attrName.toLowerCase() == 'for' && this.browser.msie && this.browser.version < 8) { 2366 attrName = 'htmlFor'; 2367 } 2368 var found = [], foundCount = 0; 2369 for (var h = 0; h < currentContext.length; h++) { 2370 var elements; 2371 if (tagName == '*') { 2372 elements = currentContext[h].getElementsByTagName('*'); 2373 } else { 2374 elements = currentContext[h].getElementsByTagName(tagName); 2375 } 2376 for (var j = 0; elements[j]; j++) { 2377 found[foundCount++] = elements[j]; 2378 } 2379 } 2380 currentContext = []; 2381 var currentContextIndex = 0, checkFunction; 2382 switch (attrOperator) { 2383 case '=': checkFunction = function(e) { return (e.getAttribute(attrName) == attrValue) }; break; 2384 case '~': checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('(\\s|^)'+attrValue+'(\\s|$)'))) }; break; 2385 case '|': checkFunction = function(e) { return (e.getAttribute(attrName).match(new RegExp('^'+attrValue+'-?'))) }; break; 2386 case '^': checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) == 0) }; break; 2387 case '$': checkFunction = function(e) { return (e.getAttribute(attrName).lastIndexOf(attrValue) == e.getAttribute(attrName).length - attrValue.length) }; break; 2388 case '*': checkFunction = function(e) { return (e.getAttribute(attrName).indexOf(attrValue) > -1) }; break; 2389 default : checkFunction = function(e) { return e.getAttribute(attrName) }; 2390 } 2391 currentContext = []; 2392 var currentContextIndex = 0; 2393 for (var k = 0; k < found.length; k++) { 2394 if (checkFunction(found[k])) { 2395 currentContext[currentContextIndex++] = found[k]; 2396 } 2397 } 2398 continue; 2399 } 2400 tagName = token; 2401 var found = [], foundCount = 0; 2402 for (var h = 0; h < currentContext.length; h++) { 2403 var elements = currentContext[h].getElementsByTagName(tagName); 2404 for (var j = 0; j < elements.length; j++) { 2405 found[foundCount++] = elements[j]; 2406 } 2407 } 2408 currentContext = found; 2409 } 2410 resultList = [].concat(resultList,currentContext); 2411 } 2412 return resultList; 2413 }, 2414 trim: function (str) { 2415 return str.replace(/^\s+/, '').replace(/\s+$/, ''); 2416 }, 2417 bind: function(f, scope, forceArgs){ 2418 return function() {return f.apply(scope, typeof forceArgs !== 'undefined' ? [forceArgs] : arguments);}; 2419 } 2420 }; 2421 2422 /* 2423 * jQuery retina cover plugin 2424 */ 2425 ;(function($) { 2426 'use strict'; 2427 2428 var styleRules = {}; 2429 var templates = { 2430 '2x': [ 2431 '(-webkit-min-device-pixel-ratio: 1.5)', 2432 '(min-resolution: 192dpi)', 2433 '(min-device-pixel-ratio: 1.5)', 2434 '(min-resolution: 1.5dppx)' 2435 ], 2436 '3x': [ 2437 '(-webkit-min-device-pixel-ratio: 3)', 2438 '(min-resolution: 384dpi)', 2439 '(min-device-pixel-ratio: 3)', 2440 '(min-resolution: 3dppx)' 2441 ] 2442 }; 2443 2444 function addSimple(imageSrc, media, id) { 2445 var style = buildRule(id, imageSrc); 2446 2447 addRule(media, style); 2448 } 2449 2450 function addRetina(imageData, media, id) { 2451 var currentRules = templates[imageData[1]].slice(); 2452 var patchedRules = currentRules; 2453 var style = buildRule(id, imageData[0]); 2454 2455 if (media !== 'default') { 2456 patchedRules = $.map(currentRules, function(ele, i) { 2457 return ele + ' and ' + media; 2458 }); 2459 } 2460 2461 media = patchedRules.join(','); 2462 2463 addRule(media, style); 2464 } 2465 2466 function buildRule(id, src) { 2467 return '#' + id + '{background-image: url("' + src + '");}'; 2468 } 2469 2470 function addRule(media, rule) { 2471 var $styleTag = styleRules[media]; 2472 var styleTagData; 2473 var rules = ''; 2474 2475 if (media === 'default') { 2476 rules = rule + ' '; 2477 } else { 2478 rules = '@media ' + media + '{' + rule + '}'; 2479 } 2480 2481 if (!$styleTag) { 2482 styleRules[media] = $('<style>').text(rules).appendTo('head'); 2483 } else { 2484 styleTagData = $styleTag.text(); 2485 styleTagData = styleTagData.substring(0, styleTagData.length - 2) + ' }' + rule + '}'; 2486 $styleTag.text(styleTagData); 2487 } 2488 } 2489 2490 $.fn.retinaCover = function() { 2491 return this.each(function() { 2492 var $block = $(this); 2493 var $items = $block.children('[data-srcset]'); 2494 var id = 'bg-stretch' + Date.now() + (Math.random() * 1000).toFixed(0); 2495 2496 if ($items.length) { 2497 $block.attr('id', id); 2498 2499 $items.each(function() { 2500 var $item = $(this); 2501 var data = $item.data('srcset').split(', '); 2502 var media = $item.data('media') || 'default'; 2503 var dataLength = data.length; 2504 var itemData; 2505 var i; 2506 2507 for (i = 0; i < dataLength; i++) { 2508 itemData = data[i].split(' '); 2509 2510 if (itemData.length === 1) { 2511 addSimple(itemData[0], media, id); 2512 } else { 2513 addRetina(itemData, media, id); 2514 } 2515 } 2516 }); 2517 } 2518 2519 $items.detach(); 2520 }); 2521 }; 2522 }(jQuery)); 2523 2524/*! Picturefill - v3.0.1 - 2015-09-30 2525 * http://scottjehl.github.io/picturefill 2526 * Copyright (c) 2015 https://github.com/scottjehl/picturefill/blob/master/Authors.txt; Licensed MIT 2527 */ 2528 !function(a){var b=navigator.userAgent;a.HTMLPictureElement&&/ecko/.test(b)&&b.match(/rv\:(\d+)/)&&RegExp.$1<41&&addEventListener("resize",function(){var b,c=document.createElement("source"),d=function(a){var b,d,e=a.parentNode;
vendor: 4,515 bytes, line 2528
2528"PICTURE"===e.nodeName.toUpperCase()?(b=c.cloneNode(),e.insertBefore(b,e.firstElementChild),setTimeout(function(){e.removeChild(b)})):(!a._pfLastSize||a.offsetWidth>a._pfLastSize)&&(a._pfLastSize=a.offsetWidth,d=a.sizes,a.sizes+=",100vw",setTimeout(function(){a.sizes=d}))},e=function(){var a,b=document.querySelectorAll("picture > img, img[srcset][sizes]");for(a=0;a<b.length;a++)d(b[a])},f=function(){clearTimeout(b),b=setTimeout(e,99)},g=a.matchMedia&&matchMedia("(orientation: landscape)"),h=function(){f(),g&&g.addListener&&g.addListener(f)};return c.srcset="data:image/gif;base64,R0lGODlhAQABAAAAACH5BAEKAAEALAAAAAABAAEAAAICTAEAOw==",/^[c|i]|d$/.test(document.readyState||"")?h():document.addEventListener("DOMContentLoaded",h),f}())}(window),function(a,b,c){"use strict";function d(a){return" "===a||" "===a||"\n"===a||"\f"===a||"\r"===a}function e(b,c){var d=new a.Image;return d.onerror=function(){z[b]=!1,aa()},d.onload=function(){z[b]=1===d.width,aa()},d.src=c,"pending"}function f(){L=!1,O=a.devicePixelRatio,M={},N={},s.DPR=O||1,P.width=Math.max(a.innerWidth||0,y.clientWidth),P.height=Math.max(a.innerHeight||0,y.clientHeight),P.vw=P.width/100,P.vh=P.height/100,r=[P.height,P.width,O].join("-"),P.em=s.getEmValue(),P.rem=P.em}function g(a,b,c,d){var e,f,g,h;return"saveData"===A.algorithm?a>2.7?h=c+1:(f=b-c,e=Math.pow(a-.6,1.5),g=f*e,d&&(g+=.1*e),h=a+g):h=c>1?Math.sqrt(a*b):a,h>c}function h(a){var b,c=s.getSet(a),d=!1;"pending"!==c&&(d=r,c&&(b=s.setRes(c),s.applySetCandidate(b,a))),a[s.ns].evaled=d}function i(a,b){return a.res-b.res}function j(a,b,c){var d;return!c&&b&&(c=a[s.ns].sets,c=c&&c[c.length-1]),d=k(b,c),d&&(b=s.makeUrl(b),a[s.ns].curSrc=b,a[s.ns].curCan=d,d.res||_(d,d.set.sizes)),d}function k(a,b){var c,d,e;if(a&&b)for(e=s.parseSet(b),a=s.makeUrl(a),c=0;c<e.length;c++)if(a===s.makeUrl(e[c].url)){d=e[c];break}return d}function l(a,b){var c,d,e,f,g=a.getElementsByTagName("source");for(c=0,d=g.length;d>c;c++)e=g[c],e[s.ns]=!0,f=e.getAttribute("srcset"),f&&b.push({srcset:f,media:e.getAttribute("media"),type:e.getAttribute("type"),sizes:e.getAttribute("sizes")})}function m(a,b){function c(b){var c,d=b.exec(a.substring(m));return d?(c=d[0],m+=c.length,c):void 0}function e(){var a,c,d,e,f,i,j,k,l,m=!1,o={};for(e=0;e<h.length;e++)f=h[e],i=f[f.length-1],j=f.substring(0,f.length-1),k=parseInt(j,10),l=parseFloat(j),W.test(j)&&"w"===i?((a||c)&&(m=!0),0===k?m=!0:a=k):X.test(j)&&"x"===i?((a||c||d)&&(m=!0),0>l?m=!0:c=l):W.test(j)&&"h"===i?((d||c)&&(m=!0),0===k?m=!0:d=k):m=!0;m||(o.url=g,a&&(o.w=a),c&&(o.d=c),d&&(o.h=d),d||c||a||(o.d=1),1===o.d&&(b.has1x=!0),o.set=b,n.push(o))}function f(){for(c(S),i="",j="in descriptor";;){if(k=a.charAt(m),"in descriptor"===j)if(d(k))i&&(h.push(i),i="",j="after descriptor");else{if(","===k)return m+=1,i&&h.push(i),void e();if("("===k)i+=k,j="in parens";else{if(""===k)return i&&h.push(i),void e();i+=k}}else if("in parens"===j)if(")"===k)i+=k,j="in descriptor";else{if(""===k)return h.push(i),void e();i+=k}else if("after descriptor"===j)if(d(k));else{if(""===k)return void e();j="in descriptor",m-=1}m+=1}}for(var g,h,i,j,k,l=a.length,m=0,n=[];;){if(c(T),m>=l)return n;g=c(U),h=[],","===g.slice(-1)?(g=g.replace(V,""),e()):f()}}function n(a){function b(a){function b(){f&&(g.push(f),f="")}function c(){g[0]&&(h.push(g),g=[])}for(var e,f="",g=[],h=[],i=0,j=0,k=!1;;){if(e=a.charAt(j),""===e)return b(),c(),h;if(k){if("*"===e&&"/"===a[j+1]){k=!1,j+=2,b();continue}j+=1}else{if(d(e)){if(a.charAt(j-1)&&d(a.charAt(j-1))||!f){j+=1;continue}if(0===i){b(),j+=1;continue}e=" "}else if("("===e)i+=1;else if(")"===e)i-=1;else{if(","===e){b(),c(),j+=1;continue}if("/"===e&&"*"===a.charAt(j+1)){k=!0,j+=2;continue}}f+=e,j+=1}}}function c(a){return k.test(a)&&parseFloat(a)>=0?!0:l.test(a)?!0:"0"===a||"-0"===a||"+0"===a?!0:!1}var e,f,g,h,i,j,k=/^(?:[+-]?[0-9]+|[0-9]*\.[0-9]+)(?:[eE][+-]?[0-9]+)?(?:ch|cm|em|ex|in|mm|pc|pt|px|rem|vh|vmin|vmax|vw)$/i,l=/^calc\((?:[0-9a-z \.\+\-\*\/\(\)]+)\)$/i;for(f=b(a),g=f.length,e=0;g>e;e++)if(h=f[e],i=h[h.length-1],c(i)){if(j=i,h.pop(),0===h.length)return j;if(h=h.join(" "),s.matchesMedia(h))return j}return"100vw"}b.createElement("picture");var o,p,q,r,s={},t=function(){},u=b.createElement("img"),v=u.getAttribute,w=u.setAttribute,x=u.removeAttribute,y=b.documentElement,z={},A={algorithm:""},B="data-pfsrc",C=B+"set",D=navigator.userAgent,E=/rident/.test(D)||/ecko/.test(D)&&D.match(/rv\:(\d+)/)&&RegExp.$1>35,F="currentSrc",G=/\s+\+?\d+(e\d+)?w/,H=/(\([^)]+\))?\s*(.+)/,I=a.picturefillCFG,J="position:absolute;
2528left:0;visibility:hidden;display:block;padding:0;border:none;font-size:1em;width:1em;overflow:hidden;clip:rect(0px, 0px, 0px, 0px)",K="font-size:100%!important;",L=!0,M={},N={},O=a.devicePixelRatio,P={px:1,"in":96},Q=b.createElement("a"),R=!1,S=/^[ \t\n\r\u000c]+/,T=/^[, \t\n\r\u000c]+/,U=/^[^ \t\n\r\u000c]+/,V=/[,]+$/,W=/^\d+$/,X=/^-?(?:[0-9]+|[0-9]*\.[0-9]+)(?:[eE][+-]?[0-9]+)?$/,Y=function(a,b,c,d){a.addEventListener?a.addEventListener(b,c,d||!1):a.attachEvent&&a.attachEvent("on"+b,c)},Z=function(a){var b={};return function(c){return c in b||(b[c]=a(c)),b[c]}},$=function(){var a=/^([\d\.]+)(em|vw|px)$/,b=function(){for(var a=arguments,b=0,c=a[0];++b in a;)c=c.replace(a[b],a[++b]);return c},c=Z(function(a){return"return "+b((a||"").toLowerCase(),/\band\b/g,"&&",/,/g,"||",/min-([a-z-\s]+):/g,"e.$1>=",/max-([a-z-\s]+):/g,"e.$1<=",/calc([^)]+)/g,"($1)",/(\d+[\.]*[\d]*)([a-z]+)/g,"($1 * e.$2)",/^(?!(e.[a-z]|[0-9\.&=|><\+\-\*\(\)\/])).*/gi,"")+";"});return function(b,d){var e;if(!(b in M))if(M[b]=!1,d&&(e=b.match(a)))M[b]=e[1]*P[e[2]];else try{M[b]=new Function("e",c(b))(P)}catch(f){}return M[b]}}(),_=function(a,b){return a.w?(a.cWidth=s.calcListLength(b||"100vw"),a.res=a.w/a.cWidth):a.res=a.d,a},aa=function(a){var c,d,e,f=a||{};if(f.elements&&1===f.elements.nodeType&&("IMG"===f.elements.nodeName.toUpperCase()?f.elements=[f.elements]:(f.context=f.elements,f.elements=null)),c=f.elements||s.qsa(f.context||b,f.reevaluate||f.reselect?s.sel:s.selShort),e=c.length){for(s.setupRun(f),R=!0,d=0;e>d;d++)s.fillImg(c[d],f);s.teardownRun(f)}};o=a.console&&console.warn?function(a){console.warn(a)}:t,F in u||(F="src"),z["image/jpeg"]=!0,z["image/gif"]=!0,z["image/png"]=!0,z["image/svg+xml"]=b.implementation.hasFeature("http://wwwindow.w3.org/TR/SVG11/feature#Image","1.1"),s.ns=("pf"+(new Date).getTime()).substr(0,9),s.supSrcset="srcset"in u,s.supSizes="sizes"in u,s.supPicture=!!a.HTMLPictureElement,s.supSrcset&&s.supPicture&&!s.supSizes&&!function(a){u.srcset="data:,a",a.src="data:,a",s.supSrcset=u.complete===a.complete,s.supPicture=s.supSrcset&&s.supPicture}(b.createElement("img")),s.selShort="picture>img,img[srcset]",s.sel=s.selShort,s.cfg=A,s.supSrcset&&(s.sel+=",img["+C+"]"),s.DPR=O||1,s.u=P,s.types=z,q=s.supSrcset&&!s.supSizes,s.setSize=t,s.makeUrl=Z(function(a){return Q.href=a,Q.href}),s.qsa=function(a,b){return a.querySelectorAll(b)},s.matchesMedia=function(){return a.matchMedia&&(matchMedia("(min-width: 0.1em)")||{}).matches?s.matchesMedia=function(a){return!a||matchMedia(a).matches}:s.matchesMedia=s.mMQ,s.matchesMedia.apply(this,arguments)},s.mMQ=function(a){return a?$(a):!0},s.calcLength=function(a){var b=$(a,!0)||!1;return 0>b&&(b=!1),b},s.supportsType=function(a){return a?z[a]:!0},s.parseSize=Z(function(a){var b=(a||"").match(H);return{media:b&&b[1],length:b&&b[2]}}),s.parseSet=function(a){return a.cands||(a.cands=m(a.srcset,a)),a.cands},s.getEmValue=function(){var a;if(!p&&(a=b.body)){var c=b.createElement("div"),d=y.style.cssText,e=a.style.cssText;c.style.cssText=J,y.style.cssText=K,a.style.cssText=K,a.appendChild(c),p=c.offsetWidth,a.removeChild(c),p=parseFloat(p,10),y.style.cssText=d,a.style.cssText=e}return p||16},s.calcListLength=function(a){if(!(a in N)||A.uT){var b=s.calcLength(n(a));N[a]=b?b:P.width}return N[a]},s.setRes=function(a){var b;if(a){b=s.parseSet(a);for(var c=0,d=b.length;d>c;c++)_(b[c],a.sizes)}return b},s.setRes.res=_,s.applySetCandidate=function(a,b){if(a.length){var c,d,e,f,h,k,l,m,n,o=b[s.ns],p=s.DPR;if(k=o.curSrc||b[F],l=o.curCan||j(b,k,a[0].set),l&&l.set===a[0].set&&(n=E&&!b.complete&&l.res-.1>p,n||(l.cached=!0,l.res>=p&&(h=l))),!h)for(a.sort(i),f=a.length,h=a[f-1],d=0;f>d;d++)if(c=a[d],c.res>=p){e=d-1,h=a[e]&&(n||k!==s.makeUrl(c.url))&&g(a[e].res,c.res,p,a[e].cached)?a[e]:c;break}h&&(m=s.makeUrl(h.url),o.curSrc=m,o.curCan=h,m!==k&&s.setSrc(b,h),s.setSize(b))}},s.setSrc=function(a,b){var c;a.src=b.url,"image/svg+xml"===b.set.type&&(c=a.style.width,a.style.width=a.offsetWidth+1+"px",a.offsetWidth+1&&(a.style.width=c))},s.getSet=function(a){var b,c,d,e=!1,f=a[s.ns].sets;for(b=0;b<f.length&&!e;b++)if(c=f[b],c.srcset&&s.matchesMedia(c.media)&&(d=s.supportsType(c.type))){"pending"===d&&(c=d),e=c;break}return e},s.parseSets=function(a,b,d){var e,f,g,h,i=b&&"PICTURE"===b.nodeName.toUpperCase(),j=a[s.ns];(j.src===c||d.src)&&(j.src=v.call(a,"src"),j.src?w.call(a,B,j.src):x.call(a,B)),(j.srcset===c||d.srcset||!s.supSrcset||a.srcset)&&(e=v.call(a,"srcset"),j.srcset=e,h=!0),j.sets=[],i&&(j.pic=!0,l(b,j.set
vendor: 2,198 bytes, lines 2528-2534
2528s)),j.srcset?(f={srcset:j.srcset,sizes:v.call(a,"sizes")},j.sets.push(f),g=(q||j.src)&&G.test(j.srcset||""),g||!j.src||k(j.src,f)||f.has1x||(f.srcset+=", "+j.src,f.cands.push({url:j.src,d:1,set:f}))):j.src&&j.sets.push({srcset:j.src,sizes:null}),j.curCan=null,j.curSrc=c,j.supported=!(i||f&&!s.supSrcset||g),h&&s.supSrcset&&!j.supported&&(e?(w.call(a,C,e),a.srcset=""):x.call(a,C)),j.supported&&!j.srcset&&(!j.src&&a.src||a.src!==s.makeUrl(j.src))&&(null===j.src?a.removeAttribute("src"):a.src=j.src),j.parsed=!0},s.fillImg=function(a,b){var c,d=b.reselect||b.reevaluate;a[s.ns]||(a[s.ns]={}),c=a[s.ns],(d||c.evaled!==r)&&((!c.parsed||b.reevaluate)&&s.parseSets(a,a.parentNode,b),c.supported?c.evaled=r:h(a))},s.setupRun=function(){(!R||L||O!==a.devicePixelRatio)&&f()},s.supPicture?(aa=t,s.fillImg=t):!function(){var c,d=a.attachEvent?/d$|^c/:/d$|^c|^i/,e=function(){var a=b.readyState||"";f=setTimeout(e,"loading"===a?200:999),b.body&&(s.fillImgs(),c=c||d.test(a),c&&clearTimeout(f))},f=setTimeout(e,b.body?9:99),g=function(a,b){var c,d,e=function(){var f=new Date-d;b>f?c=setTimeout(e,b-f):(c=null,a())};return function(){d=new Date,c||(c=setTimeout(e,b))}},h=y.clientHeight,i=function(){L=Math.max(a.innerWidth||0,y.clientWidth)!==P.width||y.clientHeight!==h,h=y.clientHeight,L&&s.fillImgs()};Y(a,"resize",g(i,99)),Y(b,"readystatechange",e)}(),s.picturefill=aa,s.fillImgs=aa,s.teardownRun=t,aa._=s,a.picturefillCFG={pf:s,push:function(a){var b=a.shift();"function"==typeof s[b]?s[b].apply(s,a):(A[b]=a[0],R&&s.fillImgs({reselect:!0}))}};for(;I&&I.length;)a.picturefillCFG.push(I.shift());a.picturefill=aa,"object"==typeof module&&"object"==typeof module.exports?module.exports=aa:"function"==typeof define&&define.amd&&define("picturefill",function(){return aa}),s.supPicture||(z["image/webp"]=e("image/webp","data:image/webp;base64,UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAABBxAR/Q9ERP8DAABWUDggGAAAADABAJ0BKgEAAQADADQlpAADcAD++/1QAA=="))}(window,document); 2529 2530 if(!('backgroundBlendMode' in document.body.style)) { 2531 // No support for background-blend-mode 2532 var html = document.getElementsByTagName("html")[0]; 2533 html.className = html.className + " no-background-blend-mode"; 2534}
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.