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