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