PageSourceSearch

https://jobs.eyesoneyecare.com/static/eyes-on-eyecare/dist/assets/js/vendor/flickity.pkgd.919e7857fbf1.js

js eyesoneyecare.com collected 2026-09-25 14:41:20 UTC 119,743 bytes, 4,596 lines download raw bytes

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

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.