PageSourceSearch

https://amandaie.fr/wp-content/themes/salient/js/third-party/flickity.min.js?ver=2.2

js amandaie.fr collected 2026-10-07 15:36:51 UTC 126,695 bytes, 4,722 lines download raw bytes

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

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.