PageSourceSearch

https://www.fullers.co.nz/cassette.axd/asset/ContentFullers360/Scr…?9bf3772dbaaf2adaa51d554ff34f6e0e92f02263

js fullers.co.nz collected 2026-09-24 09:35:25 UTC 124,530 bytes, 4,597 lines download raw bytes

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

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.