PageSourceSearch

https://www.varesenews.it/wp-content/plugins/edinet-necrologie/lib/node_modules/flickity/dist/flickity.pkgd.js

js varesenews.it collected 2026-09-24 09:11:35 UTC 118,713 bytes, 4,586 lines download raw bytes

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

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.