vendor: 47,223 bytes, lines 1-1574
1var _____WB$wombat$assign$function_____=function(name){return (globalThis._wb_wombat && globalThis._wb_wombat.local_init && globalThis._wb_wombat.local_init(name))||globalThis[name];};if(!globalThis.__WB_pmw){globalThis.__WB_pmw=function(obj){this.__WB_source=obj;return this;}}{ 2let window = _____WB$wombat$assign$function_____("window"); 3let self = _____WB$wombat$assign$function_____("self"); 4let document = _____WB$wombat$assign$function_____("document"); 5let location = _____WB$wombat$assign$function_____("location"); 6let top = _____WB$wombat$assign$function_____("top"); 7let parent = _____WB$wombat$assign$function_____("parent"); 8let frames = _____WB$wombat$assign$function_____("frames"); 9let opener = _____WB$wombat$assign$function_____("opener"); 10/*! 11 * Isotope PACKAGED v3.0.3 12 * 13 * Licensed GPLv3 for open source use 14 * or Isotope Commercial License for commercial use 15 * 16 * http://isotope.metafizzy.co 17 * Copyright 2017 Metafizzy 18 */ 19 20/** 21 * Bridget makes jQuery widgets 22 * v2.0.1 23 * MIT license 24 */ 25 26/* jshint browser: true, strict: true, undef: true, unused: true */ 27 28( function( window, factory ) { 29 // universal module definition 30 /*jshint strict: false */ /* globals define, module, require */ 31 if ( typeof define == 'function' && define.amd ) { 32 // AMD 33 define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) { 34 return factory( window, jQuery ); 35 }); 36 } else if ( typeof module == 'object' && module.exports ) { 37 // CommonJS 38 module.exports = factory( 39 window, 40 require('jquery') 41 ); 42 } else { 43 // browser global 44 window.jQueryBridget = factory( 45 window, 46 window.jQuery 47 ); 48 } 49 50}( window, function factory( window, jQuery ) { 51 'use strict'; 52 53// ----- utils ----- // 54 55 var arraySlice = Array.prototype.slice; 56 57// helper function for logging errors 58// $.error breaks jQuery chaining 59 var console = window.console; 60 var logError = typeof console == 'undefined' ? function() {} : 61 function( message ) { 62 console.error( message ); 63 }; 64 65// ----- jQueryBridget ----- // 66 67 function jQueryBridget( namespace, PluginClass, $ ) { 68 $ = $ || jQuery || window.jQuery; 69 if ( !$ ) { 70 return; 71 } 72 73 // add option method -> $().plugin('option', {...}) 74 if ( !PluginClass.prototype.option ) { 75 // option setter 76 PluginClass.prototype.option = function( opts ) { 77 // bail out if not an object 78 if ( !$.isPlainObject( opts ) ){ 79 return; 80 } 81 this.options = $.extend( true, this.options, opts ); 82 }; 83 } 84 85 // make jQuery plugin 86 $.fn[ namespace ] = function( arg0 /*, arg1 */ ) { 87 if ( typeof arg0 == 'string' ) { 88 // method call $().plugin( 'methodName', { options } ) 89 // shift arguments by 1 90 var args = arraySlice.call( arguments, 1 ); 91 return methodCall( this, arg0, args ); 92 } 93 // just $().plugin({ options }) 94 plainCall( this, arg0 ); 95 return this; 96 }; 97 98 // $().plugin('methodName') 99 function methodCall( $elems, methodName, args ) { 100 var returnValue; 101 var pluginMethodStr = '$().' + namespace + '("' + methodName + '")'; 102 103 $elems.each( function( i, elem ) { 104 // get instance 105 var instance = $.data( elem, namespace ); 106 if ( !instance ) { 107 logError( namespace + ' not initialized. Cannot call methods, i.e. ' + 108 pluginMethodStr ); 109 return; 110 } 111 112 var method = instance[ methodName ]; 113 if ( !method || methodName.charAt(0) == '_' ) { 114 logError( pluginMethodStr + ' is not a valid method' ); 115 return; 116 } 117 118 // apply method, get return value 119 var value = method.apply( instance, args ); 120 // set return value if value is returned, use only first value 121 returnValue = returnValue === undefined ? value : returnValue; 122 }); 123 124 return returnValue !== undefined ? returnValue : $elems; 125 } 126 127 function plainCall( $elems, options ) { 128 $elems.each( function( i, elem ) { 129 var instance = $.data( elem, namespace ); 130 if ( instance ) { 131 // set options & init 132 instance.option( options ); 133 instance._init(); 134 } else { 135 // initialize new instance 136 instance = new PluginClass( elem, options ); 137 $.data( elem, namespace, instance ); 138 } 139 }); 140 } 141 142 updateJQuery( $ ); 143 144 } 145 146// ----- updateJQuery ----- // 147 148// set $.bridget for v1 backwards compatibility 149 function updateJQuery( $ ) { 150 if ( !$ || ( $ && $.bridget ) ) { 151 return; 152 } 153 $.bridget = jQueryBridget; 154 } 155 156 updateJQuery( jQuery || window.jQuery ); 157 158// ----- ----- // 159 160 return jQueryBridget; 161 162})); 163 164/** 165 * EvEmitter v1.0.3 166 * Lil' event emitter 167 * MIT License 168 */ 169 170/* jshint unused: true, undef: true, strict: true */ 171 172( function( global, factory ) { 173 // universal module definition 174 /* jshint strict: false */ /* globals define, module, window */ 175 if ( typeof define == 'function' && define.amd ) { 176 // AMD - RequireJS 177 define( 'ev-emitter/ev-emitter',factory ); 178 } else if ( typeof module == 'object' && module.exports ) { 179 // CommonJS - Browserify, Webpack 180 module.exports = factory(); 181 } else { 182 // Browser globals 183 global.EvEmitter = factory(); 184 } 185 186}( typeof window != 'undefined' ? window : this, function() { 187 188 189 190 function EvEmitter() {} 191 192 var proto = EvEmitter.prototype; 193 194 proto.on = function( eventName, listener ) { 195 if ( !eventName || !listener ) { 196 return; 197 } 198 // set events hash 199 var events = this._events = this._events || {}; 200 // set listeners array 201 var listeners = events[ eventName ] = events[ eventName ] || []; 202 // only add once 203 if ( listeners.indexOf( listener ) == -1 ) { 204 listeners.push( listener ); 205 } 206 207 return this; 208 }; 209 210 proto.once = function( eventName, listener ) { 211 if ( !eventName || !listener ) { 212 return; 213 } 214 // add event 215 this.on( eventName, listener ); 216 // set once flag 217 // set onceEvents hash 218 var onceEvents = this._onceEvents = this._onceEvents || {}; 219 // set onceListeners object 220 var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {}; 221 // set flag 222 onceListeners[ listener ] = true; 223 224 return this; 225 }; 226 227 proto.off = function( eventName, listener ) { 228 var listeners = this._events && this._events[ eventName ]; 229 if ( !listeners || !listeners.length ) { 230 return; 231 } 232 var index = listeners.indexOf( listener ); 233 if ( index != -1 ) { 234 listeners.splice( index, 1 ); 235 } 236 237 return this; 238 }; 239 240 proto.emitEvent = function( eventName, args ) { 241 var listeners = this._events && this._events[ eventName ]; 242 if ( !listeners || !listeners.length ) { 243 return; 244 } 245 var i = 0; 246 var listener = listeners[i]; 247 args = args || []; 248 // once stuff 249 var onceListeners = this._onceEvents && this._onceEvents[ eventName ]; 250 251 while ( listener ) { 252 var isOnce = onceListeners && onceListeners[ listener ]; 253 if ( isOnce ) { 254 // remove listener 255 // remove before trigger to prevent recursion 256 this.off( eventName, listener ); 257 // unset once flag 258 delete onceListeners[ listener ]; 259 } 260 // trigger listener 261 listener.apply( this, args ); 262 // get next listener 263 i += isOnce ? 0 : 1; 264 listener = listeners[i]; 265 } 266 267 return this; 268 }; 269 270 return EvEmitter; 271 272})); 273 274/*! 275 * getSize v2.0.2 276 * measure size of elements 277 * MIT license 278 */ 279 280/*jshint browser: true, strict: true, undef: true, unused: true */ 281/*global define: false, module: false, console: false */ 282 283( function( window, factory ) { 284 'use strict'; 285 286 if ( typeof define == 'function' && define.amd ) { 287 // AMD 288 define( 'get-size/get-size',[],function() { 289 return factory(); 290 }); 291 } else if ( typeof module == 'object' && module.exports ) { 292 // CommonJS 293 module.exports = factory(); 294 } else { 295 // browser global 296 window.getSize = factory(); 297 } 298 299})( window, function factory() { 300 'use strict'; 301 302// -------------------------- helpers -------------------------- // 303 304// get a number from a string, not a percentage 305 function getStyleSize( value ) { 306 var num = parseFloat( value ); 307 // not a percent like '100%', and a number 308 var isValid = value.indexOf('%') == -1 && !isNaN( num ); 309 return isValid && num; 310 } 311 312 function noop() {} 313 314 var logError = typeof console == 'undefined' ? noop : 315 function( message ) { 316 console.error( message ); 317 }; 318 319// -------------------------- measurements -------------------------- // 320 321 var measurements = [ 322 'paddingLeft', 323 'paddingRight', 324 'paddingTop', 325 'paddingBottom', 326 'marginLeft', 327 'marginRight', 328 'marginTop', 329 'marginBottom', 330 'borderLeftWidth', 331 'borderRightWidth', 332 'borderTopWidth', 333 'borderBottomWidth' 334 ]; 335 336 var measurementsLength = measurements.length; 337 338 function getZeroSize() { 339 var size = { 340 width: 0, 341 height: 0, 342 innerWidth: 0, 343 innerHeight: 0, 344 outerWidth: 0, 345 outerHeight: 0 346 }; 347 for ( var i=0; i < measurementsLength; i++ ) { 348 var measurement = measurements[i]; 349 size[ measurement ] = 0; 350 } 351 return size; 352 } 353 354// -------------------------- getStyle -------------------------- // 355 356 /** 357 * getStyle, get style of element, check for Firefox bug 358 * https://bugzilla.mozilla.org/show_bug.cgi?id=548397 359 */ 360 function getStyle( elem ) { 361 var style = getComputedStyle( elem ); 362 if ( !style ) { 363 logError( 'Style returned ' + style + 364 '. Are you running this code in a hidden iframe on Firefox? ' + 365 'See http://bit.ly/getsizebug1' ); 366 } 367 return style; 368 } 369 370// -------------------------- setup -------------------------- // 371 372 var isSetup = false; 373 374 var isBoxSizeOuter; 375 376 /** 377 * setup 378 * check isBoxSizerOuter 379 * do on first getSize() rather than on page load for Firefox bug 380 */ 381 function setup() { 382 // setup once 383 if ( isSetup ) { 384 return; 385 } 386 isSetup = true; 387 388 // -------------------------- box sizing -------------------------- // 389 390 /** 391 * WebKit measures the outer-width on style.width on border-box elems 392 * IE & Firefox<29 measures the inner-width 393 */ 394 var div = document.createElement('div'); 395 div.style.width = '200px'; 396 div.style.padding = '1px 2px 3px 4px'; 397 div.style.borderStyle = 'solid'; 398 div.style.borderWidth = '1px 2px 3px 4px'; 399 div.style.boxSizing = 'border-box'; 400 401 var body = document.body || document.documentElement; 402 body.appendChild( div ); 403 var style = getStyle( div ); 404 405 getSize.isBoxSizeOuter = isBoxSizeOuter = getStyleSize( style.width ) == 200; 406 body.removeChild( div ); 407 408 } 409 410// -------------------------- getSize -------------------------- // 411 412 function getSize( elem ) { 413 setup(); 414 415 // use querySeletor if elem is string 416 if ( typeof elem == 'string' ) { 417 elem = document.querySelector( elem ); 418 } 419 420 // do not proceed on non-objects 421 if ( !elem || typeof elem != 'object' || !elem.nodeType ) { 422 return; 423 } 424 425 var style = getStyle( elem ); 426 427 // if hidden, everything is 0 428 if ( style.display == 'none' ) { 429 return getZeroSize(); 430 } 431 432 var size = {}; 433 size.width = elem.offsetWidth; 434 size.height = elem.offsetHeight; 435 436 var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box'; 437 438 // get all measurements 439 for ( var i=0; i < measurementsLength; i++ ) { 440 var measurement = measurements[i]; 441 var value = style[ measurement ]; 442 var num = parseFloat( value ); 443 // any 'auto', 'medium' value will be 0 444 size[ measurement ] = !isNaN( num ) ? num : 0; 445 } 446 447 var paddingWidth = size.paddingLeft + size.paddingRight; 448 var paddingHeight = size.paddingTop + size.paddingBottom; 449 var marginWidth = size.marginLeft + size.marginRight; 450 var marginHeight = size.marginTop + size.marginBottom; 451 var borderWidth = size.borderLeftWidth + size.borderRightWidth; 452 var borderHeight = size.borderTopWidth + size.borderBottomWidth; 453 454 var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter; 455 456 // overwrite width and height if we can get it from style 457 var styleWidth = getStyleSize( style.width ); 458 if ( styleWidth !== false ) { 459 size.width = styleWidth + 460 // add padding and border unless it's already including it 461 ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth ); 462 } 463 464 var styleHeight = getStyleSize( style.height ); 465 if ( styleHeight !== false ) { 466 size.height = styleHeight + 467 // add padding and border unless it's already including it 468 ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight ); 469 } 470 471 size.innerWidth = size.width - ( paddingWidth + borderWidth ); 472 size.innerHeight = size.height - ( paddingHeight + borderHeight ); 473 474 size.outerWidth = size.width + marginWidth; 475 size.outerHeight = size.height + marginHeight; 476 477 return size; 478 } 479 480 return getSize; 481 482}); 483 484/** 485 * matchesSelector v2.0.2 486 * matchesSelector( element, '.selector' ) 487 * MIT license 488 */ 489 490/*jshint browser: true, strict: true, undef: true, unused: true */ 491 492( function( window, factory ) { 493 /*global define: false, module: false */ 494 'use strict'; 495 // universal module definition 496 if ( typeof define == 'function' && define.amd ) { 497 // AMD 498 define( 'desandro-matches-selector/matches-selector',factory ); 499 } else if ( typeof module == 'object' && module.exports ) { 500 // CommonJS 501 module.exports = factory(); 502 } else { 503 // browser global 504 window.matchesSelector = factory(); 505 } 506 507}( window, function factory() { 508 'use strict'; 509 510 var matchesMethod = ( function() { 511 var ElemProto = window.Element.prototype; 512 // check for the standard method name first 513 if ( ElemProto.matches ) { 514 return 'matches'; 515 } 516 // check un-prefixed 517 if ( ElemProto.matchesSelector ) { 518 return 'matchesSelector'; 519 } 520 // check vendor prefixes 521 var prefixes = [ 'webkit', 'moz', 'ms', 'o' ]; 522 523 for ( var i=0; i < prefixes.length; i++ ) { 524 var prefix = prefixes[i]; 525 var method = prefix + 'MatchesSelector'; 526 if ( ElemProto[ method ] ) { 527 return method; 528 } 529 } 530 })(); 531 532 return function matchesSelector( elem, selector ) { 533 return elem[ matchesMethod ]( selector ); 534 }; 535 536})); 537 538/** 539 * Fizzy UI utils v2.0.4 540 * MIT license 541 */ 542 543/*jshint browser: true, undef: true, unused: true, strict: true */ 544 545( function( window, factory ) { 546 // universal module definition 547 /*jshint strict: false */ /*globals define, module, require */ 548 549 if ( typeof define == 'function' && define.amd ) { 550 // AMD 551 define( 'fizzy-ui-utils/utils',[ 552 'desandro-matches-selector/matches-selector' 553 ], function( matchesSelector ) { 554 return factory( window, matchesSelector ); 555 }); 556 } else if ( typeof module == 'object' && module.exports ) { 557 // CommonJS 558 module.exports = factory( 559 window, 560 require('desandro-matches-selector') 561 ); 562 } else { 563 // browser global 564 window.fizzyUIUtils = factory( 565 window, 566 window.matchesSelector 567 ); 568 } 569 570}( window, function factory( window, matchesSelector ) { 571 572 573 574 var utils = {}; 575 576// ----- extend ----- // 577 578// extends objects 579 utils.extend = function( a, b ) { 580 for ( var prop in b ) { 581 a[ prop ] = b[ prop ]; 582 } 583 return a; 584 }; 585 586// ----- modulo ----- // 587 588 utils.modulo = function( num, div ) { 589 return ( ( num % div ) + div ) % div; 590 }; 591 592// ----- makeArray ----- // 593 594// turn element or nodeList into an array 595 utils.makeArray = function( obj ) { 596 var ary = []; 597 if ( Array.isArray( obj ) ) { 598 // use object if already an array 599 ary = obj; 600 } else if ( obj && typeof obj == 'object' && 601 typeof obj.length == 'number' ) { 602 // convert nodeList to array 603 for ( var i=0; i < obj.length; i++ ) { 604 ary.push( obj[i] ); 605 } 606 } else { 607 // array of single index 608 ary.push( obj ); 609 } 610 return ary; 611 }; 612 613// ----- removeFrom ----- // 614 615 utils.removeFrom = function( ary, obj ) { 616 var index = ary.indexOf( obj ); 617 if ( index != -1 ) { 618 ary.splice( index, 1 ); 619 } 620 }; 621 622// ----- getParent ----- // 623 624 utils.getParent = function( elem, selector ) { 625 while ( elem != document.body ) { 626 elem = elem.parentNode; 627 if ( matchesSelector( elem, selector ) ) { 628 return elem; 629 } 630 } 631 }; 632 633// ----- getQueryElement ----- // 634 635// use element as selector string 636 utils.getQueryElement = function( elem ) { 637 if ( typeof elem == 'string' ) { 638 return document.querySelector( elem ); 639 } 640 return elem; 641 }; 642 643// ----- handleEvent ----- // 644 645// enable .ontype to trigger from .addEventListener( elem, 'type' ) 646 utils.handleEvent = function( event ) { 647 var method = 'on' + event.type; 648 if ( this[ method ] ) { 649 this[ method ]( event ); 650 } 651 }; 652 653// ----- filterFindElements ----- // 654 655 utils.filterFindElements = function( elems, selector ) { 656 // make array of elems 657 elems = utils.makeArray( elems ); 658 var ffElems = []; 659 660 elems.forEach( function( elem ) { 661 // check that elem is an actual element 662 if ( !( elem instanceof HTMLElement ) ) { 663 return; 664 } 665 // add elem if no selector 666 if ( !selector ) { 667 ffElems.push( elem ); 668 return; 669 } 670 // filter & find items if we have a selector 671 // filter 672 if ( matchesSelector( elem, selector ) ) { 673 ffElems.push( elem ); 674 } 675 // find children 676 var childElems = elem.querySelectorAll( selector ); 677 // concat childElems to filterFound array 678 for ( var i=0; i < childElems.length; i++ ) { 679 ffElems.push( childElems[i] ); 680 } 681 }); 682 683 return ffElems; 684 }; 685 686// ----- debounceMethod ----- // 687 688 utils.debounceMethod = function( _class, methodName, threshold ) { 689 // original method 690 var method = _class.prototype[ methodName ]; 691 var timeoutName = methodName + 'Timeout'; 692 693 _class.prototype[ methodName ] = function() { 694 var timeout = this[ timeoutName ]; 695 if ( timeout ) { 696 clearTimeout( timeout ); 697 } 698 var args = arguments; 699 700 var _this = this; 701 this[ timeoutName ] = setTimeout( function() { 702 method.apply( _this, args ); 703 delete _this[ timeoutName ]; 704 }, threshold || 100 ); 705 }; 706 }; 707 708// ----- docReady ----- // 709 710 utils.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/ 723 utils.toDashed = function( str ) { 724 return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) { 725 return $1 + '-' + $2; 726 }).toLowerCase(); 727 }; 728 729 var 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 */ 735 utils.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 773 return utils; 774 775})); 776 777/** 778 * Outlayer Item 779 */ 780 781( function( window, factory ) { 782 // universal module definition 783 /* jshint strict: false */ /* globals define, module, require */ 784 if ( typeof define == 'function' && define.amd ) { 785 // AMD - RequireJS 786 define( 'outlayer/item',[ 787 'ev-emitter/ev-emitter', 788 'get-size/get-size' 789 ], 790 factory 791 ); 792 } else if ( typeof module == 'object' && module.exports ) { 793 // CommonJS - Browserify, Webpack 794 module.exports = factory( 795 require('ev-emitter'), 796 require('get-size') 797 ); 798 } else { 799 // browser global 800 window.Outlayer = {}; 801 window.Outlayer.Item = factory( 802 window.EvEmitter, 803 window.getSize 804 ); 805 } 806 807}( window, function factory( EvEmitter, getSize ) { 808 'use strict'; 809 810// ----- helpers ----- // 811 812 function isEmptyObj( obj ) { 813 for ( var prop in obj ) { 814 return false; 815 } 816 prop = null; 817 return true; 818 } 819 820// -------------------------- CSS3 support -------------------------- // 821 822 823 var docElemStyle = document.documentElement.style; 824 825 var transitionProperty = typeof docElemStyle.transition == 'string' ? 826 'transition' : 'WebkitTransition'; 827 var transformProperty = typeof docElemStyle.transform == 'string' ? 828 'transform' : 'WebkitTransform'; 829 830 var transitionEndEvent = { 831 WebkitTransition: 'webkitTransitionEnd', 832 transition: 'transitionend' 833 }[ transitionProperty ]; 834 835// cache all vendor properties that could have vendor prefix 836 var vendorProperties = { 837 transform: transformProperty, 838 transition: transitionProperty, 839 transitionDuration: transitionProperty + 'Duration', 840 transitionProperty: transitionProperty + 'Property', 841 transitionDelay: transitionProperty + 'Delay' 842 }; 843 844// -------------------------- Item -------------------------- // 845 846 function Item( element, layout ) { 847 if ( !element ) { 848 return; 849 } 850 851 this.element = element; 852 // parent layout class, i.e. Masonry, Isotope, or Packery 853 this.layout = layout; 854 this.position = { 855 x: 0, 856 y: 0 857 }; 858 859 this._create(); 860 } 861 862// inherit EvEmitter 863 var proto = Item.prototype = Object.create( EvEmitter.prototype ); 864 proto.constructor = Item; 865 866 proto._create = function() { 867 // transition objects 868 this._transn = { 869 ingProperties: {}, 870 clean: {}, 871 onEnd: {} 872 }; 873 874 this.css({ 875 position: 'absolute' 876 }); 877 }; 878 879// trigger specified handler for event type 880 proto.handleEvent = function( event ) { 881 var method = 'on' + event.type; 882 if ( this[ method ] ) { 883 this[ method ]( event ); 884 } 885 }; 886 887 proto.getSize = function() { 888 this.size = getSize( this.element ); 889 }; 890 891 /** 892 * apply CSS styles to element 893 * @param {Object} style 894 */ 895 proto.css = function( style ) { 896 var elemStyle = this.element.style; 897 898 for ( var prop in style ) { 899 // use vendor property if available 900 var supportedProp = vendorProperties[ prop ] || prop; 901 elemStyle[ supportedProp ] = style[ prop ]; 902 } 903 }; 904 905 // measure position, and sets it 906 proto.getPosition = function() { 907 var style = getComputedStyle( this.element ); 908 var isOriginLeft = this.layout._getOption('originLeft'); 909 var isOriginTop = this.layout._getOption('originTop'); 910 var xValue = style[ isOriginLeft ? 'left' : 'right' ]; 911 var yValue = style[ isOriginTop ? 'top' : 'bottom' ]; 912 // convert percent to pixels 913 var layoutSize = this.layout.size; 914 var x = xValue.indexOf('%') != -1 ? 915 ( parseFloat( xValue ) / 100 ) * layoutSize.width : parseInt( xValue, 10 ); 916 var y = yValue.indexOf('%') != -1 ? 917 ( parseFloat( yValue ) / 100 ) * layoutSize.height : parseInt( yValue, 10 ); 918 919 // clean up 'auto' or other non-integer values 920 x = isNaN( x ) ? 0 : x; 921 y = isNaN( y ) ? 0 : y; 922 // remove padding from measurement 923 x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight; 924 y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom; 925 926 this.position.x = x; 927 this.position.y = y; 928 }; 929 930// set settled position, apply padding 931 proto.layoutPosition = function() { 932 var layoutSize = this.layout.size; 933 var style = {}; 934 var isOriginLeft = this.layout._getOption('originLeft'); 935 var isOriginTop = this.layout._getOption('originTop'); 936 937 // x 938 var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight'; 939 var xProperty = isOriginLeft ? 'left' : 'right'; 940 var xResetProperty = isOriginLeft ? 'right' : 'left'; 941 942 var x = this.position.x + layoutSize[ xPadding ]; 943 // set in percentage or pixels 944 style[ xProperty ] = this.getXValue( x ); 945 // reset other property 946 style[ xResetProperty ] = ''; 947 948 // y 949 var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom'; 950 var yProperty = isOriginTop ? 'top' : 'bottom'; 951 var yResetProperty = isOriginTop ? 'bottom' : 'top'; 952 953 var y = this.position.y + layoutSize[ yPadding ]; 954 // set in percentage or pixels 955 style[ yProperty ] = this.getYValue( y ); 956 // reset other property 957 style[ yResetProperty ] = ''; 958 959 this.css( style ); 960 this.emitEvent( 'layout', [ this ] ); 961 }; 962 963 proto.getXValue = function( x ) { 964 var isHorizontal = this.layout._getOption('horizontal'); 965 return this.layout.options.percentPosition && !isHorizontal ? 966 ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px'; 967 }; 968 969 proto.getYValue = function( y ) { 970 var isHorizontal = this.layout._getOption('horizontal'); 971 return this.layout.options.percentPosition && isHorizontal ? 972 ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px'; 973 }; 974 975 proto._transitionTo = function( x, y ) { 976 this.getPosition(); 977 // get current x & y from top/left 978 var curX = this.position.x; 979 var curY = this.position.y; 980 981 var compareX = parseInt( x, 10 ); 982 var compareY = parseInt( y, 10 ); 983 var didNotMove = compareX === this.position.x && compareY === this.position.y; 984 985 // save end position 986 this.setPosition( x, y ); 987 988 // if did not move and not transitioning, just go to layout 989 if ( didNotMove && !this.isTransitioning ) { 990 this.layoutPosition(); 991 return; 992 } 993 994 var transX = x - curX; 995 var transY = y - curY; 996 var transitionStyle = {}; 997 transitionStyle.transform = this.getTranslate( transX, transY ); 998 999 this.transition({ 1000 to: transitionStyle, 1001 onTransitionEnd: { 1002 transform: this.layoutPosition 1003 }, 1004 isCleaning: true 1005 }); 1006 }; 1007 1008 proto.getTranslate = function( x, y ) { 1009 // flip cooridinates if origin on right or bottom 1010 var isOriginLeft = this.layout._getOption('originLeft'); 1011 var isOriginTop = this.layout._getOption('originTop'); 1012 x = isOriginLeft ? x : -x; 1013 y = isOriginTop ? y : -y; 1014 return 'translate3d(' + x + 'px, ' + y + 'px, 0)'; 1015 }; 1016 1017// non transition + transform support 1018 proto.goTo = function( x, y ) { 1019 this.setPosition( x, y ); 1020 this.layoutPosition(); 1021 }; 1022 1023 proto.moveTo = proto._transitionTo; 1024 1025 proto.setPosition = function( x, y ) { 1026 this.position.x = parseInt( x, 10 ); 1027 this.position.y = parseInt( y, 10 ); 1028 }; 1029 1030// ----- transition ----- // 1031 1032 /** 1033 * @param {Object} style - CSS 1034 * @param {Function} onTransitionEnd 1035 */ 1036 1037// non transition, just trigger callback 1038 proto._nonTransition = function( args ) { 1039 this.css( args.to ); 1040 if ( args.isCleaning ) { 1041 this._removeStyles( args.to ); 1042 } 1043 for ( var prop in args.onTransitionEnd ) { 1044 args.onTransitionEnd[ prop ].call( this ); 1045 } 1046 }; 1047 1048 /** 1049 * proper transition 1050 * @param {Object} args - arguments 1051 * @param {Object} to - style to transition to 1052 * @param {Object} from - style to start transition from 1053 * @param {Boolean} isCleaning - removes transition styles after transition 1054 * @param {Function} onTransitionEnd - callback 1055 */ 1056 proto.transition = function( args ) { 1057 // redirect to nonTransition if no transition duration 1058 if ( !parseFloat( this.layout.options.transitionDuration ) ) { 1059 this._nonTransition( args ); 1060 return; 1061 } 1062 1063 var _transition = this._transn; 1064 // keep track of onTransitionEnd callback by css property 1065 for ( var prop in args.onTransitionEnd ) { 1066 _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ]; 1067 } 1068 // keep track of properties that are transitioning 1069 for ( prop in args.to ) { 1070 _transition.ingProperties[ prop ] = true; 1071 // keep track of properties to clean up when transition is done 1072 if ( args.isCleaning ) { 1073 _transition.clean[ prop ] = true; 1074 } 1075 } 1076 1077 // set from styles 1078 if ( args.from ) { 1079 this.css( args.from ); 1080 // force redraw. http://blog.alexmaccaw.com/css-transitions 1081 var h = this.element.offsetHeight; 1082 // hack for JSHint to hush about unused var 1083 h = null; 1084 } 1085 // enable transition 1086 this.enableTransition( args.to ); 1087 // set styles that are transitioning 1088 this.css( args.to ); 1089 1090 this.isTransitioning = true; 1091 1092 }; 1093 1094// dash before all cap letters, including first for 1095// WebkitTransform => -webkit-transform 1096 function toDashedAll( str ) { 1097 return str.replace( /([A-Z])/g, function( $1 ) { 1098 return '-' + $1.toLowerCase(); 1099 }); 1100 } 1101 1102 var transitionProps = 'opacity,' + toDashedAll( transformProperty ); 1103 1104 proto.enableTransition = function(/* style */) { 1105 // HACK changing transitionProperty during a transition 1106 // will cause transition to jump 1107 if ( this.isTransitioning ) { 1108 return; 1109 } 1110 1111 // make `transition: foo, bar, baz` from style object 1112 // HACK un-comment this when enableTransition can work 1113 // while a transition is happening 1114 // var transitionValues = []; 1115 // for ( var prop in style ) { 1116 // // dash-ify camelCased properties like WebkitTransition 1117 // prop = vendorProperties[ prop ] || prop; 1118 // transitionValues.push( toDashedAll( prop ) ); 1119 // } 1120 // munge number to millisecond, to match stagger 1121 var duration = this.layout.options.transitionDuration; 1122 duration = typeof duration == 'number' ? duration + 'ms' : duration; 1123 // enable transition styles 1124 this.css({ 1125 transitionProperty: transitionProps, 1126 transitionDuration: duration, 1127 transitionDelay: this.staggerDelay || 0 1128 }); 1129 // listen for transition end event 1130 this.element.addEventListener( transitionEndEvent, this, false ); 1131 }; 1132 1133// ----- events ----- // 1134 1135 proto.onwebkitTransitionEnd = function( event ) { 1136 this.ontransitionend( event ); 1137 }; 1138 1139 proto.onotransitionend = function( event ) { 1140 this.ontransitionend( event ); 1141 }; 1142 1143// properties that I munge to make my life easier 1144 var dashedVendorProperties = { 1145 '-webkit-transform': 'transform' 1146 }; 1147 1148 proto.ontransitionend = function( event ) { 1149 // disregard bubbled events from children 1150 if ( event.target !== this.element ) { 1151 return; 1152 } 1153 var _transition = this._transn; 1154 // get property name of transitioned property, convert to prefix-free 1155 var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName; 1156 1157 // remove property that has completed transitioning 1158 delete _transition.ingProperties[ propertyName ]; 1159 // check if any properties are still transitioning 1160 if ( isEmptyObj( _transition.ingProperties ) ) { 1161 // all properties have completed transitioning 1162 this.disableTransition(); 1163 } 1164 // clean style 1165 if ( propertyName in _transition.clean ) { 1166 // clean up style 1167 this.element.style[ event.propertyName ] = ''; 1168 delete _transition.clean[ propertyName ]; 1169 } 1170 // trigger onTransitionEnd callback 1171 if ( propertyName in _transition.onEnd ) { 1172 var onTransitionEnd = _transition.onEnd[ propertyName ]; 1173 onTransitionEnd.call( this ); 1174 delete _transition.onEnd[ propertyName ]; 1175 } 1176 1177 this.emitEvent( 'transitionEnd', [ this ] ); 1178 }; 1179 1180 proto.disableTransition = function() { 1181 this.removeTransitionStyles(); 1182 this.element.removeEventListener( transitionEndEvent, this, false ); 1183 this.isTransitioning = false; 1184 }; 1185 1186 /** 1187 * removes style property from element 1188 * @param {Object} style 1189 **/ 1190 proto._removeStyles = function( style ) { 1191 // clean up transition styles 1192 var cleanStyle = {}; 1193 for ( var prop in style ) { 1194 cleanStyle[ prop ] = ''; 1195 } 1196 this.css( cleanStyle ); 1197 }; 1198 1199 var cleanTransitionStyle = { 1200 transitionProperty: '', 1201 transitionDuration: '', 1202 transitionDelay: '' 1203 }; 1204 1205 proto.removeTransitionStyles = function() { 1206 // remove transition 1207 this.css( cleanTransitionStyle ); 1208 }; 1209 1210// ----- stagger ----- // 1211 1212 proto.stagger = function( delay ) { 1213 delay = isNaN( delay ) ? 0 : delay; 1214 this.staggerDelay = delay + 'ms'; 1215 }; 1216 1217// ----- show/hide/remove ----- // 1218 1219// remove element from DOM 1220 proto.removeElem = function() { 1221 this.element.parentNode.removeChild( this.element ); 1222 // remove display: none 1223 this.css({ display: '' }); 1224 this.emitEvent( 'remove', [ this ] ); 1225 }; 1226 1227 proto.remove = function() { 1228 // just remove element if no transition support or no transition 1229 if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) { 1230 this.removeElem(); 1231 return; 1232 } 1233 1234 // start transition 1235 this.once( 'transitionEnd', function() { 1236 this.removeElem(); 1237 }); 1238 this.hide(); 1239 }; 1240 1241 proto.reveal = function() { 1242 delete this.isHidden; 1243 // remove display: none 1244 this.css({ display: '' }); 1245 1246 var options = this.layout.options; 1247 1248 var onTransitionEnd = {}; 1249 var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle'); 1250 onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd; 1251 1252 this.transition({ 1253 from: options.hiddenStyle, 1254 to: options.visibleStyle, 1255 isCleaning: true, 1256 onTransitionEnd: onTransitionEnd 1257 }); 1258 }; 1259 1260 proto.onRevealTransitionEnd = function() { 1261 // check if still visible 1262 // during transition, item may have been hidden 1263 if ( !this.isHidden ) { 1264 this.emitEvent('reveal'); 1265 } 1266 }; 1267 1268 /** 1269 * get style property use for hide/reveal transition end 1270 * @param {String} styleProperty - hiddenStyle/visibleStyle 1271 * @returns {String} 1272 */ 1273 proto.getHideRevealTransitionEndProperty = function( styleProperty ) { 1274 var optionStyle = this.layout.options[ styleProperty ]; 1275 // use opacity 1276 if ( optionStyle.opacity ) { 1277 return 'opacity'; 1278 } 1279 // get first property 1280 for ( var prop in optionStyle ) { 1281 return prop; 1282 } 1283 }; 1284 1285 proto.hide = function() { 1286 // set flag 1287 this.isHidden = true; 1288 // remove display: none 1289 this.css({ display: '' }); 1290 1291 var options = this.layout.options; 1292 1293 var onTransitionEnd = {}; 1294 var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle'); 1295 onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd; 1296 1297 this.transition({ 1298 from: options.visibleStyle, 1299 to: options.hiddenStyle, 1300 // keep hidden stuff hidden 1301 isCleaning: true, 1302 onTransitionEnd: onTransitionEnd 1303 }); 1304 }; 1305 1306 proto.onHideTransitionEnd = function() { 1307 // check if still hidden 1308 // during transition, item may have been un-hidden 1309 if ( this.isHidden ) { 1310 this.css({ display: 'none' }); 1311 this.emitEvent('hide'); 1312 } 1313 }; 1314 1315 proto.destroy = function() { 1316 this.css({ 1317 position: '', 1318 left: '', 1319 right: '', 1320 top: '', 1321 bottom: '', 1322 transition: '', 1323 transform: '' 1324 }); 1325 }; 1326 1327 return Item; 1328 1329})); 1330 1331/*! 1332 * Outlayer v2.1.0 1333 * the brains and guts of a layout library 1334 * MIT license 1335 */ 1336 1337( function( window, factory ) { 1338 'use strict'; 1339 // universal module definition 1340 /* jshint strict: false */ /* globals define, module, require */ 1341 if ( typeof define == 'function' && define.amd ) { 1342 // AMD - RequireJS 1343 define( 'outlayer/outlayer',[ 1344 'ev-emitter/ev-emitter', 1345 'get-size/get-size', 1346 'fizzy-ui-utils/utils', 1347 './item' 1348 ], 1349 function( EvEmitter, getSize, utils, Item ) { 1350 return factory( window, EvEmitter, getSize, utils, Item); 1351 } 1352 ); 1353 } else if ( typeof module == 'object' && module.exports ) { 1354 // CommonJS - Browserify, Webpack 1355 module.exports = factory( 1356 window, 1357 require('ev-emitter'), 1358 require('get-size'), 1359 require('fizzy-ui-utils'), 1360 require('./item') 1361 ); 1362 } else { 1363 // browser global 1364 window.Outlayer = factory( 1365 window, 1366 window.EvEmitter, 1367 window.getSize, 1368 window.fizzyUIUtils, 1369 window.Outlayer.Item 1370 ); 1371 } 1372 1373}( window, function factory( window, EvEmitter, getSize, utils, Item ) { 1374 'use strict'; 1375 1376// ----- vars ----- // 1377 1378 var console = window.console; 1379 var jQuery = window.jQuery; 1380 var noop = function() {}; 1381 1382// -------------------------- Outlayer -------------------------- // 1383 1384// globally unique identifiers 1385 var GUID = 0; 1386// internal store of all Outlayer intances 1387 var instances = {}; 1388 1389 1390 /** 1391 * @param {Element, String} element 1392 * @param {Object} options 1393 * @constructor 1394 */ 1395 function Outlayer( element, options ) { 1396 var queryElement = utils.getQueryElement( element ); 1397 if ( !queryElement ) { 1398 if ( console ) { 1399 console.error( 'Bad element for ' + this.constructor.namespace + 1400 ': ' + ( queryElement || element ) ); 1401 } 1402 return; 1403 } 1404 this.element = queryElement; 1405 // add jQuery 1406 if ( jQuery ) { 1407 this.$element = jQuery( this.element ); 1408 } 1409 1410 // options 1411 this.options = utils.extend( {}, this.constructor.defaults ); 1412 this.option( options ); 1413 1414 // add id for Outlayer.getFromElement 1415 var id = ++GUID; 1416 this.element.outlayerGUID = id; // expando 1417 instances[ id ] = this; // associate via id 1418 1419 // kick it off 1420 this._create(); 1421 1422 var isInitLayout = this._getOption('initLayout'); 1423 if ( isInitLayout ) { 1424 this.layout(); 1425 } 1426 } 1427 1428// settings are for internal use only 1429 Outlayer.namespace = 'outlayer'; 1430 Outlayer.Item = Item; 1431 1432// default options 1433 Outlayer.defaults = { 1434 containerStyle: { 1435 position: 'relative' 1436 }, 1437 initLayout: true, 1438 originLeft: true, 1439 originTop: true, 1440 resize: true, 1441 resizeContainer: true, 1442 // item options 1443 transitionDuration: '0.4s', 1444 hiddenStyle: { 1445 opacity: 0, 1446 transform: 'scale(0.001)' 1447 }, 1448 visibleStyle: { 1449 opacity: 1, 1450 transform: 'scale(1)' 1451 } 1452 }; 1453 1454 var proto = Outlayer.prototype; 1455// inherit EvEmitter 1456 utils.extend( proto, EvEmitter.prototype ); 1457 1458 /** 1459 * set options 1460 * @param {Object} opts 1461 */ 1462 proto.option = function( opts ) { 1463 utils.extend( this.options, opts ); 1464 }; 1465 1466 /** 1467 * get backwards compatible option value, check old name 1468 */ 1469 proto._getOption = function( option ) { 1470 var oldOption = this.constructor.compatOptions[ option ]; 1471 return oldOption && this.options[ oldOption ] !== undefined ? 1472 this.options[ oldOption ] : this.options[ option ]; 1473 }; 1474 1475 Outlayer.compatOptions = { 1476 // currentName: oldName 1477 initLayout: 'isInitLayout', 1478 horizontal: 'isHorizontal', 1479 layoutInstant: 'isLayoutInstant', 1480 originLeft: 'isOriginLeft', 1481 originTop: 'isOriginTop', 1482 resize: 'isResizeBound', 1483 resizeContainer: 'isResizingContainer' 1484 }; 1485 1486 proto._create = function() { 1487 // get items from children 1488 this.reloadItems(); 1489 // elements that affect layout, but are not laid out 1490 this.stamps = []; 1491 this.stamp( this.options.stamp ); 1492 // set container style 1493 utils.extend( this.element.style, this.options.containerStyle ); 1494 1495 // bind resize method 1496 var canBindResize = this._getOption('resize'); 1497 if ( canBindResize ) { 1498 this.bindResize(); 1499 } 1500 }; 1501 1502// goes through all children again and gets bricks in proper order 1503 proto.reloadItems = function() { 1504 // collection of item elements 1505 this.items = this._itemize( this.element.children ); 1506 }; 1507 1508 1509 /** 1510 * turn elements into Outlayer.Items to be used in layout 1511 * @param {Array or NodeList or HTMLElement} elems 1512 * @returns {Array} items - collection of new Outlayer Items 1513 */ 1514 proto._itemize = function( elems ) { 1515 1516 var itemElems = this._filterFindItemElements( elems ); 1517 var Item = this.constructor.Item; 1518 1519 // create new Outlayer Items for collection 1520 var items = []; 1521 for ( var i=0; i < itemElems.length; i++ ) { 1522 var elem = itemElems[i]; 1523 var item = new Item( elem, this ); 1524 items.push( item ); 1525 } 1526 1527 return items; 1528 }; 1529 1530 /** 1531 * get item elements to be used in layout 1532 * @param {Array or NodeList or HTMLElement} elems 1533 * @returns {Array} items - item elements 1534 */ 1535 proto._filterFindItemElements = function( elems ) { 1536 return utils.filterFindElements( elems, this.options.itemSelector ); 1537 }; 1538 1539 /** 1540 * getter method for getting item elements 1541 * @returns {Array} elems - collection of item elements 1542 */ 1543 proto.getItemElements = function() { 1544 return this.items.map( function( item ) { 1545 return item.element; 1546 }); 1547 }; 1548 1549// ----- init & layout ----- // 1550 1551 /** 1552 * lays out all items 1553 */ 1554 proto.layout = function() { 1555 this._resetLayout(); 1556 this._manageStamps(); 1557 1558 // don't animate first layout 1559 var layoutInstant = this._getOption('layoutInstant'); 1560 var isInstant = layoutInstant !== undefined ? 1561 layoutInstant : !this._isLayoutInited; 1562 this.layoutItems( this.items, isInstant ); 1563 1564 // flag for initalized 1565 this._isLayoutInited = true; 1566 }; 1567 1568// _init is alias for layout 1569 proto._init = proto.layout; 1570 1571 /** 1572 * logic before any new layout 1573 */ 1574 proto._resetLayout = function() {
vendor: 15,627 bytes, lines 1575-2119
1575 this.getSize(); 1576 }; 1577 1578 1579 proto.getSize = function() { 1580 this.size = getSize( this.element ); 1581 }; 1582 1583 /** 1584 * get measurement from option, for columnWidth, rowHeight, gutter 1585 * if option is String -> get element from selector string, & get size of element 1586 * if option is Element -> get size of element 1587 * else use option as a number 1588 * 1589 * @param {String} measurement 1590 * @param {String} size - width or height 1591 * @private 1592 */ 1593 proto._getMeasurement = function( measurement, size ) { 1594 var option = this.options[ measurement ]; 1595 var elem; 1596 if ( !option ) { 1597 // default to 0 1598 this[ measurement ] = 0; 1599 } else { 1600 // use option as an element 1601 if ( typeof option == 'string' ) { 1602 elem = this.element.querySelector( option ); 1603 } else if ( option instanceof HTMLElement ) { 1604 elem = option; 1605 } 1606 // use size of element, if element 1607 this[ measurement ] = elem ? getSize( elem )[ size ] : option; 1608 } 1609 }; 1610 1611 /** 1612 * layout a collection of item elements 1613 * @api public 1614 */ 1615 proto.layoutItems = function( items, isInstant ) { 1616 items = this._getItemsForLayout( items ); 1617 1618 this._layoutItems( items, isInstant ); 1619 1620 this._postLayout(); 1621 }; 1622 1623 /** 1624 * get the items to be laid out 1625 * you may want to skip over some items 1626 * @param {Array} items 1627 * @returns {Array} items 1628 */ 1629 proto._getItemsForLayout = function( items ) { 1630 return items.filter( function( item ) { 1631 return !item.isIgnored; 1632 }); 1633 }; 1634 1635 /** 1636 * layout items 1637 * @param {Array} items 1638 * @param {Boolean} isInstant 1639 */ 1640 proto._layoutItems = function( items, isInstant ) { 1641 this._emitCompleteOnItems( 'layout', items ); 1642 1643 if ( !items || !items.length ) { 1644 // no items, emit event with empty array 1645 return; 1646 } 1647 1648 var queue = []; 1649 1650 items.forEach( function( item ) { 1651 // get x/y object from method 1652 var position = this._getItemLayoutPosition( item ); 1653 // enqueue 1654 position.item = item; 1655 position.isInstant = isInstant || item.isLayoutInstant; 1656 queue.push( position ); 1657 }, this ); 1658 1659 this._processLayoutQueue( queue ); 1660 }; 1661 1662 /** 1663 * get item layout position 1664 * @param {Outlayer.Item} item 1665 * @returns {Object} x and y position 1666 */ 1667 proto._getItemLayoutPosition = function( /* item */ ) { 1668 return { 1669 x: 0, 1670 y: 0 1671 }; 1672 }; 1673 1674 /** 1675 * iterate over array and position each item 1676 * Reason being - separating this logic prevents 'layout invalidation' 1677 * thx @paul_irish 1678 * @param {Array} queue 1679 */ 1680 proto._processLayoutQueue = function( queue ) { 1681 this.updateStagger(); 1682 queue.forEach( function( obj, i ) { 1683 this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i ); 1684 }, this ); 1685 }; 1686 1687// set stagger from option in milliseconds number 1688 proto.updateStagger = function() { 1689 var stagger = this.options.stagger; 1690 if ( stagger === null || stagger === undefined ) { 1691 this.stagger = 0; 1692 return; 1693 } 1694 this.stagger = getMilliseconds( stagger ); 1695 return this.stagger; 1696 }; 1697 1698 /** 1699 * Sets position of item in DOM 1700 * @param {Outlayer.Item} item 1701 * @param {Number} x - horizontal position 1702 * @param {Number} y - vertical position 1703 * @param {Boolean} isInstant - disables transitions 1704 */ 1705 proto._positionItem = function( item, x, y, isInstant, i ) { 1706 if ( isInstant ) { 1707 // if not transition, just set CSS 1708 item.goTo( x, y ); 1709 } else { 1710 item.stagger( i * this.stagger ); 1711 item.moveTo( x, y ); 1712 } 1713 }; 1714 1715 /** 1716 * Any logic you want to do after each layout, 1717 * i.e. size the container 1718 */ 1719 proto._postLayout = function() { 1720 this.resizeContainer(); 1721 }; 1722 1723 proto.resizeContainer = function() { 1724 var isResizingContainer = this._getOption('resizeContainer'); 1725 if ( !isResizingContainer ) { 1726 return; 1727 } 1728 var size = this._getContainerSize(); 1729 if ( size ) { 1730 this._setContainerMeasure( size.width, true ); 1731 this._setContainerMeasure( size.height, false ); 1732 } 1733 }; 1734 1735 /** 1736 * Sets width or height of container if returned 1737 * @returns {Object} size 1738 * @param {Number} width 1739 * @param {Number} height 1740 */ 1741 proto._getContainerSize = noop; 1742 1743 /** 1744 * @param {Number} measure - size of width or height 1745 * @param {Boolean} isWidth 1746 */ 1747 proto._setContainerMeasure = function( measure, isWidth ) { 1748 if ( measure === undefined ) { 1749 return; 1750 } 1751 1752 var elemSize = this.size; 1753 // add padding and border width if border box 1754 if ( elemSize.isBorderBox ) { 1755 measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight + 1756 elemSize.borderLeftWidth + elemSize.borderRightWidth : 1757 elemSize.paddingBottom + elemSize.paddingTop + 1758 elemSize.borderTopWidth + elemSize.borderBottomWidth; 1759 } 1760 1761 measure = Math.max( measure, 0 ); 1762 this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px'; 1763 }; 1764 1765 /** 1766 * emit eventComplete on a collection of items events 1767 * @param {String} eventName 1768 * @param {Array} items - Outlayer.Items 1769 */ 1770 proto._emitCompleteOnItems = function( eventName, items ) { 1771 var _this = this; 1772 function onComplete() { 1773 _this.dispatchEvent( eventName + 'Complete', null, [ items ] ); 1774 } 1775 1776 var count = items.length; 1777 if ( !items || !count ) { 1778 onComplete(); 1779 return; 1780 } 1781 1782 var doneCount = 0; 1783 function tick() { 1784 doneCount++; 1785 if ( doneCount == count ) { 1786 onComplete(); 1787 } 1788 } 1789 1790 // bind callback 1791 items.forEach( function( item ) { 1792 item.once( eventName, tick ); 1793 }); 1794 }; 1795 1796 /** 1797 * emits events via EvEmitter and jQuery events 1798 * @param {String} type - name of event 1799 * @param {Event} event - original event 1800 * @param {Array} args - extra arguments 1801 */ 1802 proto.dispatchEvent = function( type, event, args ) { 1803 // add original event to arguments 1804 var emitArgs = event ? [ event ].concat( args ) : args; 1805 this.emitEvent( type, emitArgs ); 1806 1807 if ( jQuery ) { 1808 // set this.$element 1809 this.$element = this.$element || jQuery( this.element ); 1810 if ( event ) { 1811 // create jQuery event 1812 var $event = jQuery.Event( event ); 1813 $event.type = type; 1814 this.$element.trigger( $event, args ); 1815 } else { 1816 // just trigger with type if no event available 1817 this.$element.trigger( type, args ); 1818 } 1819 } 1820 }; 1821 1822// -------------------------- ignore & stamps -------------------------- // 1823 1824 1825 /** 1826 * keep item in collection, but do not lay it out 1827 * ignored items do not get skipped in layout 1828 * @param {Element} elem 1829 */ 1830 proto.ignore = function( elem ) { 1831 var item = this.getItem( elem ); 1832 if ( item ) { 1833 item.isIgnored = true; 1834 } 1835 }; 1836 1837 /** 1838 * return item to layout collection 1839 * @param {Element} elem 1840 */ 1841 proto.unignore = function( elem ) { 1842 var item = this.getItem( elem ); 1843 if ( item ) { 1844 delete item.isIgnored; 1845 } 1846 }; 1847 1848 /** 1849 * adds elements to stamps 1850 * @param {NodeList, Array, Element, or String} elems 1851 */ 1852 proto.stamp = function( elems ) { 1853 elems = this._find( elems ); 1854 if ( !elems ) { 1855 return; 1856 } 1857 1858 this.stamps = this.stamps.concat( elems ); 1859 // ignore 1860 elems.forEach( this.ignore, this ); 1861 }; 1862 1863 /** 1864 * removes elements to stamps 1865 * @param {NodeList, Array, or Element} elems 1866 */ 1867 proto.unstamp = function( elems ) { 1868 elems = this._find( elems ); 1869 if ( !elems ){ 1870 return; 1871 } 1872 1873 elems.forEach( function( elem ) { 1874 // filter out removed stamp elements 1875 utils.removeFrom( this.stamps, elem ); 1876 this.unignore( elem ); 1877 }, this ); 1878 }; 1879 1880 /** 1881 * finds child elements 1882 * @param {NodeList, Array, Element, or String} elems 1883 * @returns {Array} elems 1884 */ 1885 proto._find = function( elems ) { 1886 if ( !elems ) { 1887 return; 1888 } 1889 // if string, use argument as selector string 1890 if ( typeof elems == 'string' ) { 1891 elems = this.element.querySelectorAll( elems ); 1892 } 1893 elems = utils.makeArray( elems ); 1894 return elems; 1895 }; 1896 1897 proto._manageStamps = function() { 1898 if ( !this.stamps || !this.stamps.length ) { 1899 return; 1900 } 1901 1902 this._getBoundingRect(); 1903 1904 this.stamps.forEach( this._manageStamp, this ); 1905 }; 1906 1907// update boundingLeft / Top 1908 proto._getBoundingRect = function() { 1909 // get bounding rect for container element 1910 var boundingRect = this.element.getBoundingClientRect(); 1911 var size = this.size; 1912 this._boundingRect = { 1913 left: boundingRect.left + size.paddingLeft + size.borderLeftWidth, 1914 top: boundingRect.top + size.paddingTop + size.borderTopWidth, 1915 right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ), 1916 bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth ) 1917 }; 1918 }; 1919 1920 /** 1921 * @param {Element} stamp 1922 **/ 1923 proto._manageStamp = noop; 1924 1925 /** 1926 * get x/y position of element relative to container element 1927 * @param {Element} elem 1928 * @returns {Object} offset - has left, top, right, bottom 1929 */ 1930 proto._getElementOffset = function( elem ) { 1931 var boundingRect = elem.getBoundingClientRect(); 1932 var thisRect = this._boundingRect; 1933 var size = getSize( elem ); 1934 var offset = { 1935 left: boundingRect.left - thisRect.left - size.marginLeft, 1936 top: boundingRect.top - thisRect.top - size.marginTop, 1937 right: thisRect.right - boundingRect.right - size.marginRight, 1938 bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom 1939 }; 1940 return offset; 1941 }; 1942 1943// -------------------------- resize -------------------------- // 1944 1945// enable event handlers for listeners 1946// i.e. resize -> onresize 1947 proto.handleEvent = utils.handleEvent; 1948 1949 /** 1950 * Bind layout to window resizing 1951 */ 1952 proto.bindResize = function() { 1953 window.addEventListener( 'resize', this ); 1954 this.isResizeBound = true; 1955 }; 1956 1957 /** 1958 * Unbind layout to window resizing 1959 */ 1960 proto.unbindResize = function() { 1961 window.removeEventListener( 'resize', this ); 1962 this.isResizeBound = false; 1963 }; 1964 1965 proto.onresize = function() { 1966 this.resize(); 1967 }; 1968 1969 utils.debounceMethod( Outlayer, 'onresize', 100 ); 1970 1971 proto.resize = function() { 1972 // don't trigger if size did not change 1973 // or if resize was unbound. See #9 1974 if ( !this.isResizeBound || !this.needsResizeLayout() ) { 1975 return; 1976 } 1977 1978 this.layout(); 1979 }; 1980 1981 /** 1982 * check if layout is needed post layout 1983 * @returns Boolean 1984 */ 1985 proto.needsResizeLayout = function() { 1986 var size = getSize( this.element ); 1987 // check that this.size and size are there 1988 // IE8 triggers resize on body size change, so they might not be 1989 var hasSizes = this.size && size; 1990 return hasSizes && size.innerWidth !== this.size.innerWidth; 1991 }; 1992 1993// -------------------------- methods -------------------------- // 1994 1995 /** 1996 * add items to Outlayer instance 1997 * @param {Array or NodeList or Element} elems 1998 * @returns {Array} items - Outlayer.Items 1999 **/ 2000 proto.addItems = function( elems ) { 2001 var items = this._itemize( elems ); 2002 // add items to collection 2003 if ( items.length ) { 2004 this.items = this.items.concat( items ); 2005 } 2006 return items; 2007 }; 2008 2009 /** 2010 * Layout newly-appended item elements 2011 * @param {Array or NodeList or Element} elems 2012 */ 2013 proto.appended = function( elems ) { 2014 var items = this.addItems( elems ); 2015 if ( !items.length ) { 2016 return; 2017 } 2018 // layout and reveal just the new items 2019 this.layoutItems( items, true ); 2020 this.reveal( items ); 2021 }; 2022 2023 /** 2024 * Layout prepended elements 2025 * @param {Array or NodeList or Element} elems 2026 */ 2027 proto.prepended = function( elems ) { 2028 var items = this._itemize( elems ); 2029 if ( !items.length ) { 2030 return; 2031 } 2032 // add items to beginning of collection 2033 var previousItems = this.items.slice(0); 2034 this.items = items.concat( previousItems ); 2035 // start new layout 2036 this._resetLayout(); 2037 this._manageStamps(); 2038 // layout new stuff without transition 2039 this.layoutItems( items, true ); 2040 this.reveal( items ); 2041 // layout previous items 2042 this.layoutItems( previousItems ); 2043 }; 2044 2045 /** 2046 * reveal a collection of items 2047 * @param {Array of Outlayer.Items} items 2048 */ 2049 proto.reveal = function( items ) { 2050 this._emitCompleteOnItems( 'reveal', items ); 2051 if ( !items || !items.length ) { 2052 return; 2053 } 2054 var stagger = this.updateStagger(); 2055 items.forEach( function( item, i ) { 2056 item.stagger( i * stagger ); 2057 item.reveal(); 2058 }); 2059 }; 2060 2061 /** 2062 * hide a collection of items 2063 * @param {Array of Outlayer.Items} items 2064 */ 2065 proto.hide = function( items ) { 2066 this._emitCompleteOnItems( 'hide', items ); 2067 if ( !items || !items.length ) { 2068 return; 2069 } 2070 var stagger = this.updateStagger(); 2071 items.forEach( function( item, i ) { 2072 item.stagger( i * stagger ); 2073 item.hide(); 2074 }); 2075 }; 2076 2077 /** 2078 * reveal item elements 2079 * @param {Array}, {Element}, {NodeList} items 2080 */ 2081 proto.revealItemElements = function( elems ) { 2082 var items = this.getItems( elems ); 2083 this.reveal( items ); 2084 }; 2085 2086 /** 2087 * hide item elements 2088 * @param {Array}, {Element}, {NodeList} items 2089 */ 2090 proto.hideItemElements = function( elems ) { 2091 var items = this.getItems( elems ); 2092 this.hide( items ); 2093 }; 2094 2095 /** 2096 * get Outlayer.Item, given an Element 2097 * @param {Element} elem 2098 * @param {Function} callback 2099 * @returns {Outlayer.Item} item 2100 */ 2101 proto.getItem = function( elem ) { 2102 // loop through items to get the one that matches 2103 for ( var i=0; i < this.items.length; i++ ) { 2104 var item = this.items[i]; 2105 if ( item.element == elem ) { 2106 // return item 2107 return item; 2108 } 2109 } 2110 }; 2111 2112 /** 2113 * get collection of Outlayer.Items, given Elements 2114 * @param {Array} elems 2115 * @returns {Array} items - Outlayer.Items 2116 */ 2117 proto.getItems = function( elems ) { 2118 elems = utils.makeArray( elems ); 2119 var items = [];
vendor: 30,065 bytes, lines 2120-3147
2120 elems.forEach( function( elem ) { 2121 var item = this.getItem( elem ); 2122 if ( item ) { 2123 items.push( item ); 2124 } 2125 }, this ); 2126 2127 return items; 2128 }; 2129 2130 /** 2131 * remove element(s) from instance and DOM 2132 * @param {Array or NodeList or Element} elems 2133 */ 2134 proto.remove = function( elems ) { 2135 var removeItems = this.getItems( elems ); 2136 2137 this._emitCompleteOnItems( 'remove', removeItems ); 2138 2139 // bail if no items to remove 2140 if ( !removeItems || !removeItems.length ) { 2141 return; 2142 } 2143 2144 removeItems.forEach( function( item ) { 2145 item.remove(); 2146 // remove item from collection 2147 utils.removeFrom( this.items, item ); 2148 }, this ); 2149 }; 2150 2151// ----- destroy ----- // 2152 2153// remove and disable Outlayer instance 2154 proto.destroy = function() { 2155 // clean up dynamic styles 2156 var style = this.element.style; 2157 style.height = ''; 2158 style.position = ''; 2159 style.width = ''; 2160 // destroy items 2161 this.items.forEach( function( item ) { 2162 item.destroy(); 2163 }); 2164 2165 this.unbindResize(); 2166 2167 var id = this.element.outlayerGUID; 2168 delete instances[ id ]; // remove reference to instance by id 2169 delete this.element.outlayerGUID; 2170 // remove data for jQuery 2171 if ( jQuery ) { 2172 jQuery.removeData( this.element, this.constructor.namespace ); 2173 } 2174 2175 }; 2176 2177// -------------------------- data -------------------------- // 2178 2179 /** 2180 * get Outlayer instance from element 2181 * @param {Element} elem 2182 * @returns {Outlayer} 2183 */ 2184 Outlayer.data = function( elem ) { 2185 elem = utils.getQueryElement( elem ); 2186 var id = elem && elem.outlayerGUID; 2187 return id && instances[ id ]; 2188 }; 2189 2190 2191// -------------------------- create Outlayer class -------------------------- // 2192 2193 /** 2194 * create a layout class 2195 * @param {String} namespace 2196 */ 2197 Outlayer.create = function( namespace, options ) { 2198 // sub-class Outlayer 2199 var Layout = subclass( Outlayer ); 2200 // apply new options and compatOptions 2201 Layout.defaults = utils.extend( {}, Outlayer.defaults ); 2202 utils.extend( Layout.defaults, options ); 2203 Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions ); 2204 2205 Layout.namespace = namespace; 2206 2207 Layout.data = Outlayer.data; 2208 2209 // sub-class Item 2210 Layout.Item = subclass( Item ); 2211 2212 // -------------------------- declarative -------------------------- // 2213 2214 utils.htmlInit( Layout, namespace ); 2215 2216 // -------------------------- jQuery bridge -------------------------- // 2217 2218 // make into jQuery plugin 2219 if ( jQuery && jQuery.bridget ) { 2220 jQuery.bridget( namespace, Layout ); 2221 } 2222 2223 return Layout; 2224 }; 2225 2226 function subclass( Parent ) { 2227 function SubClass() { 2228 Parent.apply( this, arguments ); 2229 } 2230 2231 SubClass.prototype = Object.create( Parent.prototype ); 2232 SubClass.prototype.constructor = SubClass; 2233 2234 return SubClass; 2235 } 2236 2237// ----- helpers ----- // 2238 2239// how many milliseconds are in each unit 2240 var msUnits = { 2241 ms: 1, 2242 s: 1000 2243 }; 2244 2245// munge time-like parameter into millisecond number 2246// '0.4s' -> 40 2247 function getMilliseconds( time ) { 2248 if ( typeof time == 'number' ) { 2249 return time; 2250 } 2251 var matches = time.match( /(^\d*\.?\d*)(\w*)/ ); 2252 var num = matches && matches[1]; 2253 var unit = matches && matches[2]; 2254 if ( !num.length ) { 2255 return 0; 2256 } 2257 num = parseFloat( num ); 2258 var mult = msUnits[ unit ] || 1; 2259 return num * mult; 2260 } 2261 2262// ----- fin ----- // 2263 2264// back in global 2265 Outlayer.Item = Item; 2266 2267 return Outlayer; 2268 2269})); 2270 2271/** 2272 * Isotope Item 2273 **/ 2274 2275( function( window, factory ) { 2276 // universal module definition 2277 /* jshint strict: false */ /*globals define, module, require */ 2278 if ( typeof define == 'function' && define.amd ) { 2279 // AMD 2280 define( 'isotope/js/item',[ 2281 'outlayer/outlayer' 2282 ], 2283 factory ); 2284 } else if ( typeof module == 'object' && module.exports ) { 2285 // CommonJS 2286 module.exports = factory( 2287 require('outlayer') 2288 ); 2289 } else { 2290 // browser global 2291 window.Isotope = window.Isotope || {}; 2292 window.Isotope.Item = factory( 2293 window.Outlayer 2294 ); 2295 } 2296 2297}( window, function factory( Outlayer ) { 2298 'use strict'; 2299 2300// -------------------------- Item -------------------------- // 2301 2302// sub-class Outlayer Item 2303 function Item() { 2304 Outlayer.Item.apply( this, arguments ); 2305 } 2306 2307 var proto = Item.prototype = Object.create( Outlayer.Item.prototype ); 2308 2309 var _create = proto._create; 2310 proto._create = function() { 2311 // assign id, used for original-order sorting 2312 this.id = this.layout.itemGUID++; 2313 _create.call( this ); 2314 this.sortData = {}; 2315 }; 2316 2317 proto.updateSortData = function() { 2318 if ( this.isIgnored ) { 2319 return; 2320 } 2321 // default sorters 2322 this.sortData.id = this.id; 2323 // for backward compatibility 2324 this.sortData['original-order'] = this.id; 2325 this.sortData.random = Math.random(); 2326 // go thru getSortData obj and apply the sorters 2327 var getSortData = this.layout.options.getSortData; 2328 var sorters = this.layout._sorters; 2329 for ( var key in getSortData ) { 2330 var sorter = sorters[ key ]; 2331 this.sortData[ key ] = sorter( this.element, this ); 2332 } 2333 }; 2334 2335 var _destroy = proto.destroy; 2336 proto.destroy = function() { 2337 // call super 2338 _destroy.apply( this, arguments ); 2339 // reset display, #741 2340 this.css({ 2341 display: '' 2342 }); 2343 }; 2344 2345 return Item; 2346 2347})); 2348 2349/** 2350 * Isotope LayoutMode 2351 */ 2352 2353( function( window, factory ) { 2354 // universal module definition 2355 /* jshint strict: false */ /*globals define, module, require */ 2356 if ( typeof define == 'function' && define.amd ) { 2357 // AMD 2358 define( 'isotope/js/layout-mode',[ 2359 'get-size/get-size', 2360 'outlayer/outlayer' 2361 ], 2362 factory ); 2363 } else if ( typeof module == 'object' && module.exports ) { 2364 // CommonJS 2365 module.exports = factory( 2366 require('get-size'), 2367 require('outlayer') 2368 ); 2369 } else { 2370 // browser global 2371 window.Isotope = window.Isotope || {}; 2372 window.Isotope.LayoutMode = factory( 2373 window.getSize, 2374 window.Outlayer 2375 ); 2376 } 2377 2378}( window, function factory( getSize, Outlayer ) { 2379 'use strict'; 2380 2381 // layout mode class 2382 function LayoutMode( isotope ) { 2383 this.isotope = isotope; 2384 // link properties 2385 if ( isotope ) { 2386 this.options = isotope.options[ this.namespace ]; 2387 this.element = isotope.element; 2388 this.items = isotope.filteredItems; 2389 this.size = isotope.size; 2390 } 2391 } 2392 2393 var proto = LayoutMode.prototype; 2394 2395 /** 2396 * some methods should just defer to default Outlayer method 2397 * and reference the Isotope instance as `this` 2398 **/ 2399 var facadeMethods = [ 2400 '_resetLayout', 2401 '_getItemLayoutPosition', 2402 '_manageStamp', 2403 '_getContainerSize', 2404 '_getElementOffset', 2405 'needsResizeLayout', 2406 '_getOption' 2407 ]; 2408 2409 facadeMethods.forEach( function( methodName ) { 2410 proto[ methodName ] = function() { 2411 return Outlayer.prototype[ methodName ].apply( this.isotope, arguments ); 2412 }; 2413 }); 2414 2415 // ----- ----- // 2416 2417 // for horizontal layout modes, check vertical size 2418 proto.needsVerticalResizeLayout = function() { 2419 // don't trigger if size did not change 2420 var size = getSize( this.isotope.element ); 2421 // check that this.size and size are there 2422 // IE8 triggers resize on body size change, so they might not be 2423 var hasSizes = this.isotope.size && size; 2424 return hasSizes && size.innerHeight != this.isotope.size.innerHeight; 2425 }; 2426 2427 // ----- measurements ----- // 2428 2429 proto._getMeasurement = function() { 2430 this.isotope._getMeasurement.apply( this, arguments ); 2431 }; 2432 2433 proto.getColumnWidth = function() { 2434 this.getSegmentSize( 'column', 'Width' ); 2435 }; 2436 2437 proto.getRowHeight = function() { 2438 this.getSegmentSize( 'row', 'Height' ); 2439 }; 2440 2441 /** 2442 * get columnWidth or rowHeight 2443 * segment: 'column' or 'row' 2444 * size 'Width' or 'Height' 2445 **/ 2446 proto.getSegmentSize = function( segment, size ) { 2447 var segmentName = segment + size; 2448 var outerSize = 'outer' + size; 2449 // columnWidth / outerWidth // rowHeight / outerHeight 2450 this._getMeasurement( segmentName, outerSize ); 2451 // got rowHeight or columnWidth, we can chill 2452 if ( this[ segmentName ] ) { 2453 return; 2454 } 2455 // fall back to item of first element 2456 var firstItemSize = this.getFirstItemSize(); 2457 this[ segmentName ] = firstItemSize && firstItemSize[ outerSize ] || 2458 // or size of container 2459 this.isotope.size[ 'inner' + size ]; 2460 }; 2461 2462 proto.getFirstItemSize = function() { 2463 var firstItem = this.isotope.filteredItems[0]; 2464 return firstItem && firstItem.element && getSize( firstItem.element ); 2465 }; 2466 2467 // ----- methods that should reference isotope ----- // 2468 2469 proto.layout = function() { 2470 this.isotope.layout.apply( this.isotope, arguments ); 2471 }; 2472 2473 proto.getSize = function() { 2474 this.isotope.getSize(); 2475 this.size = this.isotope.size; 2476 }; 2477 2478 // -------------------------- create -------------------------- // 2479 2480 LayoutMode.modes = {}; 2481 2482 LayoutMode.create = function( namespace, options ) { 2483 2484 function Mode() { 2485 LayoutMode.apply( this, arguments ); 2486 } 2487 2488 Mode.prototype = Object.create( proto ); 2489 Mode.prototype.constructor = Mode; 2490 2491 // default options 2492 if ( options ) { 2493 Mode.options = options; 2494 } 2495 2496 Mode.prototype.namespace = namespace; 2497 // register in Isotope 2498 LayoutMode.modes[ namespace ] = Mode; 2499 2500 return Mode; 2501 }; 2502 2503 return LayoutMode; 2504 2505})); 2506 2507/*! 2508 * Masonry v4.1.1 2509 * Cascading grid layout library 2510 * http://masonry.desandro.com 2511 * MIT License 2512 * by David DeSandro 2513 */ 2514 2515( function( window, factory ) { 2516 // universal module definition 2517 /* jshint strict: false */ /*globals define, module, require */ 2518 if ( typeof define == 'function' && define.amd ) { 2519 // AMD 2520 define( 'masonry/masonry',[ 2521 'outlayer/outlayer', 2522 'get-size/get-size' 2523 ], 2524 factory ); 2525 } else if ( typeof module == 'object' && module.exports ) { 2526 // CommonJS 2527 module.exports = factory( 2528 require('outlayer'), 2529 require('get-size') 2530 ); 2531 } else { 2532 // browser global 2533 window.Masonry = factory( 2534 window.Outlayer, 2535 window.getSize 2536 ); 2537 } 2538 2539}( window, function factory( Outlayer, getSize ) { 2540 2541 2542 2543// -------------------------- masonryDefinition -------------------------- // 2544 2545 // create an Outlayer layout class 2546 var Masonry = Outlayer.create('masonry'); 2547 // isFitWidth -> fitWidth 2548 Masonry.compatOptions.fitWidth = 'isFitWidth'; 2549 2550 Masonry.prototype._resetLayout = function() { 2551 this.getSize(); 2552 this._getMeasurement( 'columnWidth', 'outerWidth' ); 2553 this._getMeasurement( 'gutter', 'outerWidth' ); 2554 this.measureColumns(); 2555 2556 // reset column Y 2557 this.colYs = []; 2558 for ( var i=0; i < this.cols; i++ ) { 2559 this.colYs.push( 0 ); 2560 } 2561 2562 this.maxY = 0; 2563 }; 2564 2565 Masonry.prototype.measureColumns = function() { 2566 this.getContainerWidth(); 2567 // if columnWidth is 0, default to outerWidth of first item 2568 if ( !this.columnWidth ) { 2569 var firstItem = this.items[0]; 2570 var firstItemElem = firstItem && firstItem.element; 2571 // columnWidth fall back to item of first element 2572 this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth || 2573 // if first elem has no width, default to size of container 2574 this.containerWidth; 2575 } 2576 2577 var columnWidth = this.columnWidth += this.gutter; 2578 2579 // calculate columns 2580 var containerWidth = this.containerWidth + this.gutter; 2581 var cols = containerWidth / columnWidth; 2582 // fix rounding errors, typically with gutters 2583 var excess = columnWidth - containerWidth % columnWidth; 2584 // if overshoot is less than a pixel, round up, otherwise floor it 2585 var mathMethod = excess && excess < 1 ? 'round' : 'floor'; 2586 cols = Math[ mathMethod ]( cols ); 2587 this.cols = Math.max( cols, 1 ); 2588 }; 2589 2590 Masonry.prototype.getContainerWidth = function() { 2591 // container is parent if fit width 2592 var isFitWidth = this._getOption('fitWidth'); 2593 var container = isFitWidth ? this.element.parentNode : this.element; 2594 // check that this.size and size are there 2595 // IE8 triggers resize on body size change, so they might not be 2596 var size = getSize( container ); 2597 this.containerWidth = size && size.innerWidth; 2598 }; 2599 2600 Masonry.prototype._getItemLayoutPosition = function( item ) { 2601 item.getSize(); 2602 // how many columns does this brick span 2603 var remainder = item.size.outerWidth % this.columnWidth; 2604 var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; 2605 // round if off by 1 pixel, otherwise use ceil 2606 var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth ); 2607 colSpan = Math.min( colSpan, this.cols ); 2608 2609 var colGroup = this._getColGroup( colSpan ); 2610 // get the minimum Y value from the columns 2611 var minimumY = Math.min.apply( Math, colGroup ); 2612 var shortColIndex = colGroup.indexOf( minimumY ); 2613 2614 // position the brick 2615 var position = { 2616 x: this.columnWidth * shortColIndex, 2617 y: minimumY 2618 }; 2619 2620 // apply setHeight to necessary columns 2621 var setHeight = minimumY + item.size.outerHeight; 2622 var setSpan = this.cols + 1 - colGroup.length; 2623 for ( var i = 0; i < setSpan; i++ ) { 2624 this.colYs[ shortColIndex + i ] = setHeight; 2625 } 2626 2627 return position; 2628 }; 2629 2630 /** 2631 * @param {Number} colSpan - number of columns the element spans 2632 * @returns {Array} colGroup 2633 */ 2634 Masonry.prototype._getColGroup = function( colSpan ) { 2635 if ( colSpan < 2 ) { 2636 // if brick spans only one column, use all the column Ys 2637 return this.colYs; 2638 } 2639 2640 var colGroup = []; 2641 // how many different places could this brick fit horizontally 2642 var groupCount = this.cols + 1 - colSpan; 2643 // for each group potential horizontal position 2644 for ( var i = 0; i < groupCount; i++ ) { 2645 // make an array of colY values for that one group 2646 var groupColYs = this.colYs.slice( i, i + colSpan ); 2647 // and get the max value of the array 2648 colGroup[i] = Math.max.apply( Math, groupColYs ); 2649 } 2650 return colGroup; 2651 }; 2652 2653 Masonry.prototype._manageStamp = function( stamp ) { 2654 var stampSize = getSize( stamp ); 2655 var offset = this._getElementOffset( stamp ); 2656 // get the columns that this stamp affects 2657 var isOriginLeft = this._getOption('originLeft'); 2658 var firstX = isOriginLeft ? offset.left : offset.right; 2659 var lastX = firstX + stampSize.outerWidth; 2660 var firstCol = Math.floor( firstX / this.columnWidth ); 2661 firstCol = Math.max( 0, firstCol ); 2662 var lastCol = Math.floor( lastX / this.columnWidth ); 2663 // lastCol should not go over if multiple of columnWidth #425 2664 lastCol -= lastX % this.columnWidth ? 0 : 1; 2665 lastCol = Math.min( this.cols - 1, lastCol ); 2666 // set colYs to bottom of the stamp 2667 2668 var isOriginTop = this._getOption('originTop'); 2669 var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) + 2670 stampSize.outerHeight; 2671 for ( var i = firstCol; i <= lastCol; i++ ) { 2672 this.colYs[i] = Math.max( stampMaxY, this.colYs[i] ); 2673 } 2674 }; 2675 2676 Masonry.prototype._getContainerSize = function() { 2677 this.maxY = Math.max.apply( Math, this.colYs ); 2678 var size = { 2679 height: this.maxY 2680 }; 2681 2682 if ( this._getOption('fitWidth') ) { 2683 size.width = this._getContainerFitWidth(); 2684 } 2685 2686 return size; 2687 }; 2688 2689 Masonry.prototype._getContainerFitWidth = function() { 2690 var unusedCols = 0; 2691 // count unused columns 2692 var i = this.cols; 2693 while ( --i ) { 2694 if ( this.colYs[i] !== 0 ) { 2695 break; 2696 } 2697 unusedCols++; 2698 } 2699 // fit container to columns that have been used 2700 return ( this.cols - unusedCols ) * this.columnWidth - this.gutter; 2701 }; 2702 2703 Masonry.prototype.needsResizeLayout = function() { 2704 var previousWidth = this.containerWidth; 2705 this.getContainerWidth(); 2706 return previousWidth != this.containerWidth; 2707 }; 2708 2709 return Masonry; 2710 2711})); 2712 2713/*! 2714 * Masonry layout mode 2715 * sub-classes Masonry 2716 * http://masonry.desandro.com 2717 */ 2718 2719( function( window, factory ) { 2720 // universal module definition 2721 /* jshint strict: false */ /*globals define, module, require */ 2722 if ( typeof define == 'function' && define.amd ) { 2723 // AMD 2724 define( 'isotope/js/layout-modes/masonry',[ 2725 '../layout-mode', 2726 'masonry/masonry' 2727 ], 2728 factory ); 2729 } else if ( typeof module == 'object' && module.exports ) { 2730 // CommonJS 2731 module.exports = factory( 2732 require('../layout-mode'), 2733 require('masonry-layout') 2734 ); 2735 } else { 2736 // browser global 2737 factory( 2738 window.Isotope.LayoutMode, 2739 window.Masonry 2740 ); 2741 } 2742 2743}( window, function factory( LayoutMode, Masonry ) { 2744 'use strict'; 2745 2746// -------------------------- masonryDefinition -------------------------- // 2747 2748 // create an Outlayer layout class 2749 var MasonryMode = LayoutMode.create('masonry'); 2750 2751 var proto = MasonryMode.prototype; 2752 2753 var keepModeMethods = { 2754 _getElementOffset: true, 2755 layout: true, 2756 _getMeasurement: true 2757 }; 2758 2759 // inherit Masonry prototype 2760 for ( var method in Masonry.prototype ) { 2761 // do not inherit mode methods 2762 if ( !keepModeMethods[ method ] ) { 2763 proto[ method ] = Masonry.prototype[ method ]; 2764 } 2765 } 2766 2767 var measureColumns = proto.measureColumns; 2768 proto.measureColumns = function() { 2769 // set items, used if measuring first item 2770 this.items = this.isotope.filteredItems; 2771 measureColumns.call( this ); 2772 }; 2773 2774 // point to mode options for fitWidth 2775 var _getOption = proto._getOption; 2776 proto._getOption = function( option ) { 2777 if ( option == 'fitWidth' ) { 2778 return this.options.isFitWidth !== undefined ? 2779 this.options.isFitWidth : this.options.fitWidth; 2780 } 2781 return _getOption.apply( this.isotope, arguments ); 2782 }; 2783 2784 return MasonryMode; 2785 2786})); 2787 2788/** 2789 * fitRows layout mode 2790 */ 2791 2792( function( window, factory ) { 2793 // universal module definition 2794 /* jshint strict: false */ /*globals define, module, require */ 2795 if ( typeof define == 'function' && define.amd ) { 2796 // AMD 2797 define( 'isotope/js/layout-modes/fit-rows',[ 2798 '../layout-mode' 2799 ], 2800 factory ); 2801 } else if ( typeof exports == 'object' ) { 2802 // CommonJS 2803 module.exports = factory( 2804 require('../layout-mode') 2805 ); 2806 } else { 2807 // browser global 2808 factory( 2809 window.Isotope.LayoutMode 2810 ); 2811 } 2812 2813}( window, function factory( LayoutMode ) { 2814 'use strict'; 2815 2816 var FitRows = LayoutMode.create('fitRows'); 2817 2818 var proto = FitRows.prototype; 2819 2820 proto._resetLayout = function() { 2821 this.x = 0; 2822 this.y = 0; 2823 this.maxY = 0; 2824 this._getMeasurement( 'gutter', 'outerWidth' ); 2825 }; 2826 2827 proto._getItemLayoutPosition = function( item ) { 2828 item.getSize(); 2829 2830 var itemWidth = item.size.outerWidth + this.gutter; 2831 // if this element cannot fit in the current row 2832 var containerWidth = this.isotope.size.innerWidth + this.gutter; 2833 if ( this.x !== 0 && itemWidth + this.x > containerWidth ) { 2834 this.x = 0; 2835 this.y = this.maxY; 2836 } 2837 2838 var position = { 2839 x: this.x, 2840 y: this.y 2841 }; 2842 2843 this.maxY = Math.max( this.maxY, this.y + item.size.outerHeight ); 2844 this.x += itemWidth; 2845 2846 return position; 2847 }; 2848 2849 proto._getContainerSize = function() { 2850 return { height: this.maxY }; 2851 }; 2852 2853 return FitRows; 2854 2855})); 2856 2857/** 2858 * vertical layout mode 2859 */ 2860 2861( function( window, factory ) { 2862 // universal module definition 2863 /* jshint strict: false */ /*globals define, module, require */ 2864 if ( typeof define == 'function' && define.amd ) { 2865 // AMD 2866 define( 'isotope/js/layout-modes/vertical',[ 2867 '../layout-mode' 2868 ], 2869 factory ); 2870 } else if ( typeof module == 'object' && module.exports ) { 2871 // CommonJS 2872 module.exports = factory( 2873 require('../layout-mode') 2874 ); 2875 } else { 2876 // browser global 2877 factory( 2878 window.Isotope.LayoutMode 2879 ); 2880 } 2881 2882}( window, function factory( LayoutMode ) { 2883 'use strict'; 2884 2885 var Vertical = LayoutMode.create( 'vertical', { 2886 horizontalAlignment: 0 2887 }); 2888 2889 var proto = Vertical.prototype; 2890 2891 proto._resetLayout = function() { 2892 this.y = 0; 2893 }; 2894 2895 proto._getItemLayoutPosition = function( item ) { 2896 item.getSize(); 2897 var x = ( this.isotope.size.innerWidth - item.size.outerWidth ) * 2898 this.options.horizontalAlignment; 2899 var y = this.y; 2900 this.y += item.size.outerHeight; 2901 return { x: x, y: y }; 2902 }; 2903 2904 proto._getContainerSize = function() { 2905 return { height: this.y }; 2906 }; 2907 2908 return Vertical; 2909 2910})); 2911 2912/*! 2913 * Isotope v3.0.3 2914 * 2915 * Licensed GPLv3 for open source use 2916 * or Isotope Commercial License for commercial use 2917 * 2918 * http://isotope.metafizzy.co 2919 * Copyright 2017 Metafizzy 2920 */ 2921 2922( function( window, factory ) { 2923 // universal module definition 2924 /* jshint strict: false */ /*globals define, module, require */ 2925 if ( typeof define == 'function' && define.amd ) { 2926 // AMD 2927 define( [ 2928 'outlayer/outlayer', 2929 'get-size/get-size', 2930 'desandro-matches-selector/matches-selector', 2931 'fizzy-ui-utils/utils', 2932 'isotope/js/item', 2933 'isotope/js/layout-mode', 2934 // include default layout modes 2935 'isotope/js/layout-modes/masonry', 2936 'isotope/js/layout-modes/fit-rows', 2937 'isotope/js/layout-modes/vertical' 2938 ], 2939 function( Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ) { 2940 return factory( window, Outlayer, getSize, matchesSelector, utils, Item, LayoutMode ); 2941 }); 2942 } else if ( typeof module == 'object' && module.exports ) { 2943 // CommonJS 2944 module.exports = factory( 2945 window, 2946 require('outlayer'), 2947 require('get-size'), 2948 require('desandro-matches-selector'), 2949 require('fizzy-ui-utils'), 2950 require('isotope/js/item'), 2951 require('isotope/js/layout-mode'), 2952 // include default layout modes 2953 require('isotope/js/layout-modes/masonry'), 2954 require('isotope/js/layout-modes/fit-rows'), 2955 require('isotope/js/layout-modes/vertical') 2956 ); 2957 } else { 2958 // browser global 2959 window.Isotope = factory( 2960 window, 2961 window.Outlayer, 2962 window.getSize, 2963 window.matchesSelector, 2964 window.fizzyUIUtils, 2965 window.Isotope.Item, 2966 window.Isotope.LayoutMode 2967 ); 2968 } 2969 2970}( window, function factory( window, Outlayer, getSize, matchesSelector, utils, 2971 Item, LayoutMode ) { 2972 2973 2974 2975// -------------------------- vars -------------------------- // 2976 2977 var jQuery = window.jQuery; 2978 2979// -------------------------- helpers -------------------------- // 2980 2981 var trim = String.prototype.trim ? 2982 function( str ) { 2983 return str.trim(); 2984 } : 2985 function( str ) { 2986 return str.replace( /^\s+|\s+$/g, '' ); 2987 }; 2988 2989// -------------------------- isotopeDefinition -------------------------- // 2990 2991 // create an Outlayer layout class 2992 var Isotope = Outlayer.create( 'isotope', { 2993 layoutMode: 'masonry', 2994 isJQueryFiltering: true, 2995 sortAscending: true 2996 }); 2997 2998 Isotope.Item = Item; 2999 Isotope.LayoutMode = LayoutMode; 3000 3001 var proto = Isotope.prototype; 3002 3003 proto._create = function() { 3004 this.itemGUID = 0; 3005 // functions that sort items 3006 this._sorters = {}; 3007 this._getSorters(); 3008 // call super 3009 Outlayer.prototype._create.call( this ); 3010 3011 // create layout modes 3012 this.modes = {}; 3013 // start filteredItems with all items 3014 this.filteredItems = this.items; 3015 // keep of track of sortBys 3016 this.sortHistory = [ 'original-order' ]; 3017 // create from registered layout modes 3018 for ( var name in LayoutMode.modes ) { 3019 this._initLayoutMode( name ); 3020 } 3021 }; 3022 3023 proto.reloadItems = function() { 3024 // reset item ID counter 3025 this.itemGUID = 0; 3026 // call super 3027 Outlayer.prototype.reloadItems.call( this ); 3028 }; 3029 3030 proto._itemize = function() { 3031 var items = Outlayer.prototype._itemize.apply( this, arguments ); 3032 // assign ID for original-order 3033 for ( var i=0; i < items.length; i++ ) { 3034 var item = items[i]; 3035 item.id = this.itemGUID++; 3036 } 3037 this._updateItemsSortData( items ); 3038 return items; 3039 }; 3040 3041 3042 // -------------------------- layout -------------------------- // 3043 3044 proto._initLayoutMode = function( name ) { 3045 var Mode = LayoutMode.modes[ name ]; 3046 // set mode options 3047 // HACK extend initial options, back-fill in default options 3048 var initialOpts = this.options[ name ] || {}; 3049 this.options[ name ] = Mode.options ? 3050 utils.extend( Mode.options, initialOpts ) : initialOpts; 3051 // init layout mode instance 3052 this.modes[ name ] = new Mode( this ); 3053 }; 3054 3055 3056 proto.layout = function() { 3057 // if first time doing layout, do all magic 3058 if ( !this._isLayoutInited && this._getOption('initLayout') ) { 3059 this.arrange(); 3060 return; 3061 } 3062 this._layout(); 3063 }; 3064 3065 // private method to be used in layout() & magic() 3066 proto._layout = function() { 3067 // don't animate first layout 3068 var isInstant = this._getIsInstant(); 3069 // layout flow 3070 this._resetLayout(); 3071 this._manageStamps(); 3072 this.layoutItems( this.filteredItems, isInstant ); 3073 3074 // flag for initalized 3075 this._isLayoutInited = true; 3076 }; 3077 3078 // filter + sort + layout 3079 proto.arrange = function( opts ) { 3080 // set any options pass 3081 this.option( opts ); 3082 this._getIsInstant(); 3083 // filter, sort, and layout 3084 3085 // filter 3086 var filtered = this._filter( this.items ); 3087 this.filteredItems = filtered.matches; 3088 3089 this._bindArrangeComplete(); 3090 3091 if ( this._isInstant ) { 3092 this._noTransition( this._hideReveal, [ filtered ] ); 3093 } else { 3094 this._hideReveal( filtered ); 3095 } 3096 3097 this._sort(); 3098 this._layout(); 3099 }; 3100 // alias to _init for main plugin method 3101 proto._init = proto.arrange; 3102 3103 proto._hideReveal = function( filtered ) { 3104 this.reveal( filtered.needReveal ); 3105 this.hide( filtered.needHide ); 3106 }; 3107 3108 // HACK 3109 // Don't animate/transition first layout 3110 // Or don't animate/transition other layouts 3111 proto._getIsInstant = function() { 3112 var isLayoutInstant = this._getOption('layoutInstant'); 3113 var isInstant = isLayoutInstant !== undefined ? isLayoutInstant : 3114 !this._isLayoutInited; 3115 this._isInstant = isInstant; 3116 return isInstant; 3117 }; 3118 3119 // listen for layoutComplete, hideComplete and revealComplete 3120 // to trigger arrangeComplete 3121 proto._bindArrangeComplete = function() { 3122 // listen for 3 events to trigger arrangeComplete 3123 var isLayoutComplete, isHideComplete, isRevealComplete; 3124 var _this = this; 3125 function arrangeParallelCallback() { 3126 if ( isLayoutComplete && isHideComplete && isRevealComplete ) { 3127 _this.dispatchEvent( 'arrangeComplete', null, [ _this.filteredItems ] ); 3128 } 3129 } 3130 this.once( 'layoutComplete', function() { 3131 isLayoutComplete = true; 3132 arrangeParallelCallback(); 3133 }); 3134 this.once( 'hideComplete', function() { 3135 isHideComplete = true; 3136 arrangeParallelCallback(); 3137 }); 3138 this.once( 'revealComplete', function() { 3139 isRevealComplete = true; 3140 arrangeParallelCallback(); 3141 }); 3142 }; 3143 3144 // -------------------------- filter -------------------------- // 3145 3146 proto._filter = function( items ) { 3147 var filter = this.options.filter;
vendor: 12,676 bytes, lines 3148-3541
3148 filter = filter || '*'; 3149 var matches = []; 3150 var hiddenMatched = []; 3151 var visibleUnmatched = []; 3152 3153 var test = this._getFilterTest( filter ); 3154 3155 // test each item 3156 for ( var i=0; i < items.length; i++ ) { 3157 var item = items[i]; 3158 if ( item.isIgnored ) { 3159 continue; 3160 } 3161 // add item to either matched or unmatched group 3162 var isMatched = test( item ); 3163 // item.isFilterMatched = isMatched; 3164 // add to matches if its a match 3165 if ( isMatched ) { 3166 matches.push( item ); 3167 } 3168 // add to additional group if item needs to be hidden or revealed 3169 if ( isMatched && item.isHidden ) { 3170 hiddenMatched.push( item ); 3171 } else if ( !isMatched && !item.isHidden ) { 3172 visibleUnmatched.push( item ); 3173 } 3174 } 3175 3176 // return collections of items to be manipulated 3177 return { 3178 matches: matches, 3179 needReveal: hiddenMatched, 3180 needHide: visibleUnmatched 3181 }; 3182 }; 3183 3184 // get a jQuery, function, or a matchesSelector test given the filter 3185 proto._getFilterTest = function( filter ) { 3186 if ( jQuery && this.options.isJQueryFiltering ) { 3187 // use jQuery 3188 return function( item ) { 3189 return jQuery( item.element ).is( filter ); 3190 }; 3191 } 3192 if ( typeof filter == 'function' ) { 3193 // use filter as function 3194 return function( item ) { 3195 return filter( item.element ); 3196 }; 3197 } 3198 // default, use filter as selector string 3199 return function( item ) { 3200 return matchesSelector( item.element, filter ); 3201 }; 3202 }; 3203 3204 // -------------------------- sorting -------------------------- // 3205 3206 /** 3207 * @params {Array} elems 3208 * @public 3209 */ 3210 proto.updateSortData = function( elems ) { 3211 // get items 3212 var items; 3213 if ( elems ) { 3214 elems = utils.makeArray( elems ); 3215 items = this.getItems( elems ); 3216 } else { 3217 // update all items if no elems provided 3218 items = this.items; 3219 } 3220 3221 this._getSorters(); 3222 this._updateItemsSortData( items ); 3223 }; 3224 3225 proto._getSorters = function() { 3226 var getSortData = this.options.getSortData; 3227 for ( var key in getSortData ) { 3228 var sorter = getSortData[ key ]; 3229 this._sorters[ key ] = mungeSorter( sorter ); 3230 } 3231 }; 3232 3233 /** 3234 * @params {Array} items - of Isotope.Items 3235 * @private 3236 */ 3237 proto._updateItemsSortData = function( items ) { 3238 // do not update if no items 3239 var len = items && items.length; 3240 3241 for ( var i=0; len && i < len; i++ ) { 3242 var item = items[i]; 3243 item.updateSortData(); 3244 } 3245 }; 3246 3247 // ----- munge sorter ----- // 3248 3249 // encapsulate this, as we just need mungeSorter 3250 // other functions in here are just for munging 3251 var mungeSorter = ( function() { 3252 // add a magic layer to sorters for convienent shorthands 3253 // `.foo-bar` will use the text of .foo-bar querySelector 3254 // `[foo-bar]` will use attribute 3255 // you can also add parser 3256 // `.foo-bar parseInt` will parse that as a number 3257 function mungeSorter( sorter ) { 3258 // if not a string, return function or whatever it is 3259 if ( typeof sorter != 'string' ) { 3260 return sorter; 3261 } 3262 // parse the sorter string 3263 var args = trim( sorter ).split(' '); 3264 var query = args[0]; 3265 // check if query looks like [an-attribute] 3266 var attrMatch = query.match( /^\[(.+)\]$/ ); 3267 var attr = attrMatch && attrMatch[1]; 3268 var getValue = getValueGetter( attr, query ); 3269 // use second argument as a parser 3270 var parser = Isotope.sortDataParsers[ args[1] ]; 3271 // parse the value, if there was a parser 3272 sorter = parser ? function( elem ) { 3273 return elem && parser( getValue( elem ) ); 3274 } : 3275 // otherwise just return value 3276 function( elem ) { 3277 return elem && getValue( elem ); 3278 }; 3279 3280 return sorter; 3281 } 3282 3283 // get an attribute getter, or get text of the querySelector 3284 function getValueGetter( attr, query ) { 3285 // if query looks like [foo-bar], get attribute 3286 if ( attr ) { 3287 return function getAttribute( elem ) { 3288 return elem.getAttribute( attr ); 3289 }; 3290 } 3291 3292 // otherwise, assume its a querySelector, and get its text 3293 return function getChildText( elem ) { 3294 var child = elem.querySelector( query ); 3295 return child && child.textContent; 3296 }; 3297 } 3298 3299 return mungeSorter; 3300 })(); 3301 3302 // parsers used in getSortData shortcut strings 3303 Isotope.sortDataParsers = { 3304 'parseInt': function( val ) { 3305 return parseInt( val, 10 ); 3306 }, 3307 'parseFloat': function( val ) { 3308 return parseFloat( val ); 3309 } 3310 }; 3311 3312 // ----- sort method ----- // 3313 3314 // sort filteredItem order 3315 proto._sort = function() { 3316 if ( !this.options.sortBy ) { 3317 return; 3318 } 3319 // keep track of sortBy History 3320 var sortBys = utils.makeArray( this.options.sortBy ); 3321 if ( !this._getIsSameSortBy( sortBys ) ) { 3322 // concat all sortBy and sortHistory, add to front, oldest goes in last 3323 this.sortHistory = sortBys.concat( this.sortHistory ); 3324 } 3325 // sort magic 3326 var itemSorter = getItemSorter( this.sortHistory, this.options.sortAscending ); 3327 this.filteredItems.sort( itemSorter ); 3328 }; 3329 3330 // check if sortBys is same as start of sortHistory 3331 proto._getIsSameSortBy = function( sortBys ) { 3332 for ( var i=0; i < sortBys.length; i++ ) { 3333 if ( sortBys[i] != this.sortHistory[i] ) { 3334 return false; 3335 } 3336 } 3337 return true; 3338 }; 3339 3340 // returns a function used for sorting 3341 function getItemSorter( sortBys, sortAsc ) { 3342 return function sorter( itemA, itemB ) { 3343 // cycle through all sortKeys 3344 for ( var i = 0; i < sortBys.length; i++ ) { 3345 var sortBy = sortBys[i]; 3346 var a = itemA.sortData[ sortBy ]; 3347 var b = itemB.sortData[ sortBy ]; 3348 if ( a > b || a < b ) { 3349 // if sortAsc is an object, use the value given the sortBy key 3350 var isAscending = sortAsc[ sortBy ] !== undefined ? sortAsc[ sortBy ] : sortAsc; 3351 var direction = isAscending ? 1 : -1; 3352 return ( a > b ? 1 : -1 ) * direction; 3353 } 3354 } 3355 return 0; 3356 }; 3357 } 3358 3359 // -------------------------- methods -------------------------- // 3360 3361 // get layout mode 3362 proto._mode = function() { 3363 var layoutMode = this.options.layoutMode; 3364 var mode = this.modes[ layoutMode ]; 3365 if ( !mode ) { 3366 // TODO console.error 3367 throw new Error( 'No layout mode: ' + layoutMode ); 3368 } 3369 // HACK sync mode's options 3370 // any options set after init for layout mode need to be synced 3371 mode.options = this.options[ layoutMode ]; 3372 return mode; 3373 }; 3374 3375 proto._resetLayout = function() { 3376 // trigger original reset layout 3377 Outlayer.prototype._resetLayout.call( this ); 3378 this._mode()._resetLayout(); 3379 }; 3380 3381 proto._getItemLayoutPosition = function( item ) { 3382 return this._mode()._getItemLayoutPosition( item ); 3383 }; 3384 3385 proto._manageStamp = function( stamp ) { 3386 this._mode()._manageStamp( stamp ); 3387 }; 3388 3389 proto._getContainerSize = function() { 3390 return this._mode()._getContainerSize(); 3391 }; 3392 3393 proto.needsResizeLayout = function() { 3394 return this._mode().needsResizeLayout(); 3395 }; 3396 3397 // -------------------------- adding & removing -------------------------- // 3398 3399 // HEADS UP overwrites default Outlayer appended 3400 proto.appended = function( elems ) { 3401 var items = this.addItems( elems ); 3402 if ( !items.length ) { 3403 return; 3404 } 3405 // filter, layout, reveal new items 3406 var filteredItems = this._filterRevealAdded( items ); 3407 // add to filteredItems 3408 this.filteredItems = this.filteredItems.concat( filteredItems ); 3409 }; 3410 3411 // HEADS UP overwrites default Outlayer prepended 3412 proto.prepended = function( elems ) { 3413 var items = this._itemize( elems ); 3414 if ( !items.length ) { 3415 return; 3416 } 3417 // start new layout 3418 this._resetLayout(); 3419 this._manageStamps(); 3420 // filter, layout, reveal new items 3421 var filteredItems = this._filterRevealAdded( items ); 3422 // layout previous items 3423 this.layoutItems( this.filteredItems ); 3424 // add to items and filteredItems 3425 this.filteredItems = filteredItems.concat( this.filteredItems ); 3426 this.items = items.concat( this.items ); 3427 }; 3428 3429 proto._filterRevealAdded = function( items ) { 3430 var filtered = this._filter( items ); 3431 this.hide( filtered.needHide ); 3432 // reveal all new items 3433 this.reveal( filtered.matches ); 3434 // layout new items, no transition 3435 this.layoutItems( filtered.matches, true ); 3436 return filtered.matches; 3437 }; 3438 3439 /** 3440 * Filter, sort, and layout newly-appended item elements 3441 * @param {Array or NodeList or Element} elems 3442 */ 3443 proto.insert = function( elems ) { 3444 var items = this.addItems( elems ); 3445 if ( !items.length ) { 3446 return; 3447 } 3448 // append item elements 3449 var i, item; 3450 var len = items.length; 3451 for ( i=0; i < len; i++ ) { 3452 item = items[i]; 3453 this.element.appendChild( item.element ); 3454 } 3455 // filter new stuff 3456 var filteredInsertItems = this._filter( items ).matches; 3457 // set flag 3458 for ( i=0; i < len; i++ ) { 3459 items[i].isLayoutInstant = true; 3460 } 3461 this.arrange(); 3462 // reset flag 3463 for ( i=0; i < len; i++ ) { 3464 delete items[i].isLayoutInstant; 3465 } 3466 this.reveal( filteredInsertItems ); 3467 }; 3468 3469 var _remove = proto.remove; 3470 proto.remove = function( elems ) { 3471 elems = utils.makeArray( elems ); 3472 var removeItems = this.getItems( elems ); 3473 // do regular thing 3474 _remove.call( this, elems ); 3475 // bail if no items to remove 3476 var len = removeItems && removeItems.length; 3477 // remove elems from filteredItems 3478 for ( var i=0; len && i < len; i++ ) { 3479 var item = removeItems[i]; 3480 // remove item from collection 3481 utils.removeFrom( this.filteredItems, item ); 3482 } 3483 }; 3484 3485 proto.shuffle = function() { 3486 // update random sortData 3487 for ( var i=0; i < this.items.length; i++ ) { 3488 var item = this.items[i]; 3489 item.sortData.random = Math.random(); 3490 } 3491 this.options.sortBy = 'random'; 3492 this._sort(); 3493 this._layout(); 3494 }; 3495 3496 /** 3497 * trigger fn without transition 3498 * kind of hacky to have this in the first place 3499 * @param {Function} fn 3500 * @param {Array} args 3501 * @returns ret 3502 * @private 3503 */ 3504 proto._noTransition = function( fn, args ) { 3505 // save transitionDuration before disabling 3506 var transitionDuration = this.options.transitionDuration; 3507 // disable transition 3508 this.options.transitionDuration = 0; 3509 // do it 3510 var returnValue = fn.apply( this, args ); 3511 // re-enable transition for reveal 3512 this.options.transitionDuration = transitionDuration; 3513 return returnValue; 3514 }; 3515 3516 // ----- helper methods ----- // 3517 3518 /** 3519 * getter method for getting filtered item elements 3520 * @returns {Array} elems - collection of item elements 3521 */ 3522 proto.getFilteredItemElements = function() { 3523 return this.filteredItems.map( function( item ) { 3524 return item.element; 3525 }); 3526 }; 3527 3528 // ----- ----- // 3529 3530 return Isotope; 3531 3532})); 3533 3534 3535} 3536 3537/* 3538 FILE ARCHIVED ON 05:02:56 May 20, 2023 AND RETRIEVED FROM THE 3539 INTERNET ARCHIVE ON 12:06:49 Aug 06, 2026. 3540 JAVASCRIPT APPENDED BY WAYBACK MACHINE, COPYRIGHT INTERNET ARCHIVE. 3541
3542 ALL OTHER CONTENT MAY ALSO BE PROTECTED BY COPYRIGHT (17 U.S.C. 3543 SECTION 108(a)(3)). 3544*/ 3545/* 3546playback timings (ms): 3547 captures_list: 0.394 3548 exclusion.robots: 0.042 3549 exclusion.robots.policy: 0.034 3550 esindex: 0.008 3551 cdx.remote: 6.569 3552 LoadShardBlock: 120.705 (3) 3553 PetaboxLoader3.datanode: 111.426 (4) 3554 PetaboxLoader3.resolve: 63.128 (2) 3555 load_resource: 63.582 3556*/
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.