vendor: 19,414 bytes, lines 1-656
1/*! 2 * Flickity PACKAGED v2.1.2 3 * Touch, responsive, flickable carousels 4 * 5 * Licensed GPLv3 for open source use 6 * or Flickity Commercial License for commercial use 7 * 8 * https://flickity.metafizzy.co 9 * Copyright 2015-2018 Metafizzy 10 */ 11 12/** 13 * Bridget makes jQuery widgets 14 * v2.0.1 15 * MIT license 16 */ 17 18/* jshint browser: true, strict: true, undef: true, unused: true */ 19 20( function( window, factory ) { 21 // universal module definition 22 /*jshint strict: false */ /* globals define, module, require */ 23 if ( typeof define == 'function' && define.amd ) { 24 // AMD 25 define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) { 26 return factory( window, jQuery ); 27 }); 28 } else if ( typeof module == 'object' && module.exports ) { 29 // CommonJS 30 module.exports = factory( 31 window, 32 require('jquery') 33 ); 34 } else { 35 // browser global 36 window.jQueryBridget = factory( 37 window, 38 window.jQuery 39 ); 40 } 41 42}( window, function factory( window, jQuery ) { 43 'use strict'; 44 45// ----- utils ----- // 46 47 var arraySlice = Array.prototype.slice; 48 49// helper function for logging errors 50// $.error breaks jQuery chaining 51 var console = window.console; 52 var logError = typeof console == 'undefined' ? function() {} : 53 function( message ) { 54 console.error( message ); 55 }; 56 57// ----- jQueryBridget ----- // 58 59 function jQueryBridget( namespace, PluginClass, $ ) { 60 $ = $ || jQuery || window.jQuery; 61 if ( !$ ) { 62 return; 63 } 64 65 // add option method -> $().plugin('option', {...}) 66 if ( !PluginClass.prototype.option ) { 67 // option setter 68 PluginClass.prototype.option = function( opts ) { 69 // bail out if not an object 70 if ( !$.isPlainObject( opts ) ){ 71 return; 72 } 73 this.options = $.extend( true, this.options, opts ); 74 }; 75 } 76 77 // make jQuery plugin 78 $.fn[ namespace ] = function( arg0 /*, arg1 */ ) { 79 if ( typeof arg0 == 'string' ) { 80 // method call $().plugin( 'methodName', { options } ) 81 // shift arguments by 1 82 var args = arraySlice.call( arguments, 1 ); 83 return methodCall( this, arg0, args ); 84 } 85 // just $().plugin({ options }) 86 plainCall( this, arg0 ); 87 return this; 88 }; 89 90 // $().plugin('methodName') 91 function methodCall( $elems, methodName, args ) { 92 var returnValue; 93 var pluginMethodStr = '$().' + namespace + '("' + methodName + '")'; 94 95 $elems.each( function( i, elem ) { 96 // get instance 97 var instance = $.data( elem, namespace ); 98 if ( !instance ) { 99 logError( namespace + ' not initialized. Cannot call methods, i.e. ' + 100 pluginMethodStr ); 101 return; 102 } 103 104 var method = instance[ methodName ]; 105 if ( !method || methodName.charAt(0) == '_' ) { 106 logError( pluginMethodStr + ' is not a valid method' ); 107 return; 108 } 109 110 // apply method, get return value 111 var value = method.apply( instance, args ); 112 // set return value if value is returned, use only first value 113 returnValue = returnValue === undefined ? value : returnValue; 114 }); 115 116 return returnValue !== undefined ? returnValue : $elems; 117 } 118 119 function plainCall( $elems, options ) { 120 $elems.each( function( i, elem ) { 121 var instance = $.data( elem, namespace ); 122 if ( instance ) { 123 // set options & init 124 instance.option( options ); 125 instance._init(); 126 } else { 127 // initialize new instance 128 instance = new PluginClass( elem, options ); 129 $.data( elem, namespace, instance ); 130 } 131 }); 132 } 133 134 updateJQuery( $ ); 135 136 } 137 138// ----- updateJQuery ----- // 139 140// set $.bridget for v1 backwards compatibility 141 function updateJQuery( $ ) { 142 if ( !$ || ( $ && $.bridget ) ) { 143 return; 144 } 145 $.bridget = jQueryBridget; 146 } 147 148 updateJQuery( jQuery || window.jQuery ); 149 150// ----- ----- // 151 152 return jQueryBridget; 153 154})); 155 156/** 157 * EvEmitter v1.1.0 158 * Lil' event emitter 159 * MIT License 160 */ 161 162/* jshint unused: true, undef: true, strict: true */ 163 164( function( global, factory ) { 165 // universal module definition 166 /* jshint strict: false */ /* globals define, module, window */ 167 if ( typeof define == 'function' && define.amd ) { 168 // AMD - RequireJS 169 define( 'ev-emitter/ev-emitter',factory ); 170 } else if ( typeof module == 'object' && module.exports ) { 171 // CommonJS - Browserify, Webpack 172 module.exports = factory(); 173 } else { 174 // Browser globals 175 global.EvEmitter = factory(); 176 } 177 178}( typeof window != 'undefined' ? window : this, function() { 179 180 181 182 function EvEmitter() {} 183 184 var proto = EvEmitter.prototype; 185 186 proto.on = function( eventName, listener ) { 187 if ( !eventName || !listener ) { 188 return; 189 } 190 // set events hash 191 var events = this._events = this._events || {}; 192 // set listeners array 193 var listeners = events[ eventName ] = events[ eventName ] || []; 194 // only add once 195 if ( listeners.indexOf( listener ) == -1 ) { 196 listeners.push( listener ); 197 } 198 199 return this; 200 }; 201 202 proto.once = function( eventName, listener ) { 203 if ( !eventName || !listener ) { 204 return; 205 } 206 // add event 207 this.on( eventName, listener ); 208 // set once flag 209 // set onceEvents hash 210 var onceEvents = this._onceEvents = this._onceEvents || {}; 211 // set onceListeners object 212 var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {}; 213 // set flag 214 onceListeners[ listener ] = true; 215 216 return this; 217 }; 218 219 proto.off = function( eventName, listener ) { 220 var listeners = this._events && this._events[ eventName ]; 221 if ( !listeners || !listeners.length ) { 222 return; 223 } 224 var index = listeners.indexOf( listener ); 225 if ( index != -1 ) { 226 listeners.splice( index, 1 ); 227 } 228 229 return this; 230 }; 231 232 proto.emitEvent = function( eventName, args ) { 233 var listeners = this._events && this._events[ eventName ]; 234 if ( !listeners || !listeners.length ) { 235 return; 236 } 237 // copy over to avoid interference if .off() in listener 238 listeners = listeners.slice(0); 239 args = args || []; 240 // once stuff 241 var onceListeners = this._onceEvents && this._onceEvents[ eventName ]; 242 243 for ( var i=0; i < listeners.length; i++ ) { 244 var listener = listeners[i] 245 var isOnce = onceListeners && onceListeners[ listener ]; 246 if ( isOnce ) { 247 // remove listener 248 // remove before trigger to prevent recursion 249 this.off( eventName, listener ); 250 // unset once flag 251 delete onceListeners[ listener ]; 252 } 253 // trigger listener 254 listener.apply( this, args ); 255 } 256 257 return this; 258 }; 259 260 proto.allOff = function() { 261 delete this._events; 262 delete this._onceEvents; 263 }; 264 265 return EvEmitter; 266 267})); 268 269/*! 270 * getSize v2.0.3 271 * measure size of elements 272 * MIT license 273 */ 274 275/* jshint browser: true, strict: true, undef: true, unused: true */ 276/* globals console: false */ 277 278( function( window, factory ) { 279 /* jshint strict: false */ /* globals define, module */ 280 if ( typeof define == 'function' && define.amd ) { 281 // AMD 282 define( 'get-size/get-size',factory ); 283 } else if ( typeof module == 'object' && module.exports ) { 284 // CommonJS 285 module.exports = factory(); 286 } else { 287 // browser global 288 window.getSize = factory(); 289 } 290 291})( window, function factory() { 292 'use strict'; 293 294// -------------------------- helpers -------------------------- // 295 296// get a number from a string, not a percentage 297 function getStyleSize( value ) { 298 var num = parseFloat( value ); 299 // not a percent like '100%', and a number 300 var isValid = value.indexOf('%') == -1 && !isNaN( num ); 301 return isValid && num; 302 } 303 304 function noop() {} 305 306 var logError = typeof console == 'undefined' ? noop : 307 function( message ) { 308 console.error( message ); 309 }; 310 311// -------------------------- measurements -------------------------- // 312 313 var measurements = [ 314 'paddingLeft', 315 'paddingRight', 316 'paddingTop', 317 'paddingBottom', 318 'marginLeft', 319 'marginRight', 320 'marginTop', 321 'marginBottom', 322 'borderLeftWidth', 323 'borderRightWidth', 324 'borderTopWidth', 325 'borderBottomWidth' 326 ]; 327 328 var measurementsLength = measurements.length; 329 330 function getZeroSize() { 331 var size = { 332 width: 0, 333 height: 0, 334 innerWidth: 0, 335 innerHeight: 0, 336 outerWidth: 0, 337 outerHeight: 0 338 }; 339 for ( var i=0; i < measurementsLength; i++ ) { 340 var measurement = measurements[i]; 341 size[ measurement ] = 0; 342 } 343 return size; 344 } 345 346// -------------------------- getStyle -------------------------- // 347 348 /** 349 * getStyle, get style of element, check for Firefox bug 350 * https://bugzilla.mozilla.org/show_bug.cgi?id=548397 351 */ 352 function getStyle( elem ) { 353 var style = getComputedStyle( elem ); 354 if ( !style ) { 355 logError( 'Style returned ' + style + 356 '. Are you running this code in a hidden iframe on Firefox? ' + 357 'See https://bit.ly/getsizebug1' ); 358 } 359 return style; 360 } 361 362// -------------------------- setup -------------------------- // 363 364 var isSetup = false; 365 366 var isBoxSizeOuter; 367 368 /** 369 * setup 370 * check isBoxSizerOuter 371 * do on first getSize() rather than on page load for Firefox bug 372 */ 373 function setup() { 374 // setup once 375 if ( isSetup ) { 376 return; 377 } 378 isSetup = true; 379 380 // -------------------------- box sizing -------------------------- // 381 382 /** 383 * Chrome & Safari measure the outer-width on style.width on border-box elems 384 * IE11 & Firefox<29 measures the inner-width 385 */ 386 var div = document.createElement('div'); 387 div.style.width = '200px'; 388 div.style.padding = '1px 2px 3px 4px'; 389 div.style.borderStyle = 'solid'; 390 div.style.borderWidth = '1px 2px 3px 4px'; 391 div.style.boxSizing = 'border-box'; 392 393 var body = document.body || document.documentElement; 394 body.appendChild( div ); 395 var style = getStyle( div ); 396 // round value for browser zoom. desandro/masonry#928 397 isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200; 398 getSize.isBoxSizeOuter = isBoxSizeOuter; 399 400 body.removeChild( div ); 401 } 402 403// -------------------------- getSize -------------------------- // 404 405 function getSize( elem ) { 406 setup(); 407 408 // use querySeletor if elem is string 409 if ( typeof elem == 'string' ) { 410 elem = document.querySelector( elem ); 411 } 412 413 // do not proceed on non-objects 414 if ( !elem || typeof elem != 'object' || !elem.nodeType ) { 415 return; 416 } 417 418 var style = getStyle( elem ); 419 420 // if hidden, everything is 0 421 if ( style.display == 'none' ) { 422 return getZeroSize(); 423 } 424 425 var size = {}; 426 size.width = elem.offsetWidth; 427 size.height = elem.offsetHeight; 428 429 var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box'; 430 431 // get all measurements 432 for ( var i=0; i < measurementsLength; i++ ) { 433 var measurement = measurements[i]; 434 var value = style[ measurement ]; 435 var num = parseFloat( value ); 436 // any 'auto', 'medium' value will be 0 437 size[ measurement ] = !isNaN( num ) ? num : 0; 438 } 439 440 var paddingWidth = size.paddingLeft + size.paddingRight; 441 var paddingHeight = size.paddingTop + size.paddingBottom; 442 var marginWidth = size.marginLeft + size.marginRight; 443 var marginHeight = size.marginTop + size.marginBottom; 444 var borderWidth = size.borderLeftWidth + size.borderRightWidth; 445 var borderHeight = size.borderTopWidth + size.borderBottomWidth; 446 447 var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter; 448 449 // overwrite width and height if we can get it from style 450 var styleWidth = getStyleSize( style.width ); 451 if ( styleWidth !== false ) { 452 size.width = styleWidth + 453 // add padding and border unless it's already including it 454 ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth ); 455 } 456 457 var styleHeight = getStyleSize( style.height ); 458 if ( styleHeight !== false ) { 459 size.height = styleHeight + 460 // add padding and border unless it's already including it 461 ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight ); 462 } 463 464 size.innerWidth = size.width - ( paddingWidth + borderWidth ); 465 size.innerHeight = size.height - ( paddingHeight + borderHeight ); 466 467 size.outerWidth = size.width + marginWidth; 468 size.outerHeight = size.height + marginHeight; 469 470 return size; 471 } 472 473 return getSize; 474 475}); 476 477/** 478 * matchesSelector v2.0.2 479 * matchesSelector( element, '.selector' ) 480 * MIT license 481 */ 482 483/*jshint browser: true, strict: true, undef: true, unused: true */ 484 485( function( window, factory ) { 486 /*global define: false, module: false */ 487 'use strict'; 488 // universal module definition 489 if ( typeof define == 'function' && define.amd ) { 490 // AMD 491 define( 'desandro-matches-selector/matches-selector',factory ); 492 } else if ( typeof module == 'object' && module.exports ) { 493 // CommonJS 494 module.exports = factory(); 495 } else { 496 // browser global 497 window.matchesSelector = factory(); 498 } 499 500}( window, function factory() { 501 'use strict'; 502 503 var matchesMethod = ( function() { 504 var ElemProto = window.Element.prototype; 505 // check for the standard method name first 506 if ( ElemProto.matches ) { 507 return 'matches'; 508 } 509 // check un-prefixed 510 if ( ElemProto.matchesSelector ) { 511 return 'matchesSelector'; 512 } 513 // check vendor prefixes 514 var prefixes = [ 'webkit', 'moz', 'ms', 'o' ]; 515 516 for ( var i=0; i < prefixes.length; i++ ) { 517 var prefix = prefixes[i]; 518 var method = prefix + 'MatchesSelector'; 519 if ( ElemProto[ method ] ) { 520 return method; 521 } 522 } 523 })(); 524 525 return function matchesSelector( elem, selector ) { 526 return elem[ matchesMethod ]( selector ); 527 }; 528 529})); 530 531/** 532 * Fizzy UI utils v2.0.7 533 * MIT license 534 */ 535 536/*jshint browser: true, undef: true, unused: true, strict: true */ 537 538( function( window, factory ) { 539 // universal module definition 540 /*jshint strict: false */ /*globals define, module, require */ 541 542 if ( typeof define == 'function' && define.amd ) { 543 // AMD 544 define( 'fizzy-ui-utils/utils',[ 545 'desandro-matches-selector/matches-selector' 546 ], function( matchesSelector ) { 547 return factory( window, matchesSelector ); 548 }); 549 } else if ( typeof module == 'object' && module.exports ) { 550 // CommonJS 551 module.exports = factory( 552 window, 553 require('desandro-matches-selector') 554 ); 555 } else { 556 // browser global 557 window.fizzyUIUtils = factory( 558 window, 559 window.matchesSelector 560 ); 561 } 562 563}( window, function factory( window, matchesSelector ) { 564 565 566 567 var utils = {}; 568 569// ----- extend ----- // 570 571// extends objects 572 utils.extend = function( a, b ) { 573 for ( var prop in b ) { 574 a[ prop ] = b[ prop ]; 575 } 576 return a; 577 }; 578 579// ----- modulo ----- // 580 581 utils.modulo = function( num, div ) { 582 return ( ( num % div ) + div ) % div; 583 }; 584 585// ----- makeArray ----- // 586 587 var arraySlice = Array.prototype.slice; 588 589// turn element or nodeList into an array 590 utils.makeArray = function( obj ) { 591 if ( Array.isArray( obj ) ) { 592 // use object if already an array 593 return obj; 594 } 595 // return empty array if undefined or null. #6 596 if ( obj === null || obj === undefined ) { 597 return []; 598 } 599 600 var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number'; 601 if ( isArrayLike ) { 602 // convert nodeList to array 603 return arraySlice.call( obj ); 604 } 605 606 // array of single index 607 return [ obj ]; 608 }; 609 610// ----- removeFrom ----- // 611 612 utils.removeFrom = function( ary, obj ) { 613 var index = ary.indexOf( obj ); 614 if ( index != -1 ) { 615 ary.splice( index, 1 ); 616 } 617 }; 618 619// ----- getParent ----- // 620 621 utils.getParent = function( elem, selector ) { 622 while ( elem.parentNode && elem != document.body ) { 623 elem = elem.parentNode; 624 if ( matchesSelector( elem, selector ) ) { 625 return elem; 626 } 627 } 628 }; 629 630// ----- getQueryElement ----- // 631 632// use element as selector string 633 utils.getQueryElement = function( elem ) { 634 if ( typeof elem == 'string' ) { 635 return document.querySelector( elem ); 636 } 637 return elem; 638 }; 639 640// ----- handleEvent ----- // 641 642// enable .ontype to trigger from .addEventListener( elem, 'type' ) 643 utils.handleEvent = function( event ) { 644 var method = 'on' + event.type; 645 if ( this[ method ] ) { 646 this[ method ]( event ); 647 } 648 }; 649 650// ----- filterFindElements ----- // 651 652 utils.filterFindElements = function( elems, selector ) { 653 // make array of elems 654 elems = utils.makeArray( elems ); 655 var ffElems = []; 656
657 elems.forEach( function( elem ) { 658 // check that elem is an actual element 659 if ( !( elem instanceof HTMLElement ) ) { 660 return; 661 } 662 // add elem if no selector 663 if ( !selector ) { 664 ffElems.push( elem ); 665 return; 666 } 667 // filter & find items if we have a selector 668 // filter 669 if ( matchesSelector( elem, selector ) ) { 670 ffElems.push( elem ); 671 } 672 // find children 673 var childElems = elem.querySelectorAll( selector ); 674 // concat childElems to filterFound array 675 for ( var i=0; i < childElems.length; i++ ) { 676 ffElems.push( childElems[i] ); 677 } 678 }); 679 680 return ffElems; 681 }; 682 683// ----- debounceMethod ----- // 684 685 utils.debounceMethod = function( _class, methodName, threshold ) { 686 threshold = threshold || 100; 687 // original method 688 var method = _class.prototype[ methodName ]; 689 var timeoutName = methodName + 'Timeout'; 690 691 _class.prototype[ methodName ] = function() { 692 var timeout = this[ timeoutName ]; 693 clearTimeout( timeout ); 694 695 var args = arguments; 696 var _this = this; 697 this[ timeoutName ] = setTimeout( function() { 698 method.apply( _this, args ); 699 delete _this[ timeoutName ]; 700 }, threshold ); 701 }; 702 }; 703 704// ----- docReady ----- // 705 706 utils.docReady = function( callback ) { 707 var readyState = document.readyState; 708 if ( readyState == 'complete' || readyState == 'interactive' ) { 709 // do async to allow for other scripts to run. metafizzy/flickity#441 710 setTimeout( callback ); 711 } else { 712 document.addEventListener( 'DOMContentLoaded', callback ); 713 } 714 }; 715 716// ----- htmlInit ----- // 717 718// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/ 719 utils.toDashed = function( str ) { 720 return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) { 721 return $1 + '-' + $2; 722 }).toLowerCase(); 723 }; 724 725 var console = window.console; 726 /** 727 * allow user to initialize classes via [data-namespace] or .js-namespace class 728 * htmlInit( Widget, 'widgetName' ) 729 * options are parsed from data-namespace-options 730 */ 731 utils.htmlInit = function( WidgetClass, namespace ) { 732 utils.docReady( function() { 733 var dashedNamespace = utils.toDashed( namespace ); 734 var dataAttr = 'data-' + dashedNamespace; 735 var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' ); 736 var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace ); 737 var elems = utils.makeArray( dataAttrElems ) 738 .concat( utils.makeArray( jsDashElems ) ); 739 var dataOptionsAttr = dataAttr + '-options'; 740 var jQuery = window.jQuery; 741 742 elems.forEach( function( elem ) { 743 var attr = elem.getAttribute( dataAttr ) || 744 elem.getAttribute( dataOptionsAttr ); 745 var options; 746 try { 747 options = attr && JSON.parse( attr ); 748 } catch ( error ) { 749 // log error, do not initialize 750 if ( console ) { 751 console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className + 752 ': ' + error ); 753 } 754 return; 755 } 756 // initialize 757 var instance = new WidgetClass( elem, options ); 758 // make available via $().data('namespace') 759 if ( jQuery ) { 760 jQuery.data( elem, namespace, instance ); 761 } 762 }); 763 764 }); 765 }; 766 767// ----- ----- // 768 769 return utils; 770 771})); 772 773// Flickity.Cell 774( function( window, factory ) { 775 // universal module definition 776 /* jshint strict: false */ 777 if ( typeof define == 'function' && define.amd ) { 778 // AMD 779 define( 'flickity/js/cell',[ 780 'get-size/get-size' 781 ], function( getSize ) { 782 return factory( window, getSize ); 783 }); 784 } else if ( typeof module == 'object' && module.exports ) { 785 // CommonJS 786 module.exports = factory( 787 window, 788 require('get-size') 789 ); 790 } else { 791 // browser global 792 window.Flickity = window.Flickity || {}; 793 window.Flickity.Cell = factory( 794 window, 795 window.getSize 796 ); 797 } 798 799}( window, function factory( window, getSize ) { 800 801 802 803 function Cell( elem, parent ) { 804 this.element = elem; 805 this.parent = parent; 806 807 this.create(); 808 } 809 810 var proto = Cell.prototype; 811 812 proto.create = function() { 813 this.element.style.position = 'absolute'; 814 this.element.setAttribute( 'aria-selected', 'false' ); 815 this.x = 0; 816 this.shift = 0; 817 }; 818 819 proto.destroy = function() { 820 // reset style 821 this.element.style.position = ''; 822 var side = this.parent.originSide; 823 this.element.removeAttribute('aria-selected'); 824 this.element.style[ side ] = ''; 825 }; 826 827 proto.getSize = function() { 828 this.size = getSize( this.element ); 829 }; 830 831 proto.setPosition = function( x ) { 832 this.x = x; 833 this.updateTarget(); 834 this.renderPosition( x ); 835 }; 836 837// setDefaultTarget v1 method, backwards compatibility, remove in v3 838 proto.updateTarget = proto.setDefaultTarget = function() { 839 var marginProperty = this.parent.originSide == 'left' ? 'marginLeft' : 'marginRight'; 840 this.target = this.x + this.size[ marginProperty ] + 841 this.size.width * this.parent.cellAlign; 842 }; 843 844 proto.renderPosition = function( x ) { 845 // render position of cell with in slider 846 var side = this.parent.originSide; 847 this.element.style[ side ] = this.parent.getPositionValue( x ); 848 }; 849 850 /** 851 * @param {Integer} factor - 0, 1, or -1 852 **/ 853 proto.wrapShift = function( shift ) { 854 this.shift = shift; 855 this.renderPosition( this.x + this.parent.slideableWidth * shift ); 856 }; 857 858 proto.remove = function() { 859 this.element.parentNode.removeChild( this.element ); 860 }; 861 862 return Cell; 863 864})); 865 866// slide 867( function( window, factory ) { 868 // universal module definition 869 /* jshint strict: false */ 870 if ( typeof define == 'function' && define.amd ) { 871 // AMD 872 define( 'flickity/js/slide',factory ); 873 } else if ( typeof module == 'object' && module.exports ) { 874 // CommonJS 875 module.exports = factory(); 876 } else { 877 // browser global 878 window.Flickity = window.Flickity || {}; 879 window.Flickity.Slide = factory(); 880 } 881 882}( window, function factory() { 883 'use strict'; 884 885 function Slide( parent ) { 886 this.parent = parent; 887 this.isOriginLeft = parent.originSide == 'left'; 888 this.cells = []; 889 this.outerWidth = 0; 890 this.height = 0; 891 } 892 893 var proto = Slide.prototype; 894 895 proto.addCell = function( cell ) { 896 this.cells.push( cell ); 897 this.outerWidth += cell.size.outerWidth; 898 this.height = Math.max( cell.size.outerHeight, this.height ); 899 // first cell stuff 900 if ( this.cells.length == 1 ) { 901 this.x = cell.x; // x comes from first cell 902 var beginMargin = this.isOriginLeft ? 'marginLeft' : 'marginRight'; 903 this.firstMargin = cell.size[ beginMargin ]; 904 } 905 }; 906 907 proto.updateTarget = function() { 908 var endMargin = this.isOriginLeft ? 'marginRight' : 'marginLeft'; 909 var lastCell = this.getLastCell(); 910 var lastMargin = lastCell ? lastCell.size[ endMargin ] : 0; 911 var slideWidth = this.outerWidth - ( this.firstMargin + lastMargin ); 912 this.target = this.x + this.firstMargin + slideWidth * this.parent.cellAlign; 913 }; 914 915 proto.getLastCell = function() { 916 return this.cells[ this.cells.length - 1 ]; 917 }; 918 919 proto.select = function() { 920 this.changeSelected( true ); 921 }; 922 923 proto.unselect = function() { 924 this.changeSelected( false ); 925 }; 926 927 proto.changeSelected = function( isSelected ) { 928 var classMethod = isSelected ? 'add' : 'remove';
929 this.cells.forEach( function( cell ) { 930 cell.element.classList[ classMethod ]('is-selected'); 931 cell.element.setAttribute( 'aria-selected', isSelected.toString() ); 932 }); 933 }; 934 935 proto.getCellElements = function() { 936 return this.cells.map( function( cell ) { 937 return cell.element; 938 }); 939 }; 940 941 return Slide; 942 943})); 944 945// animate 946( function( window, factory ) { 947 // universal module definition 948 /* jshint strict: false */ 949 if ( typeof define == 'function' && define.amd ) { 950 // AMD 951 define( 'flickity/js/animate',[ 952 'fizzy-ui-utils/utils' 953 ], function( utils ) { 954 return factory( window, utils ); 955 }); 956 } else if ( typeof module == 'object' && module.exports ) { 957 // CommonJS 958 module.exports = factory( 959 window, 960 require('fizzy-ui-utils') 961 ); 962 } else { 963 // browser global 964 window.Flickity = window.Flickity || {}; 965 window.Flickity.animatePrototype = factory( 966 window, 967 window.fizzyUIUtils 968 ); 969 } 970 971}( window, function factory( window, utils ) { 972 973 974 975// -------------------------- animate -------------------------- // 976 977 var proto = {}; 978 979 proto.startAnimation = function() { 980 if ( this.isAnimating ) { 981 return; 982 } 983 984 this.isAnimating = true; 985 this.restingFrames = 0; 986 this.animate(); 987 }; 988 989 proto.animate = function() { 990 this.applyDragForce(); 991 this.applySelectedAttraction(); 992 993 var previousX = this.x; 994 995 this.integratePhysics(); 996 this.positionSlider(); 997 this.settle( previousX ); 998 // animate next frame 999 if ( this.isAnimating ) { 1000 var _this = this; 1001 requestAnimationFrame( function animateFrame() { 1002 _this.animate(); 1003 }); 1004 } 1005 }; 1006 1007 proto.positionSlider = function() { 1008 var x = this.x; 1009 // wrap position around 1010 if ( this.options.wrapAround && this.cells.length > 1 ) { 1011 x = utils.modulo( x, this.slideableWidth ); 1012 x = x - this.slideableWidth; 1013 this.shiftWrapCells( x ); 1014 } 1015 1016 x = x + this.cursorPosition; 1017 // reverse if right-to-left and using transform 1018 x = this.options.rightToLeft ? -x : x; 1019 var value = this.getPositionValue( x ); 1020 // use 3D tranforms for hardware acceleration on iOS 1021 // but use 2D when settled, for better font-rendering 1022 this.slider.style.transform = this.isAnimating ? 1023 'translate3d(' + value + ',0,0)' : 'translateX(' + value + ')'; 1024 1025 // scroll event 1026 var firstSlide = this.slides[0]; 1027 if ( firstSlide ) { 1028 var positionX = -this.x - firstSlide.target; 1029 var progress = positionX / this.slidesWidth; 1030 this.dispatchEvent( 'scroll', null, [ progress, positionX ] ); 1031 } 1032 }; 1033 1034 proto.positionSliderAtSelected = function() { 1035 if ( !this.cells.length ) { 1036 return; 1037 } 1038 this.x = -this.selectedSlide.target; 1039 this.velocity = 0; // stop wobble 1040 this.positionSlider(); 1041 }; 1042 1043 proto.getPositionValue = function( position ) { 1044 if ( this.options.percentPosition ) { 1045 // percent position, round to 2 digits, like 12.34% 1046 return ( Math.round( ( position / this.size.innerWidth ) * 10000 ) * 0.01 )+ '%'; 1047 } else { 1048 // pixel positioning 1049 return Math.round( position ) + 'px'; 1050 } 1051 }; 1052 1053 proto.settle = function( previousX ) { 1054 // keep track of frames where x hasn't moved 1055 if ( !this.isPointerDown && Math.round( this.x * 100 ) == Math.round( previousX * 100 ) ) { 1056 this.restingFrames++; 1057 } 1058 // stop animating if resting for 3 or more frames 1059 if ( this.restingFrames > 2 ) { 1060 this.isAnimating = false; 1061 delete this.isFreeScrolling; 1062 // render position with translateX when settled 1063 this.positionSlider(); 1064 this.dispatchEvent( 'settle', null, [ this.selectedIndex ] ); 1065 } 1066 }; 1067 1068 proto.shiftWrapCells = function( x ) { 1069 // shift before cells 1070 var beforeGap = this.cursorPosition + x; 1071 this._shiftCells( this.beforeShiftCells, beforeGap, -1 ); 1072 // shift after cells 1073 var afterGap = this.size.innerWidth - ( x + this.slideableWidth + this.cursorPosition ); 1074 this._shiftCells( this.afterShiftCells, afterGap, 1 ); 1075 }; 1076 1077 proto._shiftCells = function( cells, gap, shift ) { 1078 for ( var i=0; i < cells.length; i++ ) { 1079 var cell = cells[i]; 1080 var cellShift = gap > 0 ? shift : 0; 1081 cell.wrapShift( cellShift ); 1082 gap -= cell.size.outerWidth; 1083 } 1084 }; 1085 1086 proto._unshiftCells = function( cells ) { 1087 if ( !cells || !cells.length ) { 1088 return; 1089 } 1090 for ( var i=0; i < cells.length; i++ ) { 1091 cells[i].wrapShift( 0 ); 1092 } 1093 }; 1094 1095// -------------------------- physics -------------------------- // 1096 1097 proto.integratePhysics = function() { 1098 this.x += this.velocity; 1099 this.velocity *= this.getFrictionFactor(); 1100 }; 1101 1102 proto.applyForce = function( force ) { 1103 this.velocity += force; 1104 }; 1105 1106 proto.getFrictionFactor = function() { 1107 return 1 - this.options[ this.isFreeScrolling ? 'freeScrollFriction' : 'friction' ]; 1108 }; 1109 1110 proto.getRestingPosition = function() { 1111 // my thanks to Steven Wittens, who simplified this math greatly 1112 return this.x + this.velocity / ( 1 - this.getFrictionFactor() ); 1113 }; 1114 1115 proto.applyDragForce = function() { 1116 if ( !this.isDraggable || !this.isPointerDown ) { 1117 return; 1118 } 1119 // change the position to drag position by applying force 1120 var dragVelocity = this.dragX - this.x; 1121 var dragForce = dragVelocity - this.velocity; 1122 this.applyForce( dragForce ); 1123 }; 1124 1125 proto.applySelectedAttraction = function() { 1126 // do not attract if pointer down or no slides 1127 var dragDown = this.isDraggable && this.isPointerDown; 1128 if ( dragDown || this.isFreeScrolling || !this.slides.length ) { 1129 return; 1130 } 1131 var distance = this.selectedSlide.target * -1 - this.x; 1132 var force = distance * this.options.selectedAttraction; 1133 this.applyForce( force ); 1134 }; 1135 1136 return proto; 1137 1138})); 1139 1140// Flickity main 1141( function( window, factory ) { 1142 // universal module definition 1143 /* jshint strict: false */ 1144 if ( typeof define == 'function' && define.amd ) { 1145 // AMD 1146 define( 'flickity/js/flickity',[ 1147 'ev-emitter/ev-emitter', 1148 'get-size/get-size', 1149 'fizzy-ui-utils/utils', 1150 './cell', 1151 './slide', 1152 './animate' 1153 ], function( EvEmitter, getSize, utils, Cell, Slide, animatePrototype ) { 1154 return factory( window, EvEmitter, getSize, utils, Cell, Slide, animatePrototype ); 1155 }); 1156 } else if ( typeof module == 'object' && module.exports ) { 1157 // CommonJS 1158 module.exports = factory( 1159 window, 1160 require('ev-emitter'), 1161 require('get-size'), 1162 require('fizzy-ui-utils'), 1163 require('./cell'), 1164 require('./slide'), 1165 require('./animate') 1166 ); 1167 } else { 1168 // browser global 1169 var _Flickity = window.Flickity; 1170 1171 window.Flickity = factory( 1172 window, 1173 window.EvEmitter, 1174 window.getSize, 1175 window.fizzyUIUtils, 1176 _Flickity.Cell, 1177 _Flickity.Slide, 1178 _Flickity.animatePrototype 1179 ); 1180 } 1181 1182}( window, function factory( window, EvEmitter, getSize, 1183 utils, Cell, Slide, animatePrototype ) { 1184 1185 1186 1187// vars 1188 var jQuery = window.jQuery; 1189 var getComputedStyle = window.getComputedStyle; 1190 var console = window.console; 1191 1192 function moveElements( elems, toElem ) { 1193 elems = utils.makeArray( elems ); 1194 while ( elems.length ) { 1195 toElem.appendChild( elems.shift() ); 1196 } 1197 } 1198 1199// -------------------------- Flickity -------------------------- // 1200 1201// globally unique identifiers 1202 var GUID = 0;
1203// internal store of all Flickity intances 1204 var instances = {}; 1205 1206 function Flickity( element, options ) { 1207 var queryElement = utils.getQueryElement( element ); 1208 if ( !queryElement ) { 1209 if ( console ) { 1210 console.error( 'Bad element for Flickity: ' + ( queryElement || element ) ); 1211 } 1212 return; 1213 } 1214 this.element = queryElement; 1215 // do not initialize twice on same element 1216 if ( this.element.flickityGUID ) { 1217 var instance = instances[ this.element.flickityGUID ]; 1218 instance.option( options ); 1219 return instance; 1220 } 1221 1222 // add jQuery 1223 if ( jQuery ) { 1224 this.$element = jQuery( this.element ); 1225 } 1226 // options 1227 this.options = utils.extend( {}, this.constructor.defaults ); 1228 this.option( options ); 1229 1230 // kick things off 1231 this._create(); 1232 } 1233 1234 Flickity.defaults = { 1235 accessibility: true, 1236 // adaptiveHeight: false, 1237 cellAlign: 'center', 1238 // cellSelector: undefined, 1239 // contain: false, 1240 freeScrollFriction: 0.075, // friction when free-scrolling 1241 friction: 0.28, // friction when selecting 1242 namespaceJQueryEvents: true, 1243 // initialIndex: 0, 1244 percentPosition: true, 1245 resize: true, 1246 selectedAttraction: 0.025, 1247 setGallerySize: true 1248 // watchCSS: false, 1249 // wrapAround: false 1250 }; 1251 1252// hash of methods triggered on _create() 1253 Flickity.createMethods = []; 1254 1255 var proto = Flickity.prototype; 1256// inherit EventEmitter 1257 utils.extend( proto, EvEmitter.prototype ); 1258 1259 proto._create = function() { 1260 // add id for Flickity.data 1261 var id = this.guid = ++GUID; 1262 this.element.flickityGUID = id; // expando 1263 instances[ id ] = this; // associate via id 1264 // initial properties 1265 this.selectedIndex = 0; 1266 // how many frames slider has been in same position 1267 this.restingFrames = 0; 1268 // initial physics properties 1269 this.x = 0; 1270 this.velocity = 0; 1271 this.originSide = this.options.rightToLeft ? 'right' : 'left'; 1272 // create viewport & slider 1273 this.viewport = document.createElement('div'); 1274 this.viewport.className = 'flickity-viewport'; 1275 this._createSlider(); 1276 1277 if ( this.options.resize || this.options.watchCSS ) { 1278 window.addEventListener( 'resize', this ); 1279 } 1280 1281 // add listeners from on option 1282 for ( var eventName in this.options.on ) { 1283 var listener = this.options.on[ eventName ]; 1284 this.on( eventName, listener ); 1285 } 1286 1287 Flickity.createMethods.forEach( function( method ) { 1288 this[ method ](); 1289 }, this ); 1290 1291 if ( this.options.watchCSS ) { 1292 this.watchCSS(); 1293 } else { 1294 this.activate(); 1295 } 1296 1297 }; 1298 1299 /** 1300 * set options 1301 * @param {Object} opts 1302 */ 1303 proto.option = function( opts ) { 1304 utils.extend( this.options, opts ); 1305 }; 1306 1307 proto.activate = function() { 1308 if ( this.isActive ) { 1309 return; 1310 } 1311 this.isActive = true; 1312 this.element.classList.add('flickity-enabled'); 1313 if ( this.options.rightToLeft ) { 1314 this.element.classList.add('flickity-rtl'); 1315 } 1316
1317 this.getSize(); 1318 // move initial cell elements so they can be loaded as cells 1319 var cellElems = this._filterFindCellElements( this.element.children ); 1320 moveElements( cellElems, this.slider ); 1321 this.viewport.appendChild( this.slider ); 1322 this.element.appendChild( this.viewport ); 1323 // get cells from children 1324 this.reloadCells(); 1325 1326 if ( this.options.accessibility ) { 1327 // allow element to focusable 1328 this.element.tabIndex = 0; 1329 // listen for key presses 1330 this.element.addEventListener( 'keydown', this ); 1331 } 1332 1333 this.emitEvent('activate'); 1334 1335 var index; 1336 var initialIndex = this.options.initialIndex; 1337 if ( this.isInitActivated ) { 1338 index = this.selectedIndex; 1339 } else if ( initialIndex !== undefined ) { 1340 index = this.cells[ initialIndex ] ? initialIndex : 0; 1341 } else { 1342 index = 0; 1343 } 1344 // select instantly 1345 this.select( index, false, true ); 1346 // flag for initial activation, for using initialIndex 1347 this.isInitActivated = true; 1348 // ready event. #493 1349 this.dispatchEvent('ready'); 1350 }; 1351 1352// slider positions the cells 1353 proto._createSlider = function() { 1354 // slider element does all the positioning 1355 var slider = document.createElement('div'); 1356 slider.className = 'flickity-slider'; 1357 slider.style[ this.originSide ] = 0; 1358 this.slider = slider; 1359 }; 1360 1361 proto._filterFindCellElements = function( elems ) { 1362 return utils.filterFindElements( elems, this.options.cellSelector ); 1363 }; 1364 1365// goes through all children 1366 proto.reloadCells = function() { 1367 // collection of item elements 1368 this.cells = this._makeCells( this.slider.children ); 1369 this.positionCells(); 1370 this._getWrapShiftCells(); 1371 this.setGallerySize(); 1372 }; 1373 1374 /** 1375 * turn elements into Flickity.Cells 1376 * @param {Array or NodeList or HTMLElement} elems 1377 * @returns {Array} items - collection of new Flickity Cells 1378 */ 1379 proto._makeCells = function( elems ) { 1380 var cellElems = this._filterFindCellElements( elems ); 1381 1382 // create new Flickity for collection 1383 var cells = cellElems.map( function( cellElem ) { 1384 return new Cell( cellElem, this ); 1385 }, this ); 1386 1387 return cells; 1388 }; 1389 1390 proto.getLastCell = function() { 1391 return this.cells[ this.cells.length - 1 ]; 1392 }; 1393 1394 proto.getLastSlide = function() { 1395 return this.slides[ this.slides.length - 1 ]; 1396 }; 1397 1398// positions all cells 1399 proto.positionCells = function() { 1400 // size all cells 1401 this._sizeCells( this.cells ); 1402 // position all cells 1403 this._positionCells( 0 ); 1404 }; 1405 1406 /** 1407 * position certain cells 1408 * @param {Integer} index - which cell to start with 1409 */ 1410 proto._positionCells = function( index ) { 1411 index = index || 0; 1412 // also measure maxCellHeight 1413 // start 0 if positioning all cells 1414 this.maxCellHeight = index ? this.maxCellHeight || 0 : 0; 1415 var cellX = 0; 1416 // get cellX 1417 if ( index > 0 ) { 1418 var startCell = this.cells[ index - 1 ]; 1419 cellX = startCell.x + startCell.size.outerWidth; 1420 } 1421 var len = this.cells.length; 1422 for ( var i=index; i < len; i++ ) { 1423 var cell = this.cells[i]; 1424 cell.setPosition( cellX ); 1425 cellX += cell.size.outerWidth; 1426 this.maxCellHeight = Math.max( cell.size.outerHeight, this.maxCellHeight ); 1427 } 1428 // keep track of cellX for wrap-around 1429 this.slideableWidth = cellX; 1430 // slides 1431 this.updateSlides(); 1432 // contain slides target 1433 this._containSlides(); 1434 // update slidesWidth 1435 this.slidesWidth = len ? this.getLastSlide().target - this.slides[0].target : 0; 1436 }; 1437 1438 /** 1439 * cell.getSize() on multiple cells 1440 * @param {Array} cells 1441 */ 1442 proto._sizeCells = function( cells ) {
1443 cells.forEach( function( cell ) { 1444 cell.getSize(); 1445 }); 1446 }; 1447 1448// -------------------------- -------------------------- // 1449 1450 proto.updateSlides = function() { 1451 this.slides = []; 1452 if ( !this.cells.length ) { 1453 return; 1454 } 1455 1456 var slide = new Slide( this ); 1457 this.slides.push( slide ); 1458 var isOriginLeft = this.originSide == 'left'; 1459 var nextMargin = isOriginLeft ? 'marginRight' : 'marginLeft'; 1460 1461 var canCellFit = this._getCanCellFit(); 1462 1463 this.cells.forEach( function( cell, i ) { 1464 // just add cell if first cell in slide 1465 if ( !slide.cells.length ) { 1466 slide.addCell( cell ); 1467 return; 1468 } 1469 1470 var slideWidth = ( slide.outerWidth - slide.firstMargin ) + 1471 ( cell.size.outerWidth - cell.size[ nextMargin ] ); 1472 1473 if ( canCellFit.call( this, i, slideWidth ) ) { 1474 slide.addCell( cell ); 1475 } else { 1476 // doesn't fit, new slide 1477 slide.updateTarget(); 1478 1479 slide = new Slide( this ); 1480 this.slides.push( slide ); 1481 slide.addCell( cell ); 1482 } 1483 }, this ); 1484 // last slide 1485 slide.updateTarget(); 1486 // update .selectedSlide 1487 this.updateSelectedSlide(); 1488 }; 1489 1490 proto._getCanCellFit = function() { 1491 var groupCells = this.options.groupCells; 1492 if ( !groupCells ) { 1493 return function() { 1494 return false; 1495 }; 1496 } else if ( typeof groupCells == 'number' ) { 1497 // group by number. 3 -> [0,1,2], [3,4,5], ... 1498 var number = parseInt( groupCells, 10 ); 1499 return function( i ) { 1500 return ( i % number ) !== 0; 1501 }; 1502 } 1503 // default, group by width of slide 1504 // parse '75% 1505 var percentMatch = typeof groupCells == 'string' && 1506 groupCells.match(/^(\d+)%$/); 1507 var percent = percentMatch ? parseInt( percentMatch[1], 10 ) / 100 : 1; 1508 return function( i, slideWidth ) { 1509 return slideWidth <= ( this.size.innerWidth + 1 ) * percent; 1510 }; 1511 }; 1512 1513// alias _init for jQuery plugin .flickity() 1514 proto._init = 1515 proto.reposition = function() { 1516 this.positionCells(); 1517 this.positionSliderAtSelected(); 1518 }; 1519 1520 proto.getSize = function() { 1521 this.size = getSize( this.element ); 1522 this.setCellAlign(); 1523 this.cursorPosition = this.size.innerWidth * this.cellAlign; 1524 }; 1525 1526 var cellAlignShorthands = { 1527 // cell align, then based on origin side 1528 center: { 1529 left: 0.5, 1530 right: 0.5 1531 }, 1532 left: { 1533 left: 0, 1534 right: 1 1535 }, 1536 right: { 1537 right: 0, 1538 left: 1 1539 } 1540 }; 1541 1542 proto.setCellAlign = function() { 1543 var shorthand = cellAlignShorthands[ this.options.cellAlign ]; 1544 this.cellAlign = shorthand ? shorthand[ this.originSide ] : this.options.cellAlign; 1545 }; 1546 1547 proto.setGallerySize = function() { 1548 if ( this.options.setGallerySize ) { 1549 var height = this.options.adaptiveHeight && this.selectedSlide ? 1550 this.selectedSlide.height : this.maxCellHeight; 1551 this.viewport.style.height = height + 'px'; 1552 } 1553 }; 1554 1555 proto._getWrapShiftCells = function() { 1556 // only for wrap-around 1557 if ( !this.options.wrapAround ) { 1558 return; 1559 } 1560 // unshift previous cells 1561 this._unshiftCells( this.beforeShiftCells ); 1562 this._unshiftCells( this.afterShiftCells ); 1563 // get before cells 1564 // initial gap 1565 var gapX = this.cursorPosition; 1566 var cellIndex = this.cells.length - 1; 1567 this.beforeShiftCells = this._getGapCells( gapX, cellIndex, -1 ); 1568 // get after cells 1569 // ending gap between last cell and end of gallery viewport 1570 gapX = this.size.innerWidth - this.cursorPosition; 1571 // start cloning at first cell, working forwards 1572 this.afterShiftCells = this._getGapCells( gapX, 0, 1 ); 1573 }; 1574 1575 proto._getGapCells = function( gapX, cellIndex, increment ) { 1576 // keep adding cells until the cover the initial gap 1577 var cells = []; 1578 while ( gapX > 0 ) { 1579 var cell = this.cells[ cellIndex ]; 1580 if ( !cell ) { 1581 break; 1582 } 1583 cells.push( cell ); 1584 cellIndex += increment; 1585 gapX -= cell.size.outerWidth; 1586 } 1587 return cells; 1588 }; 1589 1590// ----- contain ----- // 1591 1592// contain cell targets so no excess sliding 1593 proto._containSlides = function() { 1594 if ( !this.options.contain || this.options.wrapAround || !this.cells.length ) { 1595 return; 1596 } 1597 var isRightToLeft = this.options.rightToLeft; 1598 var beginMargin = isRightToLeft ? 'marginRight' : 'marginLeft'; 1599 var endMargin = isRightToLeft ? 'marginLeft' : 'marginRight'; 1600 var contentWidth = this.slideableWidth - this.getLastCell().size[ endMargin ]; 1601 // content is less than gallery size 1602 var isContentSmaller = contentWidth < this.size.innerWidth; 1603 // bounds 1604 var beginBound = this.cursorPosition + this.cells[0].size[ beginMargin ]; 1605 var endBound = contentWidth - this.size.innerWidth * ( 1 - this.cellAlign ); 1606 // contain each cell target
1607 this.slides.forEach( function( slide ) { 1608 if ( isContentSmaller ) { 1609 // all cells fit inside gallery 1610 slide.target = contentWidth * this.cellAlign; 1611 } else { 1612 // contain to bounds 1613 slide.target = Math.max( slide.target, beginBound ); 1614 slide.target = Math.min( slide.target, endBound ); 1615 } 1616 }, this ); 1617 }; 1618 1619// ----- ----- // 1620 1621 /** 1622 * emits events via eventEmitter and jQuery events 1623 * @param {String} type - name of event 1624 * @param {Event} event - original event 1625 * @param {Array} args - extra arguments 1626 */ 1627 proto.dispatchEvent = function( type, event, args ) { 1628 var emitArgs = event ? [ event ].concat( args ) : args; 1629 this.emitEvent( type, emitArgs ); 1630 1631 if ( jQuery && this.$element ) { 1632 // default trigger with type if no event 1633 type += this.options.namespaceJQueryEvents ? '.flickity' : ''; 1634 var $event = type; 1635 if ( event ) { 1636 // create jQuery event 1637 var jQEvent = jQuery.Event( event ); 1638 jQEvent.type = type; 1639 $event = jQEvent; 1640 } 1641 this.$element.trigger( $event, args ); 1642 } 1643 }; 1644 1645// -------------------------- select -------------------------- // 1646 1647 /** 1648 * @param {Integer} index - index of the slide 1649 * @param {Boolean} isWrap - will wrap-around to last/first if at the end 1650 * @param {Boolean} isInstant - will immediately set position at selected cell 1651 */ 1652 proto.select = function( index, isWrap, isInstant ) { 1653 if ( !this.isActive ) { 1654 return; 1655 } 1656 index = parseInt( index, 10 ); 1657 this._wrapSelect( index ); 1658 1659 if ( this.options.wrapAround || isWrap ) { 1660 index = utils.modulo( index, this.slides.length ); 1661 } 1662 // bail if invalid index 1663 if ( !this.slides[ index ] ) { 1664 return; 1665 } 1666 var prevIndex = this.selectedIndex; 1667 this.selectedIndex = index; 1668 this.updateSelectedSlide(); 1669 if ( isInstant ) { 1670 this.positionSliderAtSelected(); 1671 } else { 1672 this.startAnimation(); 1673 } 1674 if ( this.options.adaptiveHeight ) { 1675 this.setGallerySize(); 1676 } 1677 // events 1678 this.dispatchEvent( 'select', null, [ index ] ); 1679 // change event if new index 1680 if ( index != prevIndex ) { 1681 this.dispatchEvent( 'change', null, [ index ] ); 1682 } 1683 // old v1 event name, remove in v3 1684 this.dispatchEvent('cellSelect'); 1685 }; 1686 1687// wraps position for wrapAround, to move to closest slide. #113 1688 proto._wrapSelect = function( index ) { 1689 var len = this.slides.length; 1690 var isWrapping = this.options.wrapAround && len > 1; 1691 if ( !isWrapping ) { 1692 return index; 1693 } 1694 var wrapIndex = utils.modulo( index, len ); 1695 // go to shortest 1696 var delta = Math.abs( wrapIndex - this.selectedIndex ); 1697 var backWrapDelta = Math.abs( ( wrapIndex + len ) - this.selectedIndex ); 1698 var forewardWrapDelta = Math.abs( ( wrapIndex - len ) - this.selectedIndex ); 1699 if ( !this.isDragSelect && backWrapDelta < delta ) { 1700 index += len; 1701 } else if ( !this.isDragSelect && forewardWrapDelta < delta ) { 1702 index -= len; 1703 } 1704 // wrap position so slider is within normal area 1705 if ( index < 0 ) { 1706 this.x -= this.slideableWidth; 1707 } else if ( index >= len ) { 1708 this.x += this.slideableWidth; 1709 } 1710 }; 1711 1712 proto.previous = function( isWrap, isInstant ) { 1713 this.select( this.selectedIndex - 1, isWrap, isInstant ); 1714 }; 1715 1716 proto.next = function( isWrap, isInstant ) { 1717 this.select( this.selectedIndex + 1, isWrap, isInstant ); 1718 }; 1719 1720 proto.updateSelectedSlide = function() { 1721 var slide = this.slides[ this.selectedIndex ]; 1722 // selectedIndex could be outside of slides, if triggered before resize() 1723 if ( !slide ) { 1724 return; 1725 } 1726 // unselect previous selected slide 1727 this.unselectSelectedSlide(); 1728 // update new selected slide 1729 this.selectedSlide = slide; 1730 slide.select(); 1731 this.selectedCells = slide.cells; 1732 this.selectedElements = slide.getCellElements(); 1733 // HACK: selectedCell & selectedElement is first cell in slide, backwards compatibility 1734 // Remove in v3? 1735 this.selectedCell = slide.cells[0]; 1736 this.selectedElement = this.selectedElements[0]; 1737 }; 1738 1739 proto.unselectSelectedSlide = function() { 1740 if ( this.selectedSlide ) { 1741 this.selectedSlide.unselect(); 1742 } 1743 }; 1744 1745 /** 1746 * select slide from number or cell element 1747 * @param {Element or Number} elem 1748 */ 1749 proto.selectCell = function( value, isWrap, isInstant ) { 1750 // get cell 1751 var cell = this.queryCell( value ); 1752 if ( !cell ) { 1753 return; 1754 } 1755 1756 var index = this.getCellSlideIndex( cell ); 1757 this.select( index, isWrap, isInstant ); 1758 }; 1759 1760 proto.getCellSlideIndex = function( cell ) { 1761 // get index of slides that has cell 1762 for ( var i=0; i < this.slides.length; i++ ) { 1763 var slide = this.slides[i];
1764 var index = slide.cells.indexOf( cell ); 1765 if ( index != -1 ) { 1766 return i; 1767 } 1768 } 1769 }; 1770 1771// -------------------------- get cells -------------------------- // 1772 1773 /** 1774 * get Flickity.Cell, given an Element 1775 * @param {Element} elem 1776 * @returns {Flickity.Cell} item 1777 */ 1778 proto.getCell = function( elem ) { 1779 // loop through cells to get the one that matches 1780 for ( var i=0; i < this.cells.length; i++ ) { 1781 var cell = this.cells[i]; 1782 if ( cell.element == elem ) { 1783 return cell; 1784 } 1785 } 1786 }; 1787 1788 /** 1789 * get collection of Flickity.Cells, given Elements 1790 * @param {Element, Array, NodeList} elems 1791 * @returns {Array} cells - Flickity.Cells 1792 */ 1793 proto.getCells = function( elems ) { 1794 elems = utils.makeArray( elems ); 1795 var cells = []; 1796 elems.forEach( function( elem ) { 1797 var cell = this.getCell( elem ); 1798 if ( cell ) { 1799 cells.push( cell ); 1800 } 1801 }, this ); 1802 return cells; 1803 }; 1804 1805 /** 1806 * get cell elements 1807 * @returns {Array} cellElems 1808 */ 1809 proto.getCellElements = function() { 1810 return this.cells.map( function( cell ) { 1811 return cell.element; 1812 }); 1813 }; 1814 1815 /** 1816 * get parent cell from an element 1817 * @param {Element} elem 1818 * @returns {Flickit.Cell} cell 1819 */ 1820 proto.getParentCell = function( elem ) { 1821 // first check if elem is cell 1822 var cell = this.getCell( elem ); 1823 if ( cell ) { 1824 return cell; 1825 } 1826 // try to get parent cell elem 1827 elem = utils.getParent( elem, '.flickity-slider > *' ); 1828 return this.getCell( elem ); 1829 }; 1830 1831 /** 1832 * get cells adjacent to a slide 1833 * @param {Integer} adjCount - number of adjacent slides 1834 * @param {Integer} index - index of slide to start 1835 * @returns {Array} cells - array of Flickity.Cells 1836 */ 1837 proto.getAdjacentCellElements = function( adjCount, index ) { 1838 if ( !adjCount ) { 1839 return this.selectedSlide.getCellElements(); 1840 } 1841 index = index === undefined ? this.selectedIndex : index; 1842 1843 var len = this.slides.length; 1844 if ( 1 + ( adjCount * 2 ) >= len ) { 1845 return this.getCellElements(); 1846 } 1847 1848 var cellElems = []; 1849 for ( var i = index - adjCount; i <= index + adjCount ; i++ ) { 1850 var slideIndex = this.options.wrapAround ? utils.modulo( i, len ) : i; 1851 var slide = this.slides[ slideIndex ]; 1852 if ( slide ) { 1853 cellElems = cellElems.concat( slide.getCellElements() ); 1854 } 1855 } 1856 return cellElems; 1857 }; 1858 1859 /** 1860 * select slide from number or cell element 1861 * @param {Element, Selector String, or Number} selector 1862 */ 1863 proto.queryCell = function( selector ) { 1864 if ( typeof selector == 'number' ) { 1865 // use number as index 1866 return this.cells[ selector ]; 1867 } 1868 if ( typeof selector == 'string' ) { 1869 // use string as selector, get element 1870 selector = this.element.querySelector( selector ); 1871 } 1872 // get cell from element 1873 return this.getCell( selector ); 1874 }; 1875 1876// -------------------------- events -------------------------- // 1877 1878 proto.uiChange = function() { 1879 this.emitEvent('uiChange'); 1880 }; 1881 1882 proto.childUIPointerDown = function( event ) { 1883 this.emitEvent( 'childUIPointerDown', [ event ] ); 1884 }; 1885 1886// ----- resize ----- // 1887 1888 proto.onresize = function() { 1889 this.watchCSS(); 1890 this.resize(); 1891 }; 1892 1893 utils.debounceMethod( Flickity, 'onresize', 150 ); 1894 1895 proto.resize = function() { 1896 if ( !this.isActive ) { 1897 return; 1898 }
1899 this.getSize(); 1900 // wrap values 1901 if ( this.options.wrapAround ) { 1902 this.x = utils.modulo( this.x, this.slideableWidth ); 1903 } 1904 this.positionCells(); 1905 this._getWrapShiftCells(); 1906 this.setGallerySize(); 1907 this.emitEvent('resize'); 1908 // update selected index for group slides, instant 1909 // TODO: position can be lost between groups of various numbers 1910 var selectedElement = this.selectedElements && this.selectedElements[0]; 1911 this.selectCell( selectedElement, false, true ); 1912 }; 1913 1914// watches the :after property, activates/deactivates 1915 proto.watchCSS = function() { 1916 var watchOption = this.options.watchCSS; 1917 if ( !watchOption ) { 1918 return; 1919 } 1920 1921 var afterContent = getComputedStyle( this.element, ':after' ).content; 1922 // activate if :after { content: 'flickity' } 1923 if ( afterContent.indexOf('flickity') != -1 ) { 1924 this.activate(); 1925 } else { 1926 this.deactivate(); 1927 } 1928 }; 1929 1930// ----- keydown ----- // 1931 1932// go previous/next if left/right keys pressed 1933 proto.onkeydown = function( event ) { 1934 // only work if element is in focus 1935 var isNotFocused = document.activeElement && document.activeElement != this.element; 1936 if ( !this.options.accessibility ||isNotFocused ) { 1937 return; 1938 } 1939 1940 var handler = Flickity.keyboardHandlers[ event.keyCode ]; 1941 if ( handler ) { 1942 handler.call( this ); 1943 } 1944 }; 1945 1946 Flickity.keyboardHandlers = { 1947 // left arrow 1948 37: function() { 1949 var leftMethod = this.options.rightToLeft ? 'next' : 'previous'; 1950 this.uiChange(); 1951 this[ leftMethod ](); 1952 }, 1953 // right arrow 1954 39: function() { 1955 var rightMethod = this.options.rightToLeft ? 'previous' : 'next'; 1956 this.uiChange(); 1957 this[ rightMethod ](); 1958 }, 1959 }; 1960 1961// ----- focus ----- // 1962 1963 proto.focus = function() { 1964 // TODO remove scrollTo once focus options gets more support 1965 // https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/focus#Browser_compatibility 1966 var prevScrollY = window.pageYOffset; 1967 this.element.focus({ preventScroll: true }); 1968 // hack to fix scroll jump after focus, #76 1969 if ( window.pageYOffset != prevScrollY ) { 1970 window.scrollTo( window.pageXOffset, prevScrollY ); 1971 } 1972 }; 1973 1974// -------------------------- destroy -------------------------- // 1975 1976// deactivate all Flickity functionality, but keep stuff available 1977 proto.deactivate = function() { 1978 if ( !this.isActive ) { 1979 return; 1980 } 1981 this.element.classList.remove('flickity-enabled'); 1982 this.element.classList.remove('flickity-rtl'); 1983 this.unselectSelectedSlide(); 1984 // destroy cells 1985 this.cells.forEach( function( cell ) { 1986 cell.destroy(); 1987 }); 1988 this.element.removeChild( this.viewport ); 1989 // move child elements back into element 1990 moveElements( this.slider.children, this.element ); 1991 if ( this.options.accessibility ) { 1992 this.element.removeAttribute('tabIndex'); 1993 this.element.removeEventListener( 'keydown', this ); 1994 } 1995 // set flags 1996 this.isActive = false; 1997 this.emitEvent('deactivate'); 1998 }; 1999 2000 proto.destroy = function() { 2001 this.deactivate(); 2002 window.removeEventListener( 'resize', this ); 2003 this.emitEvent('destroy'); 2004 if ( jQuery && this.$element ) { 2005 jQuery.removeData( this.element, 'flickity' ); 2006 } 2007 delete this.element.flickityGUID; 2008 delete instances[ this.guid ]; 2009 }; 2010 2011// -------------------------- prototype -------------------------- // 2012 2013 utils.extend( proto, animatePrototype ); 2014 2015// -------------------------- extras -------------------------- // 2016 2017 /** 2018 * get Flickity instance from element 2019 * @param {Element} elem 2020 * @returns {Flickity} 2021 */ 2022 Flickity.data = function( elem ) { 2023 elem = utils.getQueryElement( elem ); 2024 var id = elem && elem.flickityGUID; 2025 return id && instances[ id ]; 2026 }; 2027 2028 utils.htmlInit( Flickity, 'flickity' ); 2029 2030 if ( jQuery && jQuery.bridget ) { 2031 jQuery.bridget( 'flickity', Flickity ); 2032 } 2033 2034// set internal jQuery, for Webpack + jQuery v3, #478 2035 Flickity.setJQuery = function( jq ) { 2036 jQuery = jq; 2037 }; 2038 2039 Flickity.Cell = Cell; 2040 2041 return Flickity; 2042 2043})); 2044 2045/*! 2046 * Unipointer v2.3.0 2047 * base class for doing one thing with pointer event 2048 * MIT license 2049 */ 2050 2051/*jshint browser: true, undef: true, unused: true, strict: true */ 2052 2053( function( window, factory ) { 2054 // universal module definition 2055 /* jshint strict: false */ /*global define, module, require */ 2056 if ( typeof define == 'function' && define.amd ) { 2057 // AMD 2058 define( 'unipointer/unipointer',[ 2059 'ev-emitter/ev-emitter' 2060 ], function( EvEmitter ) { 2061 return factory( window, EvEmitter ); 2062 }); 2063 } else if ( typeof module == 'object' && module.exports ) { 2064 // CommonJS 2065 module.exports = factory( 2066 window, 2067 require('ev-emitter') 2068 ); 2069 } else { 2070 // browser global 2071 window.Unipointer = factory( 2072 window, 2073 window.EvEmitter 2074 ); 2075 } 2076 2077}( window, function factory( window, EvEmitter ) { 2078 2079 2080 2081 function noop() {} 2082 2083 function Unipointer() {} 2084 2085// inherit EvEmitter 2086 var proto = Unipointer.prototype = Object.create( EvEmitter.prototype ); 2087 2088 proto.bindStartEvent = function( elem ) { 2089 this._bindStartEvent( elem, true ); 2090 }; 2091 2092 proto.unbindStartEvent = function( elem ) { 2093 this._bindStartEvent( elem, false ); 2094 }; 2095 2096 /** 2097 * Add or remove start event 2098 * @param {Boolean} isAdd - remove if falsey 2099 */ 2100 proto._bindStartEvent = function( elem, isAdd ) { 2101 // munge isAdd, default to true 2102 isAdd = isAdd === undefined ? true : isAdd;
vendor: 8,429 bytes, lines 2103-2407
2103 var bindMethod = isAdd ? 'addEventListener' : 'removeEventListener'; 2104 2105 // default to mouse events 2106 var startEvent = 'mousedown'; 2107 if ( window.PointerEvent ) { 2108 // Pointer Events 2109 startEvent = 'pointerdown'; 2110 } else if ( 'ontouchstart' in window ) { 2111 // Touch Events. iOS Safari 2112 startEvent = 'touchstart'; 2113 } 2114 elem[ bindMethod ]( startEvent, this ); 2115 }; 2116 2117// trigger handler methods for events 2118 proto.handleEvent = function( event ) { 2119 var method = 'on' + event.type; 2120 if ( this[ method ] ) { 2121 this[ method ]( event ); 2122 } 2123 }; 2124 2125// returns the touch that we're keeping track of 2126 proto.getTouch = function( touches ) { 2127 for ( var i=0; i < touches.length; i++ ) { 2128 var touch = touches[i]; 2129 if ( touch.identifier == this.pointerIdentifier ) { 2130 return touch; 2131 } 2132 } 2133 }; 2134 2135// ----- start event ----- // 2136 2137 proto.onmousedown = function( event ) { 2138 // dismiss clicks from right or middle buttons 2139 var button = event.button; 2140 if ( button && ( button !== 0 && button !== 1 ) ) { 2141 return; 2142 } 2143 this._pointerDown( event, event ); 2144 }; 2145 2146 proto.ontouchstart = function( event ) { 2147 this._pointerDown( event, event.changedTouches[0] ); 2148 }; 2149 2150 proto.onpointerdown = function( event ) { 2151 this._pointerDown( event, event ); 2152 }; 2153 2154 /** 2155 * pointer start 2156 * @param {Event} event 2157 * @param {Event or Touch} pointer 2158 */ 2159 proto._pointerDown = function( event, pointer ) { 2160 // dismiss right click and other pointers 2161 // button = 0 is okay, 1-4 not 2162 if ( event.button || this.isPointerDown ) { 2163 return; 2164 } 2165 2166 this.isPointerDown = true; 2167 // save pointer identifier to match up touch events 2168 this.pointerIdentifier = pointer.pointerId !== undefined ? 2169 // pointerId for pointer events, touch.indentifier for touch events 2170 pointer.pointerId : pointer.identifier; 2171 2172 this.pointerDown( event, pointer ); 2173 }; 2174 2175 proto.pointerDown = function( event, pointer ) { 2176 this._bindPostStartEvents( event ); 2177 this.emitEvent( 'pointerDown', [ event, pointer ] ); 2178 }; 2179 2180// hash of events to be bound after start event 2181 var postStartEvents = { 2182 mousedown: [ 'mousemove', 'mouseup' ], 2183 touchstart: [ 'touchmove', 'touchend', 'touchcancel' ], 2184 pointerdown: [ 'pointermove', 'pointerup', 'pointercancel' ], 2185 }; 2186 2187 proto._bindPostStartEvents = function( event ) { 2188 if ( !event ) { 2189 return; 2190 } 2191 // get proper events to match start event 2192 var events = postStartEvents[ event.type ]; 2193 // bind events to node 2194 events.forEach( function( eventName ) { 2195 window.addEventListener( eventName, this ); 2196 }, this ); 2197 // save these arguments 2198 this._boundPointerEvents = events; 2199 }; 2200 2201 proto._unbindPostStartEvents = function() { 2202 // check for _boundEvents, in case dragEnd triggered twice (old IE8 bug) 2203 if ( !this._boundPointerEvents ) { 2204 return; 2205 } 2206 this._boundPointerEvents.forEach( function( eventName ) { 2207 window.removeEventListener( eventName, this ); 2208 }, this ); 2209 2210 delete this._boundPointerEvents; 2211 }; 2212 2213// ----- move event ----- // 2214 2215 proto.onmousemove = function( event ) { 2216 this._pointerMove( event, event ); 2217 }; 2218 2219 proto.onpointermove = function( event ) { 2220 if ( event.pointerId == this.pointerIdentifier ) { 2221 this._pointerMove( event, event ); 2222 } 2223 }; 2224 2225 proto.ontouchmove = function( event ) { 2226 var touch = this.getTouch( event.changedTouches ); 2227 if ( touch ) { 2228 this._pointerMove( event, touch ); 2229 } 2230 }; 2231 2232 /** 2233 * pointer move 2234 * @param {Event} event 2235 * @param {Event or Touch} pointer 2236 * @private 2237 */ 2238 proto._pointerMove = function( event, pointer ) { 2239 this.pointerMove( event, pointer ); 2240 }; 2241 2242// public 2243 proto.pointerMove = function( event, pointer ) { 2244 this.emitEvent( 'pointerMove', [ event, pointer ] ); 2245 }; 2246 2247// ----- end event ----- // 2248 2249 2250 proto.onmouseup = function( event ) { 2251 this._pointerUp( event, event ); 2252 }; 2253 2254 proto.onpointerup = function( event ) { 2255 if ( event.pointerId == this.pointerIdentifier ) { 2256 this._pointerUp( event, event ); 2257 } 2258 }; 2259 2260 proto.ontouchend = function( event ) { 2261 var touch = this.getTouch( event.changedTouches ); 2262 if ( touch ) { 2263 this._pointerUp( event, touch ); 2264 } 2265 }; 2266 2267 /** 2268 * pointer up 2269 * @param {Event} event 2270 * @param {Event or Touch} pointer 2271 * @private 2272 */ 2273 proto._pointerUp = function( event, pointer ) { 2274 this._pointerDone(); 2275 this.pointerUp( event, pointer ); 2276 }; 2277 2278// public 2279 proto.pointerUp = function( event, pointer ) { 2280 this.emitEvent( 'pointerUp', [ event, pointer ] ); 2281 }; 2282 2283// ----- pointer done ----- // 2284 2285// triggered on pointer up & pointer cancel 2286 proto._pointerDone = function() { 2287 this._pointerReset(); 2288 this._unbindPostStartEvents(); 2289 this.pointerDone(); 2290 }; 2291 2292 proto._pointerReset = function() { 2293 // reset properties 2294 this.isPointerDown = false; 2295 delete this.pointerIdentifier; 2296 }; 2297 2298 proto.pointerDone = noop; 2299 2300// ----- pointer cancel ----- // 2301 2302 proto.onpointercancel = function( event ) { 2303 if ( event.pointerId == this.pointerIdentifier ) { 2304 this._pointerCancel( event, event ); 2305 } 2306 }; 2307 2308 proto.ontouchcancel = function( event ) { 2309 var touch = this.getTouch( event.changedTouches ); 2310 if ( touch ) { 2311 this._pointerCancel( event, touch ); 2312 } 2313 }; 2314 2315 /** 2316 * pointer cancel 2317 * @param {Event} event 2318 * @param {Event or Touch} pointer 2319 * @private 2320 */ 2321 proto._pointerCancel = function( event, pointer ) { 2322 this._pointerDone(); 2323 this.pointerCancel( event, pointer ); 2324 }; 2325 2326// public 2327 proto.pointerCancel = function( event, pointer ) { 2328 this.emitEvent( 'pointerCancel', [ event, pointer ] ); 2329 }; 2330 2331// ----- ----- // 2332 2333// utility function for getting x/y coords from event 2334 Unipointer.getPointerPoint = function( pointer ) { 2335 return { 2336 x: pointer.pageX, 2337 y: pointer.pageY 2338 }; 2339 }; 2340 2341// ----- ----- // 2342 2343 return Unipointer; 2344 2345})); 2346 2347/*! 2348 * Unidragger v2.3.0 2349 * Draggable base class 2350 * MIT license 2351 */ 2352 2353/*jshint browser: true, unused: true, undef: true, strict: true */ 2354 2355( function( window, factory ) { 2356 // universal module definition 2357 /*jshint strict: false */ /*globals define, module, require */ 2358 2359 if ( typeof define == 'function' && define.amd ) { 2360 // AMD 2361 define( 'unidragger/unidragger',[ 2362 'unipointer/unipointer' 2363 ], function( Unipointer ) { 2364 return factory( window, Unipointer ); 2365 }); 2366 } else if ( typeof module == 'object' && module.exports ) { 2367 // CommonJS 2368 module.exports = factory( 2369 window, 2370 require('unipointer') 2371 ); 2372 } else { 2373 // browser global 2374 window.Unidragger = factory( 2375 window, 2376 window.Unipointer 2377 ); 2378 } 2379 2380}( window, function factory( window, Unipointer ) { 2381 2382 2383 2384// -------------------------- Unidragger -------------------------- // 2385 2386 function Unidragger() {} 2387 2388// inherit Unipointer & EvEmitter 2389 var proto = Unidragger.prototype = Object.create( Unipointer.prototype ); 2390 2391// ----- bind start ----- // 2392 2393 proto.bindHandles = function() { 2394 this._bindHandles( true ); 2395 }; 2396 2397 proto.unbindHandles = function() { 2398 this._bindHandles( false ); 2399 }; 2400 2401 /** 2402 * Add or remove start event 2403 * @param {Boolean} isAdd 2404 */ 2405 proto._bindHandles = function( isAdd ) { 2406 // munge isAdd, default to true 2407 isAdd = isAdd === undefined ? true : isAdd;
vendor: 4,306 bytes, lines 2408-2543
2408 // bind each handle 2409 var bindMethod = isAdd ? 'addEventListener' : 'removeEventListener'; 2410 var touchAction = isAdd ? this._touchActionValue : ''; 2411 for ( var i=0; i < this.handles.length; i++ ) { 2412 var handle = this.handles[i]; 2413 this._bindStartEvent( handle, isAdd ); 2414 handle[ bindMethod ]( 'click', this ); 2415 // touch-action: none to override browser touch gestures. metafizzy/flickity#540 2416 if ( window.PointerEvent ) { 2417 handle.style.touchAction = touchAction; 2418 } 2419 } 2420 }; 2421 2422// prototype so it can be overwriteable by Flickity 2423 proto._touchActionValue = 'none'; 2424 2425// ----- start event ----- // 2426 2427 /** 2428 * pointer start 2429 * @param {Event} event 2430 * @param {Event or Touch} pointer 2431 */ 2432 proto.pointerDown = function( event, pointer ) { 2433 var isOkay = this.okayPointerDown( event ); 2434 if ( !isOkay ) { 2435 return; 2436 } 2437 // track start event position 2438 this.pointerDownPointer = pointer; 2439 2440 event.preventDefault(); 2441 this.pointerDownBlur(); 2442 // bind move and end events 2443 this._bindPostStartEvents( event ); 2444 this.emitEvent( 'pointerDown', [ event, pointer ] ); 2445 }; 2446 2447// nodes that have text fields 2448 var cursorNodes = { 2449 TEXTAREA: true, 2450 INPUT: true, 2451 SELECT: true, 2452 OPTION: true, 2453 }; 2454 2455// input types that do not have text fields 2456 var clickTypes = { 2457 radio: true, 2458 checkbox: true, 2459 button: true, 2460 submit: true, 2461 image: true, 2462 file: true, 2463 }; 2464 2465// dismiss inputs with text fields. flickity#403, flickity#404 2466 proto.okayPointerDown = function( event ) { 2467 var isCursorNode = cursorNodes[ event.target.nodeName ]; 2468 var isClickType = clickTypes[ event.target.type ]; 2469 var isOkay = !isCursorNode || isClickType; 2470 if ( !isOkay ) { 2471 this._pointerReset(); 2472 } 2473 return isOkay; 2474 }; 2475 2476// kludge to blur previously focused input 2477 proto.pointerDownBlur = function() { 2478 var focused = document.activeElement; 2479 // do not blur body for IE10, metafizzy/flickity#117 2480 var canBlur = focused && focused.blur && focused != document.body; 2481 if ( canBlur ) { 2482 focused.blur(); 2483 } 2484 }; 2485 2486// ----- move event ----- // 2487 2488 /** 2489 * drag move 2490 * @param {Event} event 2491 * @param {Event or Touch} pointer 2492 */ 2493 proto.pointerMove = function( event, pointer ) { 2494 var moveVector = this._dragPointerMove( event, pointer ); 2495 this.emitEvent( 'pointerMove', [ event, pointer, moveVector ] ); 2496 this._dragMove( event, pointer, moveVector ); 2497 }; 2498 2499// base pointer move logic 2500 proto._dragPointerMove = function( event, pointer ) { 2501 var moveVector = { 2502 x: pointer.pageX - this.pointerDownPointer.pageX, 2503 y: pointer.pageY - this.pointerDownPointer.pageY 2504 }; 2505 // start drag if pointer has moved far enough to start drag 2506 if ( !this.isDragging && this.hasDragStarted( moveVector ) ) { 2507 this._dragStart( event, pointer ); 2508 } 2509 return moveVector; 2510 }; 2511 2512// condition if pointer has moved far enough to start drag 2513 proto.hasDragStarted = function( moveVector ) { 2514 return Math.abs( moveVector.x ) > 3 || Math.abs( moveVector.y ) > 3; 2515 }; 2516 2517// ----- end event ----- // 2518 2519 /** 2520 * pointer up 2521 * @param {Event} event 2522 * @param {Event or Touch} pointer 2523 */ 2524 proto.pointerUp = function( event, pointer ) { 2525 this.emitEvent( 'pointerUp', [ event, pointer ] ); 2526 this._dragPointerUp( event, pointer ); 2527 }; 2528 2529 proto._dragPointerUp = function( event, pointer ) { 2530 if ( this.isDragging ) { 2531 this._dragEnd( event, pointer ); 2532 } else { 2533 // pointer didn't move enough for drag to start 2534 this._staticClick( event, pointer ); 2535 } 2536 }; 2537 2538// -------------------------- drag -------------------------- // 2539 2540// dragStart 2541 proto._dragStart = function( event, pointer ) { 2542 this.isDragging = true; 2543 // prevent clicks
2544 this.isPreventingClicks = true; 2545 this.dragStart( event, pointer ); 2546 }; 2547 2548 proto.dragStart = function( event, pointer ) { 2549 this.emitEvent( 'dragStart', [ event, pointer ] ); 2550 }; 2551 2552// dragMove 2553 proto._dragMove = function( event, pointer, moveVector ) { 2554 // do not drag if not dragging yet 2555 if ( !this.isDragging ) { 2556 return; 2557 } 2558 2559 this.dragMove( event, pointer, moveVector ); 2560 }; 2561 2562 proto.dragMove = function( event, pointer, moveVector ) { 2563 event.preventDefault(); 2564 this.emitEvent( 'dragMove', [ event, pointer, moveVector ] ); 2565 }; 2566 2567// dragEnd 2568 proto._dragEnd = function( event, pointer ) { 2569 // set flags 2570 this.isDragging = false; 2571 // re-enable clicking async 2572 setTimeout( function() { 2573 delete this.isPreventingClicks; 2574 }.bind( this ) ); 2575 2576 this.dragEnd( event, pointer ); 2577 }; 2578 2579 proto.dragEnd = function( event, pointer ) { 2580 this.emitEvent( 'dragEnd', [ event, pointer ] ); 2581 }; 2582 2583// ----- onclick ----- // 2584 2585// handle all clicks and prevent clicks when dragging 2586 proto.onclick = function( event ) {
vendor: 10,621 bytes, lines 2587-2907
2587 if ( this.isPreventingClicks ) { 2588 event.preventDefault(); 2589 } 2590 }; 2591 2592// ----- staticClick ----- // 2593 2594// triggered after pointer down & up with no/tiny movement 2595 proto._staticClick = function( event, pointer ) { 2596 // ignore emulated mouse up clicks 2597 if ( this.isIgnoringMouseUp && event.type == 'mouseup' ) { 2598 return; 2599 } 2600 2601 this.staticClick( event, pointer ); 2602 2603 // set flag for emulated clicks 300ms after touchend 2604 if ( event.type != 'mouseup' ) { 2605 this.isIgnoringMouseUp = true; 2606 // reset flag after 300ms 2607 setTimeout( function() { 2608 delete this.isIgnoringMouseUp; 2609 }.bind( this ), 400 ); 2610 } 2611 }; 2612 2613 proto.staticClick = function( event, pointer ) { 2614 this.emitEvent( 'staticClick', [ event, pointer ] ); 2615 }; 2616 2617// ----- utils ----- // 2618 2619 Unidragger.getPointerPoint = Unipointer.getPointerPoint; 2620 2621// ----- ----- // 2622 2623 return Unidragger; 2624 2625})); 2626 2627// drag 2628( function( window, factory ) { 2629 // universal module definition 2630 /* jshint strict: false */ 2631 if ( typeof define == 'function' && define.amd ) { 2632 // AMD 2633 define( 'flickity/js/drag',[ 2634 './flickity', 2635 'unidragger/unidragger', 2636 'fizzy-ui-utils/utils' 2637 ], function( Flickity, Unidragger, utils ) { 2638 return factory( window, Flickity, Unidragger, utils ); 2639 }); 2640 } else if ( typeof module == 'object' && module.exports ) { 2641 // CommonJS 2642 module.exports = factory( 2643 window, 2644 require('./flickity'), 2645 require('unidragger'), 2646 require('fizzy-ui-utils') 2647 ); 2648 } else { 2649 // browser global 2650 window.Flickity = factory( 2651 window, 2652 window.Flickity, 2653 window.Unidragger, 2654 window.fizzyUIUtils 2655 ); 2656 } 2657 2658}( window, function factory( window, Flickity, Unidragger, utils ) { 2659 2660 2661 2662// ----- defaults ----- // 2663 2664 utils.extend( Flickity.defaults, { 2665 draggable: '>1', 2666 dragThreshold: 3, 2667 }); 2668 2669// ----- create ----- // 2670 2671 Flickity.createMethods.push('_createDrag'); 2672 2673// -------------------------- drag prototype -------------------------- // 2674 2675 var proto = Flickity.prototype; 2676 utils.extend( proto, Unidragger.prototype ); 2677 proto._touchActionValue = 'pan-y'; 2678 2679// -------------------------- -------------------------- // 2680 2681 var isTouch = 'createTouch' in document; 2682 var isTouchmoveScrollCanceled = false; 2683 2684 proto._createDrag = function() { 2685 this.on( 'activate', this.onActivateDrag ); 2686 this.on( 'uiChange', this._uiChangeDrag ); 2687 this.on( 'childUIPointerDown', this._childUIPointerDownDrag ); 2688 this.on( 'deactivate', this.onDeactivateDrag ); 2689 this.on( 'cellChange', this.updateDraggable ); 2690 // TODO updateDraggable on resize? if groupCells & slides change 2691 // HACK - add seemingly innocuous handler to fix iOS 10 scroll behavior 2692 // #457, RubaXa/Sortable#973 2693 if ( isTouch && !isTouchmoveScrollCanceled ) { 2694 window.addEventListener( 'touchmove', function() {}); 2695 isTouchmoveScrollCanceled = true; 2696 } 2697 }; 2698 2699 proto.onActivateDrag = function() { 2700 this.handles = [ this.viewport ]; 2701 this.bindHandles(); 2702 this.updateDraggable(); 2703 }; 2704 2705 proto.onDeactivateDrag = function() { 2706 this.unbindHandles(); 2707 this.element.classList.remove('is-draggable'); 2708 }; 2709 2710 proto.updateDraggable = function() { 2711 // disable dragging if less than 2 slides. #278 2712 if ( this.options.draggable == '>1' ) { 2713 this.isDraggable = this.slides.length > 1; 2714 } else { 2715 this.isDraggable = this.options.draggable; 2716 } 2717 if ( this.isDraggable ) { 2718 this.element.classList.add('is-draggable'); 2719 } else { 2720 this.element.classList.remove('is-draggable'); 2721 } 2722 }; 2723 2724// backwards compatibility 2725 proto.bindDrag = function() { 2726 this.options.draggable = true; 2727 this.updateDraggable(); 2728 }; 2729 2730 proto.unbindDrag = function() { 2731 this.options.draggable = false; 2732 this.updateDraggable(); 2733 }; 2734 2735 proto._uiChangeDrag = function() { 2736 delete this.isFreeScrolling; 2737 }; 2738 2739 proto._childUIPointerDownDrag = function( event ) { 2740 // allow focus & preventDefault even when not draggable 2741 // so child UI elements keep focus on carousel. #721 2742 event.preventDefault(); 2743 this.pointerDownFocus( event ); 2744 }; 2745 2746// -------------------------- pointer events -------------------------- // 2747 2748 proto.pointerDown = function( event, pointer ) { 2749 if ( !this.isDraggable ) { 2750 this._pointerDownDefault( event, pointer ); 2751 return; 2752 } 2753 var isOkay = this.okayPointerDown( event ); 2754 if ( !isOkay ) { 2755 return; 2756 } 2757 2758 this._pointerDownPreventDefault( event ); 2759 this.pointerDownFocus( event ); 2760 // blur 2761 if ( document.activeElement != this.element ) { 2762 // do not blur if already focused 2763 this.pointerDownBlur(); 2764 } 2765 2766 // stop if it was moving 2767 this.dragX = this.x; 2768 this.viewport.classList.add('is-pointer-down'); 2769 // track scrolling 2770 this.pointerDownScroll = getScrollPosition(); 2771 window.addEventListener( 'scroll', this ); 2772 2773 this._pointerDownDefault( event, pointer ); 2774 }; 2775 2776// default pointerDown logic, used for staticClick 2777 proto._pointerDownDefault = function( event, pointer ) { 2778 // track start event position 2779 this.pointerDownPointer = pointer; 2780 // bind move and end events 2781 this._bindPostStartEvents( event ); 2782 this.dispatchEvent( 'pointerDown', event, [ pointer ] ); 2783 }; 2784 2785 var focusNodes = { 2786 INPUT: true, 2787 TEXTAREA: true, 2788 SELECT: true, 2789 }; 2790 2791 proto.pointerDownFocus = function( event ) { 2792 var isFocusNode = focusNodes[ event.target.nodeName ]; 2793 if ( !isFocusNode ) { 2794 this.focus(); 2795 } 2796 }; 2797 2798 proto._pointerDownPreventDefault = function( event ) { 2799 var isTouchStart = event.type == 'touchstart'; 2800 var isTouchPointer = event.pointerType == 'touch'; 2801 var isFocusNode = focusNodes[ event.target.nodeName ]; 2802 if ( !isTouchStart && !isTouchPointer && !isFocusNode ) { 2803 event.preventDefault(); 2804 } 2805 }; 2806 2807// ----- move ----- // 2808 2809 proto.hasDragStarted = function( moveVector ) { 2810 return Math.abs( moveVector.x ) > this.options.dragThreshold; 2811 }; 2812 2813// ----- up ----- // 2814 2815 proto.pointerUp = function( event, pointer ) { 2816 delete this.isTouchScrolling; 2817 this.viewport.classList.remove('is-pointer-down'); 2818 this.dispatchEvent( 'pointerUp', event, [ pointer ] ); 2819 this._dragPointerUp( event, pointer ); 2820 }; 2821 2822 proto.pointerDone = function() { 2823 window.removeEventListener( 'scroll', this ); 2824 delete this.pointerDownScroll; 2825 }; 2826 2827// -------------------------- dragging -------------------------- // 2828 2829 proto.dragStart = function( event, pointer ) { 2830 if ( !this.isDraggable ) { 2831 return; 2832 } 2833 this.dragStartPosition = this.x; 2834 this.startAnimation(); 2835 window.removeEventListener( 'scroll', this ); 2836 this.dispatchEvent( 'dragStart', event, [ pointer ] ); 2837 }; 2838 2839 proto.pointerMove = function( event, pointer ) { 2840 var moveVector = this._dragPointerMove( event, pointer ); 2841 this.dispatchEvent( 'pointerMove', event, [ pointer, moveVector ] ); 2842 this._dragMove( event, pointer, moveVector ); 2843 }; 2844 2845 proto.dragMove = function( event, pointer, moveVector ) { 2846 if ( !this.isDraggable ) { 2847 return; 2848 } 2849 event.preventDefault(); 2850 2851 this.previousDragX = this.dragX; 2852 // reverse if right-to-left 2853 var direction = this.options.rightToLeft ? -1 : 1; 2854 if ( this.options.wrapAround ) { 2855 // wrap around move. #589 2856 moveVector.x = moveVector.x % this.slideableWidth; 2857 } 2858 var dragX = this.dragStartPosition + moveVector.x * direction; 2859 2860 if ( !this.options.wrapAround && this.slides.length ) { 2861 // slow drag 2862 var originBound = Math.max( -this.slides[0].target, this.dragStartPosition ); 2863 dragX = dragX > originBound ? ( dragX + originBound ) * 0.5 : dragX; 2864 var endBound = Math.min( -this.getLastSlide().target, this.dragStartPosition ); 2865 dragX = dragX < endBound ? ( dragX + endBound ) * 0.5 : dragX; 2866 } 2867 2868 this.dragX = dragX; 2869 2870 this.dragMoveTime = new Date(); 2871 this.dispatchEvent( 'dragMove', event, [ pointer, moveVector ] ); 2872 }; 2873 2874 proto.dragEnd = function( event, pointer ) { 2875 if ( !this.isDraggable ) { 2876 return; 2877 } 2878 if ( this.options.freeScroll ) { 2879 this.isFreeScrolling = true; 2880 } 2881 // set selectedIndex based on where flick will end up 2882 var index = this.dragEndRestingSelect(); 2883 2884 if ( this.options.freeScroll && !this.options.wrapAround ) { 2885 // if free-scroll & not wrap around 2886 // do not free-scroll if going outside of bounding slides 2887 // so bounding slides can attract slider, and keep it in bounds 2888 var restingX = this.getRestingPosition(); 2889 this.isFreeScrolling = -restingX > this.slides[0].target && 2890 -restingX < this.getLastSlide().target; 2891 } else if ( !this.options.freeScroll && index == this.selectedIndex ) { 2892 // boost selection if selected index has not changed 2893 index += this.dragEndBoostSelect(); 2894 } 2895 delete this.previousDragX; 2896 // apply selection 2897 // TODO refactor this, selecting here feels weird 2898 // HACK, set flag so dragging stays in correct direction 2899 this.isDragSelect = this.options.wrapAround; 2900 this.select( index ); 2901 delete this.isDragSelect; 2902 this.dispatchEvent( 'dragEnd', event, [ pointer ] ); 2903 }; 2904 2905 proto.dragEndRestingSelect = function() { 2906 var restingX = this.getRestingPosition(); 2907 // how far away from selected slide
2908 var distance = Math.abs( this.getSlideDistance( -restingX, this.selectedIndex ) ); 2909 // get closet resting going up and going down 2910 var positiveResting = this._getClosestResting( restingX, distance, 1 ); 2911 var negativeResting = this._getClosestResting( restingX, distance, -1 ); 2912 // use closer resting for wrap-around 2913 var index = positiveResting.distance < negativeResting.distance ? 2914 positiveResting.index : negativeResting.index; 2915 return index; 2916 }; 2917 2918 /** 2919 * given resting X and distance to selected cell 2920 * get the distance and index of the closest cell 2921 * @param {Number} restingX - estimated post-flick resting position 2922 * @param {Number} distance - distance to selected cell 2923 * @param {Integer} increment - +1 or -1, going up or down 2924 * @returns {Object} - { distance: {Number}, index: {Integer} } 2925 */ 2926 proto._getClosestResting = function( restingX, distance, increment ) { 2927 var index = this.selectedIndex; 2928 var minDistance = Infinity; 2929 var condition = this.options.contain && !this.options.wrapAround ? 2930 // if contain, keep going if distance is equal to minDistance 2931 function( d, md ) { return d <= md; } : function( d, md ) { return d < md; }; 2932 while ( condition( distance, minDistance ) ) { 2933 // measure distance to next cell 2934 index += increment; 2935 minDistance = distance; 2936 distance = this.getSlideDistance( -restingX, index ); 2937 if ( distance === null ) { 2938 break; 2939 } 2940 distance = Math.abs( distance ); 2941 } 2942 return { 2943 distance: minDistance, 2944 // selected was previous index 2945 index: index - increment 2946 }; 2947 }; 2948 2949 /** 2950 * measure distance between x and a slide target 2951 * @param {Number} x 2952 * @param {Integer} index - slide index 2953 */ 2954 proto.getSlideDistance = function( x, index ) { 2955 var len = this.slides.length; 2956 // wrap around if at least 2 slides 2957 var isWrapAround = this.options.wrapAround && len > 1; 2958 var slideIndex = isWrapAround ? utils.modulo( index, len ) : index; 2959 var slide = this.slides[ slideIndex ]; 2960 if ( !slide ) { 2961 return null; 2962 } 2963 // add distance for wrap-around slides 2964 var wrap = isWrapAround ? this.slideableWidth * Math.floor( index / len ) : 0; 2965 return x - ( slide.target + wrap ); 2966 }; 2967 2968 proto.dragEndBoostSelect = function() { 2969 // do not boost if no previousDragX or dragMoveTime 2970 if ( this.previousDragX === undefined || !this.dragMoveTime || 2971 // or if drag was held for 100 ms 2972 new Date() - this.dragMoveTime > 100 ) { 2973 return 0; 2974 } 2975 2976 var distance = this.getSlideDistance( -this.dragX, this.selectedIndex ); 2977 var delta = this.previousDragX - this.dragX; 2978 if ( distance > 0 && delta > 0 ) { 2979 // boost to next if moving towards the right, and positive velocity 2980 return 1; 2981 } else if ( distance < 0 && delta < 0 ) { 2982 // boost to previous if moving towards the left, and negative velocity 2983 return -1; 2984 } 2985 return 0; 2986 }; 2987 2988// ----- staticClick ----- // 2989 2990 proto.staticClick = function( event, pointer ) { 2991 // get clickedCell, if cell was clicked 2992 var clickedCell = this.getParentCell( event.target ); 2993 var cellElem = clickedCell && clickedCell.element; 2994 var cellIndex = clickedCell && this.cells.indexOf( clickedCell ); 2995 this.dispatchEvent( 'staticClick', event, [ pointer, cellElem, cellIndex ] ); 2996 }; 2997 2998// ----- scroll ----- // 2999 3000 proto.onscroll = function() { 3001 var scroll = getScrollPosition(); 3002 var scrollMoveX = this.pointerDownScroll.x - scroll.x; 3003 var scrollMoveY = this.pointerDownScroll.y - scroll.y; 3004 // cancel click/tap if scroll is too much 3005 if ( Math.abs( scrollMoveX ) > 3 || Math.abs( scrollMoveY ) > 3 ) { 3006 this._pointerDone(); 3007 } 3008 }; 3009 3010// ----- utils ----- // 3011 3012 function getScrollPosition() { 3013 return { 3014 x: window.pageXOffset, 3015 y: window.pageYOffset 3016 }; 3017 } 3018 3019// ----- ----- // 3020 3021 return Flickity; 3022 3023})); 3024 3025/*! 3026 * Tap listener v2.0.0 3027 * listens to taps 3028 * MIT license 3029 */ 3030 3031/*jshint browser: true, unused: true, undef: true, strict: true */ 3032 3033( function( window, factory ) { 3034 // universal module definition 3035 /*jshint strict: false*/ /*globals define, module, require */ 3036 3037 if ( typeof define == 'function' && define.amd ) { 3038 // AMD 3039 define( 'tap-listener/tap-listener',[
3040 'unipointer/unipointer' 3041 ], function( Unipointer ) { 3042 return factory( window, Unipointer ); 3043 }); 3044 } else if ( typeof module == 'object' && module.exports ) { 3045 // CommonJS 3046 module.exports = factory( 3047 window, 3048 require('unipointer') 3049 ); 3050 } else { 3051 // browser global 3052 window.TapListener = factory( 3053 window, 3054 window.Unipointer 3055 ); 3056 } 3057 3058}( window, function factory( window, Unipointer ) { 3059 3060 3061 3062// -------------------------- TapListener -------------------------- // 3063 3064 function TapListener( elem ) { 3065 this.bindTap( elem ); 3066 } 3067 3068// inherit Unipointer & EventEmitter 3069 var proto = TapListener.prototype = Object.create( Unipointer.prototype ); 3070 3071 /** 3072 * bind tap event to element 3073 * @param {Element} elem 3074 */ 3075 proto.bindTap = function( elem ) { 3076 if ( !elem ) { 3077 return; 3078 } 3079 this.unbindTap(); 3080 this.tapElement = elem; 3081 this._bindStartEvent( elem, true ); 3082 }; 3083 3084 proto.unbindTap = function() { 3085 if ( !this.tapElement ) { 3086 return; 3087 } 3088 this._bindStartEvent( this.tapElement, true ); 3089 delete this.tapElement; 3090 }; 3091 3092 /** 3093 * pointer up 3094 * @param {Event} event 3095 * @param {Event or Touch} pointer 3096 */ 3097 proto.pointerUp = function( event, pointer ) { 3098 // ignore emulated mouse up clicks 3099 if ( this.isIgnoringMouseUp && event.type == 'mouseup' ) { 3100 return; 3101 } 3102 3103 var pointerPoint = Unipointer.getPointerPoint( pointer ); 3104 var boundingRect = this.tapElement.getBoundingClientRect(); 3105 var scrollX = window.pageXOffset; 3106 var scrollY = window.pageYOffset; 3107 // calculate if pointer is inside tapElement 3108 var isInside = pointerPoint.x >
3108= boundingRect.left + scrollX && 3109 pointerPoint.x <= boundingRect.right + scrollX && 3110 pointerPoint.y >= boundingRect.top + scrollY && 3111 pointerPoint.y <= boundingRect.bottom + scrollY; 3112 // trigger callback if pointer is inside element 3113 if ( isInside ) { 3114 this.emitEvent( 'tap', [ event, pointer ] ); 3115 } 3116 3117 // set flag for emulated clicks 300ms after touchend 3118 if ( event.type != 'mouseup' ) { 3119 this.isIgnoringMouseUp = true; 3120 // reset flag after 300ms 3121 var _this = this; 3122 setTimeout( function() { 3123 delete _this.isIgnoringMouseUp; 3124 }, 400 ); 3125 } 3126 }; 3127 3128 proto.destroy = function() { 3129 this.pointerDone(); 3130 this.unbindTap(); 3131 }; 3132 3133// ----- ----- // 3134 3135 return TapListener; 3136 3137})); 3138 3139// prev/next buttons 3140( function( window, factory ) { 3141 // universal module definition 3142 /* jshint strict: false */ 3143 if ( typeof define == 'function' && define.amd ) { 3144 // AMD 3145 define( 'flickity/js/prev-next-button',[ 3146 './flickity', 3147 'tap-listener/tap-listener', 3148 'fizzy-ui-utils/utils' 3149 ], function( Flickity, TapListener, utils ) { 3150 return factory( window, Flickity, TapListener, utils ); 3151 }); 3152 } else if ( typeof module == 'object' && module.exports ) { 3153 // CommonJS 3154 module.exports = factory( 3155 window, 3156 require('./flickity'), 3157 require('tap-listener'), 3158 require('fizzy-ui-utils') 3159 ); 3160 } else { 3161 // browser global 3162 factory( 3163 window, 3164 window.Flickity, 3165 window.TapListener, 3166 window.fizzyUIUtils 3167 ); 3168 } 3169 3170}( window, function factory( window, Flickity, TapListener, utils ) { 3171 'use strict'; 3172 3173 var svgURI = 'http://www.w3.org/2000/svg'; 3174 3175// -------------------------- PrevNextButton -------------------------- // 3176 3177 function PrevNextButton( direction, parent ) { 3178 this.direction = direction; 3179 this.parent = parent; 3180 this._create(); 3181 } 3182 3183 PrevNextButton.prototype = Object.create( TapListener.prototype ); 3184 3185 PrevNextButton.prototype._create = function() { 3186 // properties 3187 this.isEnabled = true; 3188 this.isPrevious = this.direction == -1; 3189 var leftDirection = this.parent.options.rightToLeft ? 1 : -1; 3190 this.isLeft = this.direction == leftDirection; 3191 3192 var element = this.element = document.createElement('button'); 3193 element.className = 'flickity-button flickity-prev-next-button'; 3194 element.className += this.isPrevious ? ' previous' : ' next'; 3195 // prevent button from submitting form http://stackoverflow.com/a/10836076/182183 3196 element.setAttribute( 'type', 'button' ); 3197 // init as disabled 3198 this.disable(); 3199 3200 element.setAttribute( 'aria-label', this.isPrevious ? 'Previous' : 'Next' ); 3201 3202 // create arrow 3203 var svg = this.createSVG(); 3204 element.appendChild( svg ); 3205 // events 3206 this.on( 'tap', this.onTap ); 3207 this.parent.on( 'select', this.update.bind( this ) ); 3208 this.on( 'pointerDown', this.parent.childUIPointerDown.bind( this.parent ) ); 3209 }; 3210 3211 PrevNextButton.prototype.activate = function() { 3212 this.bindTap( this.element ); 3213 // click events from keyboard 3214 this.element.addEventListener( 'click', this ); 3215 // add to DOM 3216 this.parent.element.appendChild( this.element ); 3217 }; 3218 3219 PrevNextButton.prototype.deactivate = function() { 3220 // remove from DOM 3221 this.parent.element.removeChild( this.element ); 3222 // do regular TapListener destroy 3223 TapListener.prototype.destroy.call( this ); 3224 // click events from keyboard 3225 this.element.removeEventListener( 'click', this ); 3226 }; 3227 3228 PrevNextButton.prototype.createSVG = function() { 3229 var svg = document.createElementNS( svgURI, 'svg'); 3230 svg.setAttribute( 'class', 'flickity-button-icon' ); 3231 svg.setAttribute( 'viewBox', '0 0 100 100' ); 3232 var path = document.createElementNS( svgURI, 'path'); 3233 var pathMovements = getArrowMovements( this.parent.options.arrowShape ); 3234 path.setAttribute( 'd', pathMovements ); 3235 path.setAttribute( 'class', 'arrow' ); 3236 // rotate arrow 3237 if ( !this.isLeft ) { 3238 path.setAttribute( 'transform', 'translate(100, 100) rotate(180) ' ); 3239 } 3240 svg.appendChild( path ); 3241 return svg; 3242 }; 3243 3244// get SVG path movmement 3245 function getArrowMovements( shape ) { 3246 // use shape as movement if string 3247 if ( typeof shape == 'string' ) { 3248 return shape; 3249 } 3250 // create movement string 3251 return 'M ' + shape.x0 + ',50' + 3252 ' L ' + shape.x1 + ',' + ( shape.y1 + 50 ) + 3253 ' L ' + shape.x2 + ',' + ( shape.y2 + 50 ) + 3254 ' L ' + shape.x3 + ',50 ' + 3255 ' L ' + shape.x2 + ',' + ( 50 - shape.y2 ) + 3256 ' L ' + shape.x1 + ',' + ( 50 - shape.y1 ) + 3257 ' Z'; 3258 } 3259 3260 PrevNextButton.prototype.onTap = function() { 3261 if ( !this.isEnabled ) { 3262 return; 3263 } 3264 this.parent.uiChange(); 3265 var method = this.isPrevious ? 'previous' : 'next'; 3266 this.parent[ method ](); 3267 }; 3268 3269 PrevNextButton.prototype.handleEvent = utils.handleEvent; 3270 3271 PrevNextButton.prototype.onclick = function( event ) { 3272 // only allow clicks from keyboard 3273 var focused = document.activeElement;
3274 if ( focused && focused == this.element ) { 3275 this.onTap( event, event ); 3276 } 3277 }; 3278 3279// ----- ----- // 3280 3281 PrevNextButton.prototype.enable = function() { 3282 if ( this.isEnabled ) { 3283 return; 3284 } 3285 this.element.disabled = false; 3286 this.isEnabled = true; 3287 }; 3288 3289 PrevNextButton.prototype.disable = function() { 3290 if ( !this.isEnabled ) { 3291 return; 3292 } 3293 this.element.disabled = true; 3294 this.isEnabled = false; 3295 }; 3296 3297 PrevNextButton.prototype.update = function() { 3298 // index of first or last slide, if previous or next 3299 var slides = this.parent.slides; 3300 // enable is wrapAround and at least 2 slides 3301 if ( this.parent.options.wrapAround && slides.length > 1 ) { 3302 this.enable(); 3303 return; 3304 } 3305 var lastIndex = slides.length ? slides.length - 1 : 0; 3306 var boundIndex = this.isPrevious ? 0 : lastIndex; 3307 var method = this.parent.selectedIndex == boundIndex ? 'disable' : 'enable'; 3308 this[ method ](); 3309 }; 3310 3311 PrevNextButton.prototype.destroy = function() { 3312 this.deactivate(); 3313 }; 3314 3315// -------------------------- Flickity prototype -------------------------- // 3316 3317 utils.extend( Flickity.defaults, { 3318 prevNextButtons: true, 3319 arrowShape: { 3320 x0: 10, 3321 x1: 60, y1: 50, 3322 x2: 70, y2: 40, 3323 x3: 30 3324 } 3325 }); 3326 3327 Flickity.createMethods.push('_createPrevNextButtons'); 3328 var proto = Flickity.prototype; 3329 3330 proto._createPrevNextButtons = function() { 3331 if ( !this.options.prevNextButtons ) { 3332 return; 3333 } 3334 3335 this.prevButton = new PrevNextButton( -1, this ); 3336 this.nextButton = new PrevNextButton( 1, this ); 3337 3338 this.on( 'activate', this.activatePrevNextButtons ); 3339 }; 3340 3341 proto.activatePrevNextButtons = function() { 3342 this.prevButton.activate(); 3343 this.nextButton.activate(); 3344 this.on( 'deactivate', this.deactivatePrevNextButtons ); 3345 }; 3346 3347 proto.deactivatePrevNextButtons = function() { 3348 this.prevButton.deactivate(); 3349 this.nextButton.deactivate(); 3350 this.off( 'deactivate', this.deactivatePrevNextButtons ); 3351 }; 3352 3353// -------------------------- -------------------------- // 3354 3355 Flickity.PrevNextButton = PrevNextButton; 3356 3357 return Flickity; 3358 3359})); 3360 3361// page dots 3362( function( window, factory ) { 3363 // universal module definition 3364 /* jshint strict: false */ 3365 if ( typeof define == 'function' && define.amd ) { 3366 // AMD 3367 define( 'flickity/js/page-dots',[ 3368 './flickity', 3369 'tap-listener/tap-listener', 3370 'fizzy-ui-utils/utils' 3371 ], function( Flickity, TapListener, utils ) { 3372 return factory( window, Flickity, TapListener, utils ); 3373 }); 3374 } else if ( typeof module == 'object' && module.exports ) { 3375 // CommonJS 3376 module.exports = factory( 3377 window, 3378 require('./flickity'), 3379 require('tap-listener'), 3380 require('fizzy-ui-utils') 3381 ); 3382 } else { 3383 // browser global 3384 factory( 3385 window, 3386 window.Flickity, 3387 window.TapListener, 3388 window.fizzyUIUtils 3389 ); 3390 } 3391 3392}( window, function factory( window, Flickity, TapListener, utils ) { 3393 3394// -------------------------- PageDots -------------------------- // 3395 3396 3397 3398 function PageDots( parent ) { 3399 this.parent = parent; 3400 this._create(); 3401 } 3402 3403 PageDots.prototype = new TapListener(); 3404 3405 PageDots.prototype._create = function() { 3406 // create holder element 3407 this.holder = document.createElement('ol'); 3408 this.holder.className = 'flickity-page-dots'; 3409 // create dots, array of elements 3410 this.dots = []; 3411 // events 3412 this.on( 'tap', this.onTap ); 3413 this.on( 'pointerDown', this.parent.childUIPointerDown.bind( this.parent ) ); 3414 }; 3415 3416 PageDots.prototype.activate = function() { 3417 this.setDots(); 3418 this.bindTap( this.holder ); 3419 // add to DOM 3420 this.parent.element.appendChild( this.holder ); 3421 }; 3422 3423 PageDots.prototype.deactivate = function() { 3424 // remove from DOM 3425 this.parent.element.removeChild( this.holder ); 3426 TapListener.prototype.destroy.call( this ); 3427 }; 3428 3429 PageDots.prototype.setDots = function() { 3430 // get difference between number of slides and number of dots 3431 var delta = this.parent.slides.length - this.dots.length; 3432 if ( delta > 0 ) { 3433 this.addDots( delta ); 3434 } else if ( delta < 0 ) { 3435 this.removeDots( -delta ); 3436 } 3437 }; 3438 3439 PageDots.prototype.addDots = function( count ) { 3440 var fragment = document.createDocumentFragment(); 3441 var newDots = []; 3442 var length = this.dots.length; 3443 var max = length + count; 3444 3445 for ( var i = length; i < max; i++ ) { 3446 var dot = document.createElement('li'); 3447 dot.className = 'dot'; 3448 dot.setAttribute( 'aria-label', 'Page dot ' + ( i + 1 ) ); 3449 fragment.appendChild( dot ); 3450 newDots.push( dot ); 3451 } 3452 3453 this.holder.appendChild( fragment ); 3454 this.dots = this.dots.concat( newDots ); 3455 }; 3456 3457 PageDots.prototype.removeDots = function( count ) { 3458 // remove from this.dots collection 3459 var removeDots = this.dots.splice( this.dots.length - count, count ); 3460 // remove from DOM
3461 removeDots.forEach( function( dot ) { 3462 this.holder.removeChild( dot ); 3463 }, this ); 3464 }; 3465 3466 PageDots.prototype.updateSelected = function() { 3467 // remove selected class on previous 3468 if ( this.selectedDot ) { 3469 this.selectedDot.className = 'dot'; 3470 this.selectedDot.removeAttribute('aria-current'); 3471 } 3472 // don't proceed if no dots 3473 if ( !this.dots.length ) { 3474 return; 3475 } 3476 this.selectedDot = this.dots[ this.parent.selectedIndex ]; 3477 this.selectedDot.className = 'dot is-selected'; 3478 this.selectedDot.setAttribute( 'aria-current', 'step' ); 3479 }; 3480 3481 PageDots.prototype.onTap = function( event ) { 3482 var target = event.target; 3483 // only care about dot clicks 3484 if ( target.nodeName != 'LI' ) { 3485 return; 3486 } 3487 3488 this.parent.uiChange(); 3489 var index = this.dots.indexOf( target ); 3490 this.parent.select( index ); 3491 }; 3492 3493 PageDots.prototype.destroy = function() { 3494 this.deactivate(); 3495 }; 3496 3497 Flickity.PageDots = PageDots; 3498 3499// -------------------------- Flickity -------------------------- // 3500 3501 utils.extend( Flickity.defaults, { 3502 pageDots: true 3503 }); 3504 3505 Flickity.createMethods.push('_createPageDots'); 3506 3507 var proto = Flickity.prototype; 3508 3509 proto._createPageDots = function() { 3510 if ( !this.options.pageDots ) { 3511 return; 3512 } 3513 this.pageDots = new PageDots( this ); 3514 // events 3515 this.on( 'activate', this.activatePageDots ); 3516 this.on( 'select', this.updateSelectedPageDots ); 3517 this.on( 'cellChange', this.updatePageDots ); 3518 this.on( 'resize', this.updatePageDots ); 3519 this.on( 'deactivate', this.deactivatePageDots ); 3520 }; 3521 3522 proto.activatePageDots = function() { 3523 this.pageDots.activate(); 3524 }; 3525 3526 proto.updateSelectedPageDots = function() { 3527 this.pageDots.updateSelected(); 3528 }; 3529 3530 proto.updatePageDots = function() { 3531 this.pageDots.setDots(); 3532 }; 3533 3534 proto.deactivatePageDots = function() { 3535 this.pageDots.deactivate(); 3536 }; 3537 3538// ----- ----- // 3539 3540 Flickity.PageDots = PageDots; 3541 3542 return Flickity; 3543 3544})); 3545 3546// player & autoPlay 3547( function( window, factory ) { 3548 // universal module definition 3549 /* jshint strict: false */ 3550 if ( typeof define == 'function' && define.amd ) { 3551 // AMD 3552 define( 'flickity/js/player',[ 3553 'ev-emitter/ev-emitter', 3554 'fizzy-ui-utils/utils', 3555 './flickity' 3556 ], function( EvEmitter, utils, Flickity ) { 3557 return factory( EvEmitter, utils, Flickity ); 3558 }); 3559 } else if ( typeof module == 'object' && module.exports ) { 3560 // CommonJS 3561 module.exports = factory( 3562 require('ev-emitter'), 3563 require('fizzy-ui-utils'), 3564 require('./flickity') 3565 ); 3566 } else { 3567 // browser global 3568 factory( 3569 window.EvEmitter, 3570 window.fizzyUIUtils, 3571 window.Flickity 3572 ); 3573 } 3574 3575}( window, function factory( EvEmitter, utils, Flickity ) { 3576 3577 3578 3579// -------------------------- Player -------------------------- // 3580 3581 function Player( parent ) { 3582 this.parent = parent; 3583 this.state = 'stopped'; 3584 // visibility change event handler 3585 this.onVisibilityChange = this.visibilityChange.bind( this ); 3586 this.onVisibilityPlay = this.visibilityPlay.bind( this ); 3587 } 3588 3589 Player.prototype = Object.create( EvEmitter.prototype ); 3590 3591// start play 3592 Player.prototype.play = function() { 3593 if ( this.state == 'playing' ) { 3594 return; 3595 } 3596 // do not play if page is hidden, start playing when page is visible 3597 var isPageHidden = document.hidden; 3598 if ( isPageHidden ) { 3599 document.addEventListener( 'visibilitychange', this.onVisibilityPlay ); 3600 return; 3601 } 3602 3603 this.state = 'playing'; 3604 // listen to visibility change 3605 document.addEventListener( 'visibilitychange', this.onVisibilityChange ); 3606 // start ticking 3607 this.tick(); 3608 }; 3609 3610 Player.prototype.tick = function() { 3611 // do not tick if not playing 3612 if ( this.state != 'playing' ) { 3613 return; 3614 } 3615 3616 var time = this.parent.options.autoPlay; 3617 // default to 3 seconds 3618 time = typeof time == 'number' ? time : 3000; 3619 var _this = this; 3620 // HACK: reset ticks if stopped and started within interval 3621 this.clear(); 3622 this.timeout = setTimeout( function() { 3623 _this.parent.next( true ); 3624 _this.tick(); 3625 }, time ); 3626 }; 3627 3628 Player.prototype.stop = function() { 3629 this.state = 'stopped'; 3630 this.clear(); 3631 // remove visibility change event 3632 document.removeEventListener( 'visibilitychange', this.onVisibilityChange ); 3633 }; 3634 3635 Player.prototype.clear = function() { 3636 clearTimeout( this.timeout ); 3637 }; 3638 3639 Player.prototype.pause = function() { 3640 if ( this.state == 'playing' ) { 3641 this.state = 'paused'; 3642 this.clear(); 3643 } 3644 }; 3645 3646 Player.prototype.unpause = function() { 3647 // re-start play if paused 3648 if ( this.state == 'paused' ) { 3649 this.play(); 3650 } 3651 }; 3652 3653// pause if page visibility is hidden, unpause if visible 3654 Player.prototype.visibilityChange = function() { 3655 var isPageHidden = document.hidden; 3656 this[ isPageHidden ? 'pause' : 'unpause' ](); 3657 }; 3658 3659 Player.prototype.visibilityPlay = function() { 3660 this.play(); 3661 document.removeEventListener( 'visibilitychange', this.onVisibilityPlay ); 3662 }; 3663 3664// -------------------------- Flickity -------------------------- // 3665 3666 utils.extend( Flickity.defaults, { 3667 pauseAutoPlayOnHover: true 3668 });
3669 3670 Flickity.createMethods.push('_createPlayer'); 3671 var proto = Flickity.prototype; 3672 3673 proto._createPlayer = function() { 3674 this.player = new Player( this ); 3675 3676 this.on( 'activate', this.activatePlayer ); 3677 this.on( 'uiChange', this.stopPlayer ); 3678 this.on( 'pointerDown', this.stopPlayer ); 3679 this.on( 'deactivate', this.deactivatePlayer ); 3680 }; 3681 3682 proto.activatePlayer = function() { 3683 if ( !this.options.autoPlay ) { 3684 return; 3685 } 3686 this.player.play(); 3687 this.element.addEventListener( 'mouseenter', this ); 3688 }; 3689 3690// Player API, don't hate the ... thanks I know where the door is 3691 3692 proto.playPlayer = function() { 3693 this.player.play(); 3694 }; 3695 3696 proto.stopPlayer = function() { 3697 this.player.stop(); 3698 }; 3699 3700 proto.pausePlayer = function() { 3701 this.player.pause(); 3702 }; 3703 3704 proto.unpausePlayer = function() { 3705 this.player.unpause(); 3706 }; 3707 3708 proto.deactivatePlayer = function() { 3709 this.player.stop(); 3710 this.element.removeEventListener( 'mouseenter', this ); 3711 }; 3712 3713// ----- mouseenter/leave ----- // 3714 3715// pause auto-play on hover 3716 proto.onmouseenter = function() { 3717 if ( !this.options.pauseAutoPlayOnHover ) { 3718 return; 3719 } 3720 this.player.pause(); 3721 this.element.addEventListener( 'mouseleave', this ); 3722 }; 3723 3724// resume auto-play on hover off 3725 proto.onmouseleave = function() { 3726 this.player.unpause(); 3727 this.element.removeEventListener( 'mouseleave', this ); 3728 }; 3729 3730// ----- ----- // 3731 3732 Flickity.Player = Player; 3733 3734 return Flickity; 3735 3736})); 3737 3738// add, remove cell 3739( function( window, factory ) { 3740 // universal module definition 3741 /* jshint strict: false */ 3742 if ( typeof define == 'function' && define.amd ) { 3743 // AMD 3744 define( 'flickity/js/add-remove-cell',[ 3745 './flickity', 3746 'fizzy-ui-utils/utils' 3747 ], function( Flickity, utils ) { 3748 return factory( window, Flickity, utils ); 3749 }); 3750 } else if ( typeof module == 'object' && module.exports ) { 3751 // CommonJS 3752 module.exports = factory( 3753 window, 3754 require('./flickity'), 3755 require('fizzy-ui-utils') 3756 ); 3757 } else { 3758 // browser global 3759 factory( 3760 window, 3761 window.Flickity, 3762 window.fizzyUIUtils 3763 ); 3764 } 3765 3766}( window, function factory( window, Flickity, utils ) { 3767 3768 3769 3770// append cells to a document fragment 3771 function getCellsFragment( cells ) { 3772 var fragment = document.createDocumentFragment(); 3773 cells.forEach( function( cell ) { 3774 fragment.appendChild( cell.element ); 3775 }); 3776 return fragment; 3777 } 3778 3779// -------------------------- add/remove cell prototype -------------------------- // 3780 3781 var proto = Flickity.prototype; 3782 3783 /** 3784 * Insert, prepend, or append cells 3785 * @param {Element, Array, NodeList} elems 3786 * @param {Integer} index 3787 */ 3788 proto.insert = function( elems, index ) { 3789 var cells = this._makeCells( elems ); 3790 if ( !cells || !cells.length ) { 3791 return; 3792 } 3793 var len = this.cells.length; 3794 // default to append 3795 index = index === undefined ? len : index; 3796 // add cells with document fragment 3797 var fragment = getCellsFragment( cells ); 3798 // append to slider 3799 var isAppend = index == len; 3800 if ( isAppend ) { 3801 this.slider.appendChild( fragment ); 3802 } else { 3803 var insertCellElement = this.cells[ index ].element; 3804 this.slider.insertBefore( fragment, insertCellElement ); 3805 } 3806 // add to this.cells 3807 if ( index === 0 ) { 3808 // prepend, add to start 3809 this.cells = cells.concat( this.cells ); 3810 } else if ( isAppend ) { 3811 // append, add to end 3812 this.cells = this.cells.concat( cells ); 3813 } else { 3814 // insert in this.cells 3815 var endCells = this.cells.splice( index, len - index ); 3816 this.cells = this.cells.concat( cells ).concat( endCells ); 3817 } 3818 3819 this._sizeCells( cells ); 3820 this.cellChange( index, true ); 3821 }; 3822 3823 proto.append = function( elems ) { 3824 this.insert( elems, this.cells.length ); 3825 }; 3826 3827 proto.prepend = function( elems ) { 3828 this.insert( elems, 0 ); 3829 }; 3830 3831 /** 3832 * Remove cells 3833 * @param {Element, Array, NodeList} elems 3834 */ 3835 proto.remove = function( elems ) { 3836 var cells = this.getCells( elems ); 3837 if ( !cells || !cells.length ) { 3838 return; 3839 } 3840 3841 var minCellIndex = this.cells.length - 1; 3842 // remove cells from collection & DOM
3843 cells.forEach( function( cell ) { 3844 cell.remove(); 3845 var index = this.cells.indexOf( cell ); 3846 minCellIndex = Math.min( index, minCellIndex ); 3847 utils.removeFrom( this.cells, cell ); 3848 }, this ); 3849 3850 this.cellChange( minCellIndex, true ); 3851 }; 3852 3853 /** 3854 * logic to be run after a cell's size changes 3855 * @param {Element} elem - cell's element 3856 */ 3857 proto.cellSizeChange = function( elem ) { 3858 var cell = this.getCell( elem ); 3859 if ( !cell ) { 3860 return; 3861 } 3862 cell.getSize(); 3863 3864 var index = this.cells.indexOf( cell ); 3865 this.cellChange( index ); 3866 }; 3867 3868 /** 3869 * logic any time a cell is changed: added, removed, or size changed 3870 * @param {Integer} changedCellIndex - index of the changed cell, optional 3871 */ 3872 proto.cellChange = function( changedCellIndex, isPositioningSlider ) { 3873 var prevSelectedElem = this.selectedElement; 3874 this._positionCells( changedCellIndex ); 3875 this._getWrapShiftCells(); 3876 this.setGallerySize(); 3877 // update selectedIndex 3878 // try to maintain position & select previous selected element 3879 var cell = this.getCell( prevSelectedElem ); 3880 if ( cell ) { 3881 this.selectedIndex = this.getCellSlideIndex( cell ); 3882 } 3883 this.selectedIndex = Math.min( this.slides.length - 1, this.selectedIndex ); 3884 3885 this.emitEvent( 'cellChange', [ changedCellIndex ] ); 3886 // position slider 3887 this.select( this.selectedIndex ); 3888 // do not position slider after lazy load 3889 if ( isPositioningSlider ) { 3890 this.positionSliderAtSelected(); 3891 } 3892 }; 3893 3894// ----- ----- // 3895 3896 return Flickity; 3897 3898})); 3899 3900// lazyload 3901( function( window, factory ) { 3902 // universal module definition 3903 /* jshint strict: false */ 3904 if ( typeof define == 'function' && define.amd ) { 3905 // AMD 3906 define( 'flickity/js/lazyload',[ 3907 './flickity', 3908 'fizzy-ui-utils/utils' 3909 ], function( Flickity, utils ) { 3910 return factory( window, Flickity, utils ); 3911 }); 3912 } else if ( typeof module == 'object' && module.exports ) { 3913 // CommonJS 3914 module.exports = factory( 3915 window, 3916 require('./flickity'), 3917 require('fizzy-ui-utils') 3918 ); 3919 } else { 3920 // browser global 3921 factory( 3922 window, 3923 window.Flickity, 3924 window.fizzyUIUtils 3925 ); 3926 } 3927 3928}( window, function factory( window, Flickity, utils ) { 3929 'use strict'; 3930 3931 Flickity.createMethods.push('_createLazyload'); 3932 var proto = Flickity.prototype; 3933 3934 proto._createLazyload = function() { 3935 this.on( 'select', this.lazyLoad ); 3936 }; 3937 3938 proto.lazyLoad = function() { 3939 var lazyLoad = this.options.lazyLoad; 3940 if ( !lazyLoad ) { 3941 return; 3942 } 3943 // get adjacent cells, use lazyLoad option for adjacent count 3944 var adjCount = typeof lazyLoad == 'number' ? lazyLoad : 0; 3945 var cellElems = this.getAdjacentCellElements( adjCount ); 3946 // get lazy images in those cells 3947 var lazyImages = [];
3948 cellElems.forEach( function( cellElem ) { 3949 var lazyCellImages = getCellLazyImages( cellElem ); 3950 lazyImages = lazyImages.concat( lazyCellImages ); 3951 }); 3952 // load lazy images 3953 lazyImages.forEach( function( img ) { 3954 new LazyLoader( img, this ); 3955 }, this ); 3956 }; 3957 3958 function getCellLazyImages( cellElem ) { 3959 // check if cell element is lazy image 3960 if ( cellElem.nodeName == 'IMG' ) { 3961 var lazyloadAttr = cellElem.getAttribute('data-flickity-lazyload'); 3962 var srcAttr = cellElem.getAttribute('data-flickity-lazyload-src'); 3963 var srcsetAttr = cellElem.getAttribute('data-flickity-lazyload-srcset'); 3964 if ( lazyloadAttr || srcAttr || srcsetAttr ) { 3965 return [ cellElem ]; 3966 } 3967 } 3968 // select lazy images in cell 3969 var lazySelector = 'img[data-flickity-lazyload], ' + 3970 'img[data-flickity-lazyload-src], img[data-flickity-lazyload-srcset]'; 3971 var imgs = cellElem.querySelectorAll( lazySelector ); 3972 return utils.makeArray( imgs ); 3973 } 3974 3975// -------------------------- LazyLoader -------------------------- // 3976 3977 /** 3978 * class to handle loading images 3979 */ 3980 function LazyLoader( img, flickity ) { 3981 this.img = img; 3982 this.flickity = flickity; 3983 this.load(); 3984 } 3985 3986 LazyLoader.prototype.handleEvent = utils.handleEvent; 3987 3988 LazyLoader.prototype.load = function() { 3989 this.img.addEventListener( 'load', this ); 3990 this.img.addEventListener( 'error', this ); 3991 // get src & srcset 3992 var src = this.img.getAttribute('data-flickity-lazyload') || 3993 this.img.getAttribute('data-flickity-lazyload-src'); 3994 var srcset = this.img.getAttribute('data-flickity-lazyload-srcset'); 3995 // set src & serset 3996 this.img.src = src; 3997 if ( srcset ) { 3998 this.img.setAttribute( 'srcset', srcset ); 3999 } 4000 // remove attr 4001 this.img.removeAttribute('data-flickity-lazyload'); 4002 this.img.removeAttribute('data-flickity-lazyload-src'); 4003 this.img.removeAttribute('data-flickity-lazyload-srcset'); 4004 }; 4005 4006 LazyLoader.prototype.onload = function( event ) { 4007 this.complete( event, 'flickity-lazyloaded' ); 4008 }; 4009 4010 LazyLoader.prototype.onerror = function( event ) { 4011 this.complete( event, 'flickity-lazyerror' ); 4012 }; 4013 4014 LazyLoader.prototype.complete = function( event, className ) { 4015 // unbind events 4016 this.img.removeEventListener( 'load', this ); 4017 this.img.removeEventListener( 'error', this ); 4018 4019 var cell = this.flickity.getParentCell( this.img ); 4020 var cellElem = cell && cell.element; 4021 this.flickity.cellSizeChange( cellElem ); 4022 4023 this.img.classList.add( className ); 4024 this.flickity.dispatchEvent( 'lazyLoad', event, cellElem ); 4025 }; 4026 4027// ----- ----- // 4028 4029 Flickity.LazyLoader = LazyLoader; 4030 4031 return Flickity; 4032 4033})); 4034 4035/*! 4036 * Flickity v2.1.2 4037 * Touch, responsive, flickable carousels 4038 * 4039 * Licensed GPLv3 for open source use 4040 * or Flickity Commercial License for commercial use 4041 * 4042 * https://flickity.metafizzy.co 4043 * Copyright 2015-2018 Metafizzy 4044 */ 4045 4046( function( window, factory ) { 4047 // universal module definition 4048 /* jshint strict: false */ 4049 if ( typeof define == 'function' && define.amd ) { 4050 // AMD 4051 define( 'flickity/js/index',[ 4052 './flickity', 4053 './drag', 4054 './prev-next-button', 4055 './page-dots', 4056 './player', 4057 './add-remove-cell', 4058 './lazyload' 4059 ], factory ); 4060 } else if ( typeof module == 'object' && module.exports ) { 4061 // CommonJS 4062 module.exports = factory( 4063 require('./flickity'), 4064 require('./drag'), 4065 require('./prev-next-button'), 4066 require('./page-dots'), 4067 require('./player'), 4068 require('./add-remove-cell'), 4069 require('./lazyload') 4070 ); 4071 } 4072 4073})( window, function factory( Flickity ) { 4074 /*jshint strict: false*/ 4075 return Flickity; 4076}); 4077 4078/*! 4079 * Flickity asNavFor v2.0.1 4080 * enable asNavFor for Flickity 4081 */ 4082 4083/*jshint browser: true, undef: true, unused: true, strict: true*/ 4084 4085( function( window, factory ) { 4086 // universal module definition 4087 /*jshint strict: false */ /*globals define, module, require */ 4088 if ( typeof define == 'function' && define.amd ) { 4089 // AMD 4090 define( 'flickity-as-nav-for/as-nav-for',[ 4091 'flickity/js/index', 4092 'fizzy-ui-utils/utils' 4093 ], factory ); 4094 } else if ( typeof module == 'object' && module.exports ) { 4095 // CommonJS 4096 module.exports = factory( 4097 require('flickity'), 4098 require('fizzy-ui-utils') 4099 ); 4100 } else { 4101 // browser global 4102 window.Flickity = factory( 4103 window.Flickity, 4104 window.fizzyUIUtils 4105 ); 4106 } 4107 4108}( window, function factory( Flickity, utils ) { 4109 4110 4111 4112// -------------------------- asNavFor prototype -------------------------- // 4113 4114// Flickity.defaults.asNavFor = null; 4115 4116 Flickity.createMethods.push('_createAsNavFor'); 4117 4118 var proto = Flickity.prototype; 4119 4120 proto._createAsNavFor = function() { 4121 this.on( 'activate', this.activateAsNavFor ); 4122 this.on( 'deactivate', this.deactivateAsNavFor ); 4123 this.on( 'destroy', this.destroyAsNavFor ); 4124 4125 var asNavForOption = this.options.asNavFor; 4126 if ( !asNavForOption ) { 4127 return; 4128 } 4129 // HACK do async, give time for other flickity to be initalized 4130 var _this = this; 4131 setTimeout( function initNavCompanion() { 4132 _this.setNavCompanion( asNavForOption ); 4133 }); 4134 }; 4135 4136 proto.setNavCompanion = function( elem ) { 4137 elem = utils.getQueryElement( elem ); 4138 var companion = Flickity.data( elem ); 4139 // stop if no companion or companion is self 4140 if ( !companion || companion == this ) { 4141 return; 4142 } 4143 4144 this.navCompanion = companion; 4145 // companion select 4146 var _this = this; 4147 this.onNavCompanionSelect = function() { 4148 _this.navCompanionSelect(); 4149 }; 4150 companion.on( 'select', this.onNavCompanionSelect ); 4151 // click 4152 this.on( 'staticClick', this.onNavStaticClick ); 4153 4154 this.navCompanionSelect( true ); 4155 }; 4156 4157 proto.navCompanionSelect = function( isInstant ) { 4158 if ( !this.navCompanion ) { 4159 return; 4160 } 4161 // select slide that matches first cell of slide 4162 var selectedCell = this.navCompanion.selectedCells[0]; 4163 var firstIndex = this.navCompanion.cells.indexOf( selectedCell ); 4164 var lastIndex = firstIndex + this.navCompanion.selectedCells.length - 1; 4165 var selectIndex = Math.floor( lerp( firstIndex, lastIndex, 4166 this.navCompanion.cellAlign ) ); 4167 this.selectCell( selectIndex, false, isInstant ); 4168 // set nav selected class 4169 this.removeNavSelectedElements();
vendor: 5,586 bytes, lines 4170-4355
4170 // stop if companion has more cells than this one 4171 if ( selectIndex >= this.cells.length ) { 4172 return; 4173 } 4174 4175 var selectedCells = this.cells.slice( firstIndex, lastIndex + 1 ); 4176 this.navSelectedElements = selectedCells.map( function( cell ) { 4177 return cell.element; 4178 }); 4179 this.changeNavSelectedClass('add'); 4180 }; 4181 4182 function lerp( a, b, t ) { 4183 return ( b - a ) * t + a; 4184 } 4185 4186 proto.changeNavSelectedClass = function( method ) { 4187 this.navSelectedElements.forEach( function( navElem ) { 4188 navElem.classList[ method ]('is-nav-selected'); 4189 }); 4190 }; 4191 4192 proto.activateAsNavFor = function() { 4193 this.navCompanionSelect( true ); 4194 }; 4195 4196 proto.removeNavSelectedElements = function() { 4197 if ( !this.navSelectedElements ) { 4198 return; 4199 } 4200 this.changeNavSelectedClass('remove'); 4201 delete this.navSelectedElements; 4202 }; 4203 4204 proto.onNavStaticClick = function( event, pointer, cellElement, cellIndex ) { 4205 if ( typeof cellIndex == 'number' ) { 4206 this.navCompanion.selectCell( cellIndex ); 4207 } 4208 }; 4209 4210 proto.deactivateAsNavFor = function() { 4211 this.removeNavSelectedElements(); 4212 }; 4213 4214 proto.destroyAsNavFor = function() { 4215 if ( !this.navCompanion ) { 4216 return; 4217 } 4218 this.navCompanion.off( 'select', this.onNavCompanionSelect ); 4219 this.off( 'staticClick', this.onNavStaticClick ); 4220 delete this.navCompanion; 4221 }; 4222 4223// ----- ----- // 4224 4225 return Flickity; 4226 4227})); 4228 4229/*! 4230 * imagesLoaded v4.1.4 4231 * JavaScript is all like "You images are done yet or what?" 4232 * MIT License 4233 */ 4234 4235( function( window, factory ) { 'use strict'; 4236 // universal module definition 4237 4238 /*global define: false, module: false, require: false */ 4239 4240 if ( typeof define == 'function' && define.amd ) { 4241 // AMD 4242 define( 'imagesloaded/imagesloaded',[ 4243 'ev-emitter/ev-emitter' 4244 ], function( EvEmitter ) { 4245 return factory( window, EvEmitter ); 4246 }); 4247 } else if ( typeof module == 'object' && module.exports ) { 4248 // CommonJS 4249 module.exports = factory( 4250 window, 4251 require('ev-emitter') 4252 ); 4253 } else { 4254 // browser global 4255 window.imagesLoaded = factory( 4256 window, 4257 window.EvEmitter 4258 ); 4259 } 4260 4261})( typeof window !== 'undefined' ? window : this, 4262 4263// -------------------------- factory -------------------------- // 4264 4265 function factory( window, EvEmitter ) { 4266 4267 4268 4269 var $ = window.jQuery; 4270 var console = window.console; 4271 4272// -------------------------- helpers -------------------------- // 4273 4274// extend objects 4275 function extend( a, b ) { 4276 for ( var prop in b ) { 4277 a[ prop ] = b[ prop ]; 4278 } 4279 return a; 4280 } 4281 4282 var arraySlice = Array.prototype.slice; 4283 4284// turn element or nodeList into an array 4285 function makeArray( obj ) { 4286 if ( Array.isArray( obj ) ) { 4287 // use object if already an array 4288 return obj; 4289 } 4290 4291 var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number'; 4292 if ( isArrayLike ) { 4293 // convert nodeList to array 4294 return arraySlice.call( obj ); 4295 } 4296 4297 // array of single index 4298 return [ obj ]; 4299 } 4300 4301// -------------------------- imagesLoaded -------------------------- // 4302 4303 /** 4304 * @param {Array, Element, NodeList, String} elem 4305 * @param {Object or Function} options - if function, use as callback 4306 * @param {Function} onAlways - callback function 4307 */ 4308 function ImagesLoaded( elem, options, onAlways ) { 4309 // coerce ImagesLoaded() without new, to be new ImagesLoaded() 4310 if ( !( this instanceof ImagesLoaded ) ) { 4311 return new ImagesLoaded( elem, options, onAlways ); 4312 } 4313 // use elem as selector string 4314 var queryElem = elem; 4315 if ( typeof elem == 'string' ) { 4316 queryElem = document.querySelectorAll( elem ); 4317 } 4318 // bail if bad element 4319 if ( !queryElem ) { 4320 console.error( 'Bad element for imagesLoaded ' + ( queryElem || elem ) ); 4321 return; 4322 } 4323 4324 this.elements = makeArray( queryElem ); 4325 this.options = extend( {}, this.options ); 4326 // shift arguments if no options set 4327 if ( typeof options == 'function' ) { 4328 onAlways = options; 4329 } else { 4330 extend( this.options, options ); 4331 } 4332 4333 if ( onAlways ) { 4334 this.on( 'always', onAlways ); 4335 } 4336 4337 this.getImages(); 4338 4339 if ( $ ) { 4340 // add jQuery Deferred object 4341 this.jqDeferred = new $.Deferred(); 4342 } 4343 4344 // HACK check async to allow time to bind listeners 4345 setTimeout( this.check.bind( this ) ); 4346 } 4347 4348 ImagesLoaded.prototype = Object.create( EvEmitter.prototype ); 4349 4350 ImagesLoaded.prototype.options = {}; 4351 4352 ImagesLoaded.prototype.getImages = function() { 4353 this.images = []; 4354 4355 // filter & find items if we have an item selector
vendor: 4,890 bytes, lines 4356-4491
4356 this.elements.forEach( this.addElementImages, this ); 4357 }; 4358 4359 /** 4360 * @param {Node} element 4361 */ 4362 ImagesLoaded.prototype.addElementImages = function( elem ) { 4363 // filter siblings 4364 if ( elem.nodeName == 'IMG' ) { 4365 this.addImage( elem ); 4366 } 4367 // get background image on element 4368 if ( this.options.background === true ) { 4369 this.addElementBackgroundImages( elem ); 4370 } 4371 4372 // find children 4373 // no non-element nodes, #143 4374 var nodeType = elem.nodeType; 4375 if ( !nodeType || !elementNodeTypes[ nodeType ] ) { 4376 return; 4377 } 4378 var childImgs = elem.querySelectorAll('img'); 4379 // concat childElems to filterFound array 4380 for ( var i=0; i < childImgs.length; i++ ) { 4381 var img = childImgs[i]; 4382 this.addImage( img ); 4383 } 4384 4385 // get child background images 4386 if ( typeof this.options.background == 'string' ) { 4387 var children = elem.querySelectorAll( this.options.background ); 4388 for ( i=0; i < children.length; i++ ) { 4389 var child = children[i]; 4390 this.addElementBackgroundImages( child ); 4391 } 4392 } 4393 }; 4394 4395 var elementNodeTypes = { 4396 1: true, 4397 9: true, 4398 11: true 4399 }; 4400 4401 ImagesLoaded.prototype.addElementBackgroundImages = function( elem ) { 4402 var style = getComputedStyle( elem ); 4403 if ( !style ) { 4404 // Firefox returns null if in a hidden iframe https://bugzil.la/548397 4405 return; 4406 } 4407 // get url inside url("...") 4408 var reURL = /url\((['"])?(.*?)\1\)/gi; 4409 var matches = reURL.exec( style.backgroundImage ); 4410 while ( matches !== null ) { 4411 var url = matches && matches[2]; 4412 if ( url ) { 4413 this.addBackground( url, elem ); 4414 } 4415 matches = reURL.exec( style.backgroundImage ); 4416 } 4417 }; 4418 4419 /** 4420 * @param {Image} img 4421 */ 4422 ImagesLoaded.prototype.addImage = function( img ) { 4423 var loadingImage = new LoadingImage( img ); 4424 this.images.push( loadingImage ); 4425 }; 4426 4427 ImagesLoaded.prototype.addBackground = function( url, elem ) { 4428 var background = new Background( url, elem ); 4429 this.images.push( background ); 4430 }; 4431 4432 ImagesLoaded.prototype.check = function() { 4433 var _this = this; 4434 this.progressedCount = 0; 4435 this.hasAnyBroken = false; 4436 // complete if no images 4437 if ( !this.images.length ) { 4438 this.complete(); 4439 return; 4440 } 4441 4442 function onProgress( image, elem, message ) { 4443 // HACK - Chrome triggers event before object properties have changed. #83 4444 setTimeout( function() { 4445 _this.progress( image, elem, message ); 4446 }); 4447 } 4448 4449 this.images.forEach( function( loadingImage ) { 4450 loadingImage.once( 'progress', onProgress ); 4451 loadingImage.check(); 4452 }); 4453 }; 4454 4455 ImagesLoaded.prototype.progress = function( image, elem, message ) { 4456 this.progressedCount++; 4457 this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded; 4458 // progress event 4459 this.emitEvent( 'progress', [ this, image, elem ] ); 4460 if ( this.jqDeferred && this.jqDeferred.notify ) { 4461 this.jqDeferred.notify( this, image ); 4462 } 4463 // check if completed 4464 if ( this.progressedCount == this.images.length ) { 4465 this.complete(); 4466 } 4467 4468 if ( this.options.debug && console ) { 4469 console.log( 'progress: ' + message, image, elem ); 4470 } 4471 }; 4472 4473 ImagesLoaded.prototype.complete = function() { 4474 var eventName = this.hasAnyBroken ? 'fail' : 'done'; 4475 this.isComplete = true; 4476 this.emitEvent( eventName, [ this ] ); 4477 this.emitEvent( 'always', [ this ] ); 4478 if ( this.jqDeferred ) { 4479 var jqMethod = this.hasAnyBroken ? 'reject' : 'resolve'; 4480 this.jqDeferred[ jqMethod ]( this ); 4481 } 4482 }; 4483 4484// -------------------------- -------------------------- // 4485 4486 function LoadingImage( img ) { 4487 this.img = img; 4488 } 4489 4490 LoadingImage.prototype = Object.create( EvEmitter.prototype ); 4491
vendor: 4,307 bytes, lines 4492-4605
4492 LoadingImage.prototype.check = function() { 4493 // If complete is true and browser supports natural sizes, 4494 // try to check for image status manually. 4495 var isComplete = this.getIsImageComplete(); 4496 if ( isComplete ) { 4497 // report based on naturalWidth 4498 this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); 4499 return; 4500 } 4501 4502 // If none of the checks above matched, simulate loading on detached element. 4503 this.proxyImage = new Image(); 4504 this.proxyImage.addEventListener( 'load', this ); 4505 this.proxyImage.addEventListener( 'error', this ); 4506 // bind to image as well for Firefox. #191 4507 this.img.addEventListener( 'load', this ); 4508 this.img.addEventListener( 'error', this ); 4509 this.proxyImage.src = this.img.src; 4510 }; 4511 4512 LoadingImage.prototype.getIsImageComplete = function() { 4513 // check for non-zero, non-undefined naturalWidth 4514 // fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671 4515 return this.img.complete && this.img.naturalWidth; 4516 }; 4517 4518 LoadingImage.prototype.confirm = function( isLoaded, message ) { 4519 this.isLoaded = isLoaded; 4520 this.emitEvent( 'progress', [ this, this.img, message ] ); 4521 }; 4522 4523// ----- events ----- // 4524 4525// trigger specified handler for event type 4526 LoadingImage.prototype.handleEvent = function( event ) { 4527 var method = 'on' + event.type; 4528 if ( this[ method ] ) { 4529 this[ method ]( event ); 4530 } 4531 }; 4532 4533 LoadingImage.prototype.onload = function() { 4534 this.confirm( true, 'onload' ); 4535 this.unbindEvents(); 4536 }; 4537 4538 LoadingImage.prototype.onerror = function() { 4539 this.confirm( false, 'onerror' ); 4540 this.unbindEvents(); 4541 }; 4542 4543 LoadingImage.prototype.unbindEvents = function() { 4544 this.proxyImage.removeEventListener( 'load', this ); 4545 this.proxyImage.removeEventListener( 'error', this ); 4546 this.img.removeEventListener( 'load', this ); 4547 this.img.removeEventListener( 'error', this ); 4548 }; 4549 4550// -------------------------- Background -------------------------- // 4551 4552 function Background( url, element ) { 4553 this.url = url; 4554 this.element = element; 4555 this.img = new Image(); 4556 } 4557 4558// inherit LoadingImage prototype 4559 Background.prototype = Object.create( LoadingImage.prototype ); 4560 4561 Background.prototype.check = function() { 4562 this.img.addEventListener( 'load', this ); 4563 this.img.addEventListener( 'error', this ); 4564 this.img.src = this.url; 4565 // check if image is already complete 4566 var isComplete = this.getIsImageComplete(); 4567 if ( isComplete ) { 4568 this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); 4569 this.unbindEvents(); 4570 } 4571 }; 4572 4573 Background.prototype.unbindEvents = function() { 4574 this.img.removeEventListener( 'load', this ); 4575 this.img.removeEventListener( 'error', this ); 4576 }; 4577 4578 Background.prototype.confirm = function( isLoaded, message ) { 4579 this.isLoaded = isLoaded; 4580 this.emitEvent( 'progress', [ this, this.element, message ] ); 4581 }; 4582 4583// -------------------------- jQuery -------------------------- // 4584 4585 ImagesLoaded.makeJQueryPlugin = function( jQuery ) { 4586 jQuery = jQuery || window.jQuery; 4587 if ( !jQuery ) { 4588 return; 4589 } 4590 // set local variable 4591 $ = jQuery; 4592 // $().imagesLoaded() 4593 $.fn.imagesLoaded = function( options, callback ) { 4594 var instance = new ImagesLoaded( this, options, callback ); 4595 return instance.jqDeferred.promise( $(this) ); 4596 }; 4597 }; 4598// try making plugin 4599 ImagesLoaded.makeJQueryPlugin(); 4600 4601// -------------------------- -------------------------- // 4602 4603 return ImagesLoaded; 4604 4605 });
vendor: 1,856 bytes, lines 4606-4670
4606 4607/*! 4608 * Flickity imagesLoaded v2.0.0 4609 * enables imagesLoaded option for Flickity 4610 */ 4611 4612/*jshint browser: true, strict: true, undef: true, unused: true */ 4613 4614( function( window, factory ) { 4615 // universal module definition 4616 /*jshint strict: false */ /*globals define, module, require */ 4617 if ( typeof define == 'function' && define.amd ) { 4618 // AMD 4619 define( [ 4620 'flickity/js/index', 4621 'imagesloaded/imagesloaded' 4622 ], function( Flickity, imagesLoaded ) { 4623 return factory( window, Flickity, imagesLoaded ); 4624 }); 4625 } else if ( typeof module == 'object' && module.exports ) { 4626 // CommonJS 4627 module.exports = factory( 4628 window, 4629 require('flickity'), 4630 require('imagesloaded') 4631 ); 4632 } else { 4633 // browser global 4634 window.Flickity = factory( 4635 window, 4636 window.Flickity, 4637 window.imagesLoaded 4638 ); 4639 } 4640 4641}( window, function factory( window, Flickity, imagesLoaded ) { 4642 'use strict'; 4643 4644 Flickity.createMethods.push('_createImagesLoaded'); 4645 4646 var proto = Flickity.prototype; 4647 4648 proto._createImagesLoaded = function() { 4649 this.on( 'activate', this.imagesLoaded ); 4650 }; 4651 4652 proto.imagesLoaded = function() { 4653 if ( !this.options.imagesLoaded ) { 4654 return; 4655 } 4656 var _this = this; 4657 function onImagesLoadedProgress( instance, image ) { 4658 var cell = _this.getParentCell( image.img ); 4659 _this.cellSizeChange( cell && cell.element ); 4660 if ( !_this.options.freeScroll ) { 4661 _this.positionSliderAtSelected(); 4662 } 4663 } 4664 imagesLoaded( this.slider ).on( 'progress', onImagesLoadedProgress ); 4665 }; 4666 4667 return Flickity; 4668 4669})); 4670
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.