vendor: 36,544 bytes, lines 1-1379
1/*! 2 * Masonry PACKAGED v4.2.2 3 * Cascading grid layout library 4 * https://masonry.desandro.com 5 * MIT License 6 * by David DeSandro 7 */ 8 9/** 10 * Bridget makes jQuery widgets 11 * v2.0.1 12 * MIT license 13 */ 14 15/* jshint browser: true, strict: true, undef: true, unused: true */ 16 17( function( window, factory ) { 18 // universal module definition 19 /*jshint strict: false */ /* globals define, module, require */ 20 if ( typeof define == 'function' && define.amd ) { 21 // AMD 22 define( 'jquery-bridget/jquery-bridget',[ 'jquery' ], function( jQuery ) { 23 return factory( window, jQuery ); 24 }); 25 } else if ( typeof module == 'object' && module.exports ) { 26 // CommonJS 27 module.exports = factory( 28 window, 29 require('jquery') 30 ); 31 } else { 32 // browser global 33 window.jQueryBridget = factory( 34 window, 35 window.jQuery 36 ); 37 } 38 39}( window, function factory( window, jQuery ) { 40'use strict'; 41 42// ----- utils ----- // 43 44var arraySlice = Array.prototype.slice; 45 46// helper function for logging errors 47// $.error breaks jQuery chaining 48var console = window.console; 49var logError = typeof console == 'undefined' ? function() {} : 50 function( message ) { 51 console.error( message ); 52 }; 53 54// ----- jQueryBridget ----- // 55 56function jQueryBridget( namespace, PluginClass, $ ) { 57 $ = $ || jQuery || window.jQuery; 58 if ( !$ ) { 59 return; 60 } 61 62 // add option method -> $().plugin('option', {...}) 63 if ( !PluginClass.prototype.option ) { 64 // option setter 65 PluginClass.prototype.option = function( opts ) { 66 // bail out if not an object 67 if ( !$.isPlainObject( opts ) ){ 68 return; 69 } 70 this.options = $.extend( true, this.options, opts ); 71 }; 72 } 73 74 // make jQuery plugin 75 $.fn[ namespace ] = function( arg0 /*, arg1 */ ) { 76 if ( typeof arg0 == 'string' ) { 77 // method call $().plugin( 'methodName', { options } ) 78 // shift arguments by 1 79 var args = arraySlice.call( arguments, 1 ); 80 return methodCall( this, arg0, args ); 81 } 82 // just $().plugin({ options }) 83 plainCall( this, arg0 ); 84 return this; 85 }; 86 87 // $().plugin('methodName') 88 function methodCall( $elems, methodName, args ) { 89 var returnValue; 90 var pluginMethodStr = '$().' + namespace + '("' + methodName + '")'; 91 92 $elems.each( function( i, elem ) { 93 // get instance 94 var instance = $.data( elem, namespace ); 95 if ( !instance ) { 96 logError( namespace + ' not initialized. Cannot call methods, i.e. ' + 97 pluginMethodStr ); 98 return; 99 } 100 101 var method = instance[ methodName ]; 102 if ( !method || methodName.charAt(0) == '_' ) { 103 logError( pluginMethodStr + ' is not a valid method' ); 104 return; 105 } 106 107 // apply method, get return value 108 var value = method.apply( instance, args ); 109 // set return value if value is returned, use only first value 110 returnValue = returnValue === undefined ? value : returnValue; 111 }); 112 113 return returnValue !== undefined ? returnValue : $elems; 114 } 115 116 function plainCall( $elems, options ) { 117 $elems.each( function( i, elem ) { 118 var instance = $.data( elem, namespace ); 119 if ( instance ) { 120 // set options & init 121 instance.option( options ); 122 instance._init(); 123 } else { 124 // initialize new instance 125 instance = new PluginClass( elem, options ); 126 $.data( elem, namespace, instance ); 127 } 128 }); 129 } 130 131 updateJQuery( $ ); 132 133} 134 135// ----- updateJQuery ----- // 136 137// set $.bridget for v1 backwards compatibility 138function updateJQuery( $ ) { 139 if ( !$ || ( $ && $.bridget ) ) { 140 return; 141 } 142 $.bridget = jQueryBridget; 143} 144 145updateJQuery( jQuery || window.jQuery ); 146 147// ----- ----- // 148 149return jQueryBridget; 150 151})); 152 153/** 154 * EvEmitter v1.1.0 155 * Lil' event emitter 156 * MIT License 157 */ 158 159/* jshint unused: true, undef: true, strict: true */ 160 161( function( global, factory ) { 162 // universal module definition 163 /* jshint strict: false */ /* globals define, module, window */ 164 if ( typeof define == 'function' && define.amd ) { 165 // AMD - RequireJS 166 define( 'ev-emitter/ev-emitter',factory ); 167 } else if ( typeof module == 'object' && module.exports ) { 168 // CommonJS - Browserify, Webpack 169 module.exports = factory(); 170 } else { 171 // Browser globals 172 global.EvEmitter = factory(); 173 } 174 175}( typeof window != 'undefined' ? window : this, function() { 176 177 178 179function EvEmitter() {} 180 181var proto = EvEmitter.prototype; 182 183proto.on = function( eventName, listener ) { 184 if ( !eventName || !listener ) { 185 return; 186 } 187 // set events hash 188 var events = this._events = this._events || {}; 189 // set listeners array 190 var listeners = events[ eventName ] = events[ eventName ] || []; 191 // only add once 192 if ( listeners.indexOf( listener ) == -1 ) { 193 listeners.push( listener ); 194 } 195 196 return this; 197}; 198 199proto.once = function( eventName, listener ) { 200 if ( !eventName || !listener ) { 201 return; 202 } 203 // add event 204 this.on( eventName, listener ); 205 // set once flag 206 // set onceEvents hash 207 var onceEvents = this._onceEvents = this._onceEvents || {}; 208 // set onceListeners object 209 var onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {}; 210 // set flag 211 onceListeners[ listener ] = true; 212 213 return this; 214}; 215 216proto.off = function( eventName, listener ) { 217 var listeners = this._events && this._events[ eventName ]; 218 if ( !listeners || !listeners.length ) { 219 return; 220 } 221 var index = listeners.indexOf( listener ); 222 if ( index != -1 ) { 223 listeners.splice( index, 1 ); 224 } 225 226 return this; 227}; 228 229proto.emitEvent = function( eventName, args ) { 230 var listeners = this._events && this._events[ eventName ]; 231 if ( !listeners || !listeners.length ) { 232 return; 233 } 234 // copy over to avoid interference if .off() in listener 235 listeners = listeners.slice(0); 236 args = args || []; 237 // once stuff 238 var onceListeners = this._onceEvents && this._onceEvents[ eventName ]; 239 240 for ( var i=0; i < listeners.length; i++ ) { 241 var listener = listeners[i] 242 var isOnce = onceListeners && onceListeners[ listener ]; 243 if ( isOnce ) { 244 // remove listener 245 // remove before trigger to prevent recursion 246 this.off( eventName, listener ); 247 // unset once flag 248 delete onceListeners[ listener ]; 249 } 250 // trigger listener 251 listener.apply( this, args ); 252 } 253 254 return this; 255}; 256 257proto.allOff = function() { 258 delete this._events; 259 delete this._onceEvents; 260}; 261 262return EvEmitter; 263 264})); 265 266/*! 267 * getSize v2.0.3 268 * measure size of elements 269 * MIT license 270 */ 271 272/* jshint browser: true, strict: true, undef: true, unused: true */ 273/* globals console: false */ 274 275( function( window, factory ) { 276 /* jshint strict: false */ /* globals define, module */ 277 if ( typeof define == 'function' && define.amd ) { 278 // AMD 279 define( 'get-size/get-size',factory ); 280 } else if ( typeof module == 'object' && module.exports ) { 281 // CommonJS 282 module.exports = factory(); 283 } else { 284 // browser global 285 window.getSize = factory(); 286 } 287 288})( window, function factory() { 289'use strict'; 290 291// -------------------------- helpers -------------------------- // 292 293// get a number from a string, not a percentage 294function getStyleSize( value ) { 295 var num = parseFloat( value ); 296 // not a percent like '100%', and a number 297 var isValid = value.indexOf('%') == -1 && !isNaN( num ); 298 return isValid && num; 299} 300 301function noop() {} 302 303var logError = typeof console == 'undefined' ? noop : 304 function( message ) { 305 console.error( message ); 306 }; 307 308// -------------------------- measurements -------------------------- // 309 310var measurements = [ 311 'paddingLeft', 312 'paddingRight', 313 'paddingTop', 314 'paddingBottom', 315 'marginLeft', 316 'marginRight', 317 'marginTop', 318 'marginBottom', 319 'borderLeftWidth', 320 'borderRightWidth', 321 'borderTopWidth', 322 'borderBottomWidth' 323]; 324 325var measurementsLength = measurements.length; 326 327function getZeroSize() { 328 var size = { 329 width: 0, 330 height: 0, 331 innerWidth: 0, 332 innerHeight: 0, 333 outerWidth: 0, 334 outerHeight: 0 335 }; 336 for ( var i=0; i < measurementsLength; i++ ) { 337 var measurement = measurements[i]; 338 size[ measurement ] = 0; 339 } 340 return size; 341} 342 343// -------------------------- getStyle -------------------------- // 344 345/** 346 * getStyle, get style of element, check for Firefox bug 347 * https://bugzilla.mozilla.org/show_bug.cgi?id=548397 348 */ 349function getStyle( elem ) { 350 var style = getComputedStyle( elem ); 351 if ( !style ) { 352 logError( 'Style returned ' + style + 353 '. Are you running this code in a hidden iframe on Firefox? ' + 354 'See https://bit.ly/getsizebug1' ); 355 } 356 return style; 357} 358 359// -------------------------- setup -------------------------- // 360 361var isSetup = false; 362 363var isBoxSizeOuter; 364 365/** 366 * setup 367 * check isBoxSizerOuter 368 * do on first getSize() rather than on page load for Firefox bug 369 */ 370function setup() { 371 // setup once 372 if ( isSetup ) { 373 return; 374 } 375 isSetup = true; 376 377 // -------------------------- box sizing -------------------------- // 378 379 /** 380 * Chrome & Safari measure the outer-width on style.width on border-box elems 381 * IE11 & Firefox<29 measures the inner-width 382 */ 383 var div = document.createElement('div'); 384 div.style.width = '200px'; 385 div.style.padding = '1px 2px 3px 4px'; 386 div.style.borderStyle = 'solid'; 387 div.style.borderWidth = '1px 2px 3px 4px'; 388 div.style.boxSizing = 'border-box'; 389 390 var body = document.body || document.documentElement; 391 body.appendChild( div ); 392 var style = getStyle( div ); 393 // round value for browser zoom. desandro/masonry#928 394 isBoxSizeOuter = Math.round( getStyleSize( style.width ) ) == 200; 395 getSize.isBoxSizeOuter = isBoxSizeOuter; 396 397 body.removeChild( div ); 398} 399 400// -------------------------- getSize -------------------------- // 401 402function getSize( elem ) { 403 setup(); 404 405 // use querySeletor if elem is string 406 if ( typeof elem == 'string' ) { 407 elem = document.querySelector( elem ); 408 } 409 410 // do not proceed on non-objects 411 if ( !elem || typeof elem != 'object' || !elem.nodeType ) { 412 return; 413 } 414 415 var style = getStyle( elem ); 416 417 // if hidden, everything is 0 418 if ( style.display == 'none' ) { 419 return getZeroSize(); 420 } 421 422 var size = {}; 423 size.width = elem.offsetWidth; 424 size.height = elem.offsetHeight; 425 426 var isBorderBox = size.isBorderBox = style.boxSizing == 'border-box'; 427 428 // get all measurements 429 for ( var i=0; i < measurementsLength; i++ ) { 430 var measurement = measurements[i]; 431 var value = style[ measurement ]; 432 var num = parseFloat( value ); 433 // any 'auto', 'medium' value will be 0 434 size[ measurement ] = !isNaN( num ) ? num : 0; 435 } 436 437 var paddingWidth = size.paddingLeft + size.paddingRight; 438 var paddingHeight = size.paddingTop + size.paddingBottom; 439 var marginWidth = size.marginLeft + size.marginRight; 440 var marginHeight = size.marginTop + size.marginBottom; 441 var borderWidth = size.borderLeftWidth + size.borderRightWidth; 442 var borderHeight = size.borderTopWidth + size.borderBottomWidth; 443 444 var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter; 445 446 // overwrite width and height if we can get it from style 447 var styleWidth = getStyleSize( style.width ); 448 if ( styleWidth !== false ) { 449 size.width = styleWidth + 450 // add padding and border unless it's already including it 451 ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth ); 452 } 453 454 var styleHeight = getStyleSize( style.height ); 455 if ( styleHeight !== false ) { 456 size.height = styleHeight + 457 // add padding and border unless it's already including it 458 ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight ); 459 } 460 461 size.innerWidth = size.width - ( paddingWidth + borderWidth ); 462 size.innerHeight = size.height - ( paddingHeight + borderHeight ); 463 464 size.outerWidth = size.width + marginWidth; 465 size.outerHeight = size.height + marginHeight; 466 467 return size; 468} 469 470return getSize; 471 472}); 473 474/** 475 * matchesSelector v2.0.2 476 * matchesSelector( element, '.selector' ) 477 * MIT license 478 */ 479 480/*jshint browser: true, strict: true, undef: true, unused: true */ 481 482( function( window, factory ) { 483 /*global define: false, module: false */ 484 'use strict'; 485 // universal module definition 486 if ( typeof define == 'function' && define.amd ) { 487 // AMD 488 define( 'desandro-matches-selector/matches-selector',factory ); 489 } else if ( typeof module == 'object' && module.exports ) { 490 // CommonJS 491 module.exports = factory(); 492 } else { 493 // browser global 494 window.matchesSelector = factory(); 495 } 496 497}( window, function factory() { 498 'use strict'; 499 500 var matchesMethod = ( function() { 501 var ElemProto = window.Element.prototype; 502 // check for the standard method name first 503 if ( ElemProto.matches ) { 504 return 'matches'; 505 } 506 // check un-prefixed 507 if ( ElemProto.matchesSelector ) { 508 return 'matchesSelector'; 509 } 510 // check vendor prefixes 511 var prefixes = [ 'webkit', 'moz', 'ms', 'o' ]; 512 513 for ( var i=0; i < prefixes.length; i++ ) { 514 var prefix = prefixes[i]; 515 var method = prefix + 'MatchesSelector'; 516 if ( ElemProto[ method ] ) { 517 return method; 518 } 519 } 520 })(); 521 522 return function matchesSelector( elem, selector ) { 523 return elem[ matchesMethod ]( selector ); 524 }; 525 526})); 527 528/** 529 * Fizzy UI utils v2.0.7 530 * MIT license 531 */ 532 533/*jshint browser: true, undef: true, unused: true, strict: true */ 534 535( function( window, factory ) { 536 // universal module definition 537 /*jshint strict: false */ /*globals define, module, require */ 538 539 if ( typeof define == 'function' && define.amd ) { 540 // AMD 541 define( 'fizzy-ui-utils/utils',[ 542 'desandro-matches-selector/matches-selector' 543 ], function( matchesSelector ) { 544 return factory( window, matchesSelector ); 545 }); 546 } else if ( typeof module == 'object' && module.exports ) { 547 // CommonJS 548 module.exports = factory( 549 window, 550 require('desandro-matches-selector') 551 ); 552 } else { 553 // browser global 554 window.fizzyUIUtils = factory( 555 window, 556 window.matchesSelector 557 ); 558 } 559 560}( window, function factory( window, matchesSelector ) { 561 562 563 564var utils = {}; 565 566// ----- extend ----- // 567 568// extends objects 569utils.extend = function( a, b ) { 570 for ( var prop in b ) { 571 a[ prop ] = b[ prop ]; 572 } 573 return a; 574}; 575 576// ----- modulo ----- // 577 578utils.modulo = function( num, div ) { 579 return ( ( num % div ) + div ) % div; 580}; 581 582// ----- makeArray ----- // 583 584var arraySlice = Array.prototype.slice; 585 586// turn element or nodeList into an array 587utils.makeArray = function( obj ) { 588 if ( Array.isArray( obj ) ) { 589 // use object if already an array 590 return obj; 591 } 592 // return empty array if undefined or null. #6 593 if ( obj === null || obj === undefined ) { 594 return []; 595 } 596 597 var isArrayLike = typeof obj == 'object' && typeof obj.length == 'number'; 598 if ( isArrayLike ) { 599 // convert nodeList to array 600 return arraySlice.call( obj ); 601 } 602 603 // array of single index 604 return [ obj ]; 605}; 606 607// ----- removeFrom ----- // 608 609utils.removeFrom = function( ary, obj ) { 610 var index = ary.indexOf( obj ); 611 if ( index != -1 ) { 612 ary.splice( index, 1 ); 613 } 614}; 615 616// ----- getParent ----- // 617 618utils.getParent = function( elem, selector ) { 619 while ( elem.parentNode && elem != document.body ) { 620 elem = elem.parentNode; 621 if ( matchesSelector( elem, selector ) ) { 622 return elem; 623 } 624 } 625}; 626 627// ----- getQueryElement ----- // 628 629// use element as selector string 630utils.getQueryElement = function( elem ) { 631 if ( typeof elem == 'string' ) { 632 return document.querySelector( elem ); 633 } 634 return elem; 635}; 636 637// ----- handleEvent ----- // 638 639// enable .ontype to trigger from .addEventListener( elem, 'type' ) 640utils.handleEvent = function( event ) { 641 var method = 'on' + event.type; 642 if ( this[ method ] ) { 643 this[ method ]( event ); 644 } 645}; 646 647// ----- filterFindElements ----- // 648 649utils.filterFindElements = function( elems, selector ) { 650 // make array of elems 651 elems = utils.makeArray( elems ); 652 var ffElems = []; 653 654 elems.forEach( function( elem ) { 655 // check that elem is an actual element 656 if ( !( elem instanceof HTMLElement ) ) { 657 return; 658 } 659 // add elem if no selector 660 if ( !selector ) { 661 ffElems.push( elem ); 662 return; 663 } 664 // filter & find items if we have a selector 665 // filter 666 if ( matchesSelector( elem, selector ) ) { 667 ffElems.push( elem ); 668 } 669 // find children 670 var childElems = elem.querySelectorAll( selector ); 671 // concat childElems to filterFound array 672 for ( var i=0; i < childElems.length; i++ ) { 673 ffElems.push( childElems[i] ); 674 } 675 }); 676 677 return ffElems; 678}; 679 680// ----- debounceMethod ----- // 681 682utils.debounceMethod = function( _class, methodName, threshold ) { 683 threshold = threshold || 100; 684 // original method 685 var method = _class.prototype[ methodName ]; 686 var timeoutName = methodName + 'Timeout'; 687 688 _class.prototype[ methodName ] = function() { 689 var timeout = this[ timeoutName ]; 690 clearTimeout( timeout ); 691 692 var args = arguments; 693 var _this = this; 694 this[ timeoutName ] = setTimeout( function() { 695 method.apply( _this, args ); 696 delete _this[ timeoutName ]; 697 }, threshold ); 698 }; 699}; 700 701// ----- docReady ----- // 702 703utils.docReady = function( callback ) { 704 var readyState = document.readyState; 705 if ( readyState == 'complete' || readyState == 'interactive' ) { 706 // do async to allow for other scripts to run. metafizzy/flickity#441 707 setTimeout( callback ); 708 } else { 709 document.addEventListener( 'DOMContentLoaded', callback ); 710 } 711}; 712 713// ----- htmlInit ----- // 714 715// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/ 716utils.toDashed = function( str ) { 717 return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) { 718 return $1 + '-' + $2; 719 }).toLowerCase(); 720}; 721 722var console = window.console; 723/** 724 * allow user to initialize classes via [data-namespace] or .js-namespace class 725 * htmlInit( Widget, 'widgetName' ) 726 * options are parsed from data-namespace-options 727 */ 728utils.htmlInit = function( WidgetClass, namespace ) { 729 utils.docReady( function() { 730 var dashedNamespace = utils.toDashed( namespace ); 731 var dataAttr = 'data-' + dashedNamespace; 732 var dataAttrElems = document.querySelectorAll( '[' + dataAttr + ']' ); 733 var jsDashElems = document.querySelectorAll( '.js-' + dashedNamespace ); 734 var elems = utils.makeArray( dataAttrElems ) 735 .concat( utils.makeArray( jsDashElems ) ); 736 var dataOptionsAttr = dataAttr + '-options'; 737 var jQuery = window.jQuery; 738 739 elems.forEach( function( elem ) { 740 var attr = elem.getAttribute( dataAttr ) || 741 elem.getAttribute( dataOptionsAttr ); 742 var options; 743 try { 744 options = attr && JSON.parse( attr ); 745 } catch ( error ) { 746 // log error, do not initialize 747 if ( console ) { 748 console.error( 'Error parsing ' + dataAttr + ' on ' + elem.className + 749 ': ' + error ); 750 } 751 return; 752 } 753 // initialize 754 var instance = new WidgetClass( elem, options ); 755 // make available via $().data('namespace') 756 if ( jQuery ) { 757 jQuery.data( elem, namespace, instance ); 758 } 759 }); 760 761 }); 762}; 763 764// ----- ----- // 765 766return utils; 767 768})); 769 770/** 771 * Outlayer Item 772 */ 773 774( function( window, factory ) { 775 // universal module definition 776 /* jshint strict: false */ /* globals define, module, require */ 777 if ( typeof define == 'function' && define.amd ) { 778 // AMD - RequireJS 779 define( 'outlayer/item',[ 780 'ev-emitter/ev-emitter', 781 'get-size/get-size' 782 ], 783 factory 784 ); 785 } else if ( typeof module == 'object' && module.exports ) { 786 // CommonJS - Browserify, Webpack 787 module.exports = factory( 788 require('ev-emitter'), 789 require('get-size') 790 ); 791 } else { 792 // browser global 793 window.Outlayer = {}; 794 window.Outlayer.Item = factory( 795 window.EvEmitter, 796 window.getSize 797 ); 798 } 799 800}( window, function factory( EvEmitter, getSize ) { 801'use strict'; 802 803// ----- helpers ----- // 804 805function isEmptyObj( obj ) { 806 for ( var prop in obj ) { 807 return false; 808 } 809 prop = null; 810 return true; 811} 812 813// -------------------------- CSS3 support -------------------------- // 814 815 816var docElemStyle = document.documentElement.style; 817 818var transitionProperty = typeof docElemStyle.transition == 'string' ? 819 'transition' : 'WebkitTransition'; 820var transformProperty = typeof docElemStyle.transform == 'string' ? 821 'transform' : 'WebkitTransform'; 822 823var transitionEndEvent = { 824 WebkitTransition: 'webkitTransitionEnd', 825 transition: 'transitionend' 826}[ transitionProperty ]; 827 828// cache all vendor properties that could have vendor prefix 829var vendorProperties = { 830 transform: transformProperty, 831 transition: transitionProperty, 832 transitionDuration: transitionProperty + 'Duration', 833 transitionProperty: transitionProperty + 'Property', 834 transitionDelay: transitionProperty + 'Delay' 835}; 836 837// -------------------------- Item -------------------------- // 838 839function Item( element, layout ) { 840 if ( !element ) { 841 return; 842 } 843 844 this.element = element; 845 // parent layout class, i.e. Masonry, Isotope, or Packery 846 this.layout = layout; 847 this.position = { 848 x: 0, 849 y: 0 850 }; 851 852 this._create(); 853} 854 855// inherit EvEmitter 856var proto = Item.prototype = Object.create( EvEmitter.prototype ); 857proto.constructor = Item; 858 859proto._create = function() { 860 // transition objects 861 this._transn = { 862 ingProperties: {}, 863 clean: {}, 864 onEnd: {} 865 }; 866 867 this.css({ 868 position: 'absolute' 869 }); 870}; 871 872// trigger specified handler for event type 873proto.handleEvent = function( event ) { 874 var method = 'on' + event.type; 875 if ( this[ method ] ) { 876 this[ method ]( event ); 877 } 878}; 879 880proto.getSize = function() { 881 this.size = getSize( this.element ); 882}; 883 884/** 885 * apply CSS styles to element 886 * @param {Object} style 887 */ 888proto.css = function( style ) { 889 var elemStyle = this.element.style; 890 891 for ( var prop in style ) { 892 // use vendor property if available 893 var supportedProp = vendorProperties[ prop ] || prop; 894 elemStyle[ supportedProp ] = style[ prop ]; 895 } 896}; 897 898 // measure position, and sets it 899proto.getPosition = function() { 900 var style = getComputedStyle( this.element ); 901 var isOriginLeft = this.layout._getOption('originLeft'); 902 var isOriginTop = this.layout._getOption('originTop'); 903 var xValue = style[ isOriginLeft ? 'left' : 'right' ]; 904 var yValue = style[ isOriginTop ? 'top' : 'bottom' ]; 905 var x = parseFloat( xValue ); 906 var y = parseFloat( yValue ); 907 // convert percent to pixels 908 var layoutSize = this.layout.size; 909 if ( xValue.indexOf('%') != -1 ) { 910 x = ( x / 100 ) * layoutSize.width; 911 } 912 if ( yValue.indexOf('%') != -1 ) { 913 y = ( y / 100 ) * layoutSize.height; 914 } 915 // clean up 'auto' or other non-integer values 916 x = isNaN( x ) ? 0 : x; 917 y = isNaN( y ) ? 0 : y; 918 // remove padding from measurement 919 x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight; 920 y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom; 921 922 this.position.x = x; 923 this.position.y = y; 924}; 925 926// set settled position, apply padding 927proto.layoutPosition = function() { 928 var layoutSize = this.layout.size; 929 var style = {}; 930 var isOriginLeft = this.layout._getOption('originLeft'); 931 var isOriginTop = this.layout._getOption('originTop'); 932 933 // x 934 var xPadding = isOriginLeft ? 'paddingLeft' : 'paddingRight'; 935 var xProperty = isOriginLeft ? 'left' : 'right'; 936 var xResetProperty = isOriginLeft ? 'right' : 'left'; 937 938 var x = this.position.x + layoutSize[ xPadding ]; 939 // set in percentage or pixels 940 style[ xProperty ] = this.getXValue( x ); 941 // reset other property 942 style[ xResetProperty ] = ''; 943 944 // y 945 var yPadding = isOriginTop ? 'paddingTop' : 'paddingBottom'; 946 var yProperty = isOriginTop ? 'top' : 'bottom'; 947 var yResetProperty = isOriginTop ? 'bottom' : 'top'; 948 949 var y = this.position.y + layoutSize[ yPadding ]; 950 // set in percentage or pixels 951 style[ yProperty ] = this.getYValue( y ); 952 // reset other property 953 style[ yResetProperty ] = ''; 954 955 this.css( style ); 956 this.emitEvent( 'layout', [ this ] ); 957}; 958 959proto.getXValue = function( x ) { 960 var isHorizontal = this.layout._getOption('horizontal'); 961 return this.layout.options.percentPosition && !isHorizontal ? 962 ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px'; 963}; 964 965proto.getYValue = function( y ) { 966 var isHorizontal = this.layout._getOption('horizontal'); 967 return this.layout.options.percentPosition && isHorizontal ? 968 ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px'; 969}; 970 971proto._transitionTo = function( x, y ) { 972 this.getPosition(); 973 // get current x & y from top/left 974 var curX = this.position.x; 975 var curY = this.position.y; 976 977 var didNotMove = x == this.position.x && y == this.position.y; 978 979 // save end position 980 this.setPosition( x, y ); 981 982 // if did not move and not transitioning, just go to layout 983 if ( didNotMove && !this.isTransitioning ) { 984 this.layoutPosition(); 985 return; 986 } 987 988 var transX = x - curX; 989 var transY = y - curY; 990 var transitionStyle = {}; 991 transitionStyle.transform = this.getTranslate( transX, transY ); 992 993 this.transition({ 994 to: transitionStyle, 995 onTransitionEnd: { 996 transform: this.layoutPosition 997 }, 998 isCleaning: true 999 }); 1000}; 1001 1002proto.getTranslate = function( x, y ) { 1003 // flip cooridinates if origin on right or bottom 1004 var isOriginLeft = this.layout._getOption('originLeft'); 1005 var isOriginTop = this.layout._getOption('originTop'); 1006 x = isOriginLeft ? x : -x; 1007 y = isOriginTop ? y : -y; 1008 return 'translate3d(' + x + 'px, ' + y + 'px, 0)'; 1009}; 1010 1011// non transition + transform support 1012proto.goTo = function( x, y ) { 1013 this.setPosition( x, y ); 1014 this.layoutPosition(); 1015}; 1016 1017proto.moveTo = proto._transitionTo; 1018 1019proto.setPosition = function( x, y ) { 1020 this.position.x = parseFloat( x ); 1021 this.position.y = parseFloat( y ); 1022}; 1023 1024// ----- transition ----- // 1025 1026/** 1027 * @param {Object} style - CSS 1028 * @param {Function} onTransitionEnd 1029 */ 1030 1031// non transition, just trigger callback 1032proto._nonTransition = function( args ) { 1033 this.css( args.to ); 1034 if ( args.isCleaning ) { 1035 this._removeStyles( args.to ); 1036 } 1037 for ( var prop in args.onTransitionEnd ) { 1038 args.onTransitionEnd[ prop ].call( this ); 1039 } 1040}; 1041 1042/** 1043 * proper transition 1044 * @param {Object} args - arguments 1045 * @param {Object} to - style to transition to 1046 * @param {Object} from - style to start transition from 1047 * @param {Boolean} isCleaning - removes transition styles after transition 1048 * @param {Function} onTransitionEnd - callback 1049 */ 1050proto.transition = function( args ) { 1051 // redirect to nonTransition if no transition duration 1052 if ( !parseFloat( this.layout.options.transitionDuration ) ) { 1053 this._nonTransition( args ); 1054 return; 1055 } 1056 1057 var _transition = this._transn; 1058 // keep track of onTransitionEnd callback by css property 1059 for ( var prop in args.onTransitionEnd ) { 1060 _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ]; 1061 } 1062 // keep track of properties that are transitioning 1063 for ( prop in args.to ) { 1064 _transition.ingProperties[ prop ] = true; 1065 // keep track of properties to clean up when transition is done 1066 if ( args.isCleaning ) { 1067 _transition.clean[ prop ] = true; 1068 } 1069 } 1070 1071 // set from styles 1072 if ( args.from ) { 1073 this.css( args.from ); 1074 // force redraw. http://blog.alexmaccaw.com/css-transitions 1075 var h = this.element.offsetHeight; 1076 // hack for JSHint to hush about unused var 1077 h = null; 1078 } 1079 // enable transition 1080 this.enableTransition( args.to ); 1081 // set styles that are transitioning 1082 this.css( args.to ); 1083 1084 this.isTransitioning = true; 1085 1086}; 1087 1088// dash before all cap letters, including first for 1089// WebkitTransform => -webkit-transform 1090function toDashedAll( str ) { 1091 return str.replace( /([A-Z])/g, function( $1 ) { 1092 return '-' + $1.toLowerCase(); 1093 }); 1094} 1095 1096var transitionProps = 'opacity,' + toDashedAll( transformProperty ); 1097 1098proto.enableTransition = function(/* style */) { 1099 // HACK changing transitionProperty during a transition 1100 // will cause transition to jump 1101 if ( this.isTransitioning ) { 1102 return; 1103 } 1104 1105 // make `transition: foo, bar, baz` from style object 1106 // HACK un-comment this when enableTransition can work 1107 // while a transition is happening 1108 // var transitionValues = []; 1109 // for ( var prop in style ) { 1110 // // dash-ify camelCased properties like WebkitTransition 1111 // prop = vendorProperties[ prop ] || prop; 1112 // transitionValues.push( toDashedAll( prop ) ); 1113 // } 1114 // munge number to millisecond, to match stagger 1115 var duration = this.layout.options.transitionDuration; 1116 duration = typeof duration == 'number' ? duration + 'ms' : duration; 1117 // enable transition styles 1118 this.css({ 1119 transitionProperty: transitionProps, 1120 transitionDuration: duration, 1121 transitionDelay: this.staggerDelay || 0 1122 }); 1123 // listen for transition end event 1124 this.element.addEventListener( transitionEndEvent, this, false ); 1125}; 1126 1127// ----- events ----- // 1128 1129proto.onwebkitTransitionEnd = function( event ) { 1130 this.ontransitionend( event ); 1131}; 1132 1133proto.onotransitionend = function( event ) { 1134 this.ontransitionend( event ); 1135}; 1136 1137// properties that I munge to make my life easier 1138var dashedVendorProperties = { 1139 '-webkit-transform': 'transform' 1140}; 1141 1142proto.ontransitionend = function( event ) { 1143 // disregard bubbled events from children 1144 if ( event.target !== this.element ) { 1145 return; 1146 } 1147 var _transition = this._transn; 1148 // get property name of transitioned property, convert to prefix-free 1149 var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName; 1150 1151 // remove property that has completed transitioning 1152 delete _transition.ingProperties[ propertyName ]; 1153 // check if any properties are still transitioning 1154 if ( isEmptyObj( _transition.ingProperties ) ) { 1155 // all properties have completed transitioning 1156 this.disableTransition(); 1157 } 1158 // clean style 1159 if ( propertyName in _transition.clean ) { 1160 // clean up style 1161 this.element.style[ event.propertyName ] = ''; 1162 delete _transition.clean[ propertyName ]; 1163 } 1164 // trigger onTransitionEnd callback 1165 if ( propertyName in _transition.onEnd ) { 1166 var onTransitionEnd = _transition.onEnd[ propertyName ]; 1167 onTransitionEnd.call( this ); 1168 delete _transition.onEnd[ propertyName ]; 1169 } 1170 1171 this.emitEvent( 'transitionEnd', [ this ] ); 1172}; 1173 1174proto.disableTransition = function() { 1175 this.removeTransitionStyles(); 1176 this.element.removeEventListener( transitionEndEvent, this, false ); 1177 this.isTransitioning = false; 1178}; 1179 1180/** 1181 * removes style property from element 1182 * @param {Object} style 1183**/ 1184proto._removeStyles = function( style ) { 1185 // clean up transition styles 1186 var cleanStyle = {}; 1187 for ( var prop in style ) { 1188 cleanStyle[ prop ] = ''; 1189 } 1190 this.css( cleanStyle ); 1191}; 1192 1193var cleanTransitionStyle = { 1194 transitionProperty: '', 1195 transitionDuration: '', 1196 transitionDelay: '' 1197}; 1198 1199proto.removeTransitionStyles = function() { 1200 // remove transition 1201 this.css( cleanTransitionStyle ); 1202}; 1203 1204// ----- stagger ----- // 1205 1206proto.stagger = function( delay ) { 1207 delay = isNaN( delay ) ? 0 : delay; 1208 this.staggerDelay = delay + 'ms'; 1209}; 1210 1211// ----- show/hide/remove ----- // 1212 1213// remove element from DOM 1214proto.removeElem = function() { 1215 this.element.parentNode.removeChild( this.element ); 1216 // remove display: none 1217 this.css({ display: '' }); 1218 this.emitEvent( 'remove', [ this ] ); 1219}; 1220 1221proto.remove = function() { 1222 // just remove element if no transition support or no transition 1223 if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) { 1224 this.removeElem(); 1225 return; 1226 } 1227 1228 // start transition 1229 this.once( 'transitionEnd', function() { 1230 this.removeElem(); 1231 }); 1232 this.hide(); 1233}; 1234 1235proto.reveal = function() { 1236 delete this.isHidden; 1237 // remove display: none 1238 this.css({ display: '' }); 1239 1240 var options = this.layout.options; 1241 1242 var onTransitionEnd = {}; 1243 var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle'); 1244 onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd; 1245 1246 this.transition({ 1247 from: options.hiddenStyle, 1248 to: options.visibleStyle, 1249 isCleaning: true, 1250 onTransitionEnd: onTransitionEnd 1251 }); 1252}; 1253 1254proto.onRevealTransitionEnd = function() { 1255 // check if still visible 1256 // during transition, item may have been hidden 1257 if ( !this.isHidden ) { 1258 this.emitEvent('reveal'); 1259 } 1260}; 1261 1262/** 1263 * get style property use for hide/reveal transition end 1264 * @param {String} styleProperty - hiddenStyle/visibleStyle 1265 * @returns {String} 1266 */ 1267proto.getHideRevealTransitionEndProperty = function( styleProperty ) { 1268 var optionStyle = this.layout.options[ styleProperty ]; 1269 // use opacity 1270 if ( optionStyle.opacity ) { 1271 return 'opacity'; 1272 } 1273 // get first property 1274 for ( var prop in optionStyle ) { 1275 return prop; 1276 } 1277}; 1278 1279proto.hide = function() { 1280 // set flag 1281 this.isHidden = true; 1282 // remove display: none 1283 this.css({ display: '' }); 1284 1285 var options = this.layout.options; 1286 1287 var onTransitionEnd = {}; 1288 var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle'); 1289 onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd; 1290 1291 this.transition({ 1292 from: options.visibleStyle, 1293 to: options.hiddenStyle, 1294 // keep hidden stuff hidden 1295 isCleaning: true, 1296 onTransitionEnd: onTransitionEnd 1297 }); 1298}; 1299 1300proto.onHideTransitionEnd = function() { 1301 // check if still hidden 1302 // during transition, item may have been un-hidden 1303 if ( this.isHidden ) { 1304 this.css({ display: 'none' }); 1305 this.emitEvent('hide'); 1306 } 1307}; 1308 1309proto.destroy = function() { 1310 this.css({ 1311 position: '', 1312 left: '', 1313 right: '', 1314 top: '', 1315 bottom: '', 1316 transition: '', 1317 transform: '' 1318 }); 1319}; 1320 1321return Item; 1322 1323})); 1324 1325/*! 1326 * Outlayer v2.1.1 1327 * the brains and guts of a layout library 1328 * MIT license 1329 */ 1330 1331( function( window, factory ) { 1332 'use strict'; 1333 // universal module definition 1334 /* jshint strict: false */ /* globals define, module, require */ 1335 if ( typeof define == 'function' && define.amd ) { 1336 // AMD - RequireJS 1337 define( 'outlayer/outlayer',[ 1338 'ev-emitter/ev-emitter', 1339 'get-size/get-size', 1340 'fizzy-ui-utils/utils', 1341 './item' 1342 ], 1343 function( EvEmitter, getSize, utils, Item ) { 1344 return factory( window, EvEmitter, getSize, utils, Item); 1345 } 1346 ); 1347 } else if ( typeof module == 'object' && module.exports ) { 1348 // CommonJS - Browserify, Webpack 1349 module.exports = factory( 1350 window, 1351 require('ev-emitter'), 1352 require('get-size'), 1353 require('fizzy-ui-utils'), 1354 require('./item') 1355 ); 1356 } else { 1357 // browser global 1358 window.Outlayer = factory( 1359 window, 1360 window.EvEmitter, 1361 window.getSize, 1362 window.fizzyUIUtils, 1363 window.Outlayer.Item 1364 ); 1365 } 1366 1367}( window, function factory( window, EvEmitter, getSize, utils, Item ) { 1368'use strict'; 1369 1370// ----- vars ----- // 1371 1372var console = window.console; 1373var jQuery = window.jQuery; 1374var noop = function() {}; 1375 1376// -------------------------- Outlayer -------------------------- // 1377 1378// globally unique identifiers 1379var GUID = 0;
vendor: 18,646 bytes, lines 1380-2137
1380// internal store of all Outlayer intances 1381var instances = {}; 1382 1383 1384/** 1385 * @param {Element, String} element 1386 * @param {Object} options 1387 * @constructor 1388 */ 1389function Outlayer( element, options ) { 1390 var queryElement = utils.getQueryElement( element ); 1391 if ( !queryElement ) { 1392 if ( console ) { 1393 console.error( 'Bad element for ' + this.constructor.namespace + 1394 ': ' + ( queryElement || element ) ); 1395 } 1396 return; 1397 } 1398 this.element = queryElement; 1399 // add jQuery 1400 if ( jQuery ) { 1401 this.$element = jQuery( this.element ); 1402 } 1403 1404 // options 1405 this.options = utils.extend( {}, this.constructor.defaults ); 1406 this.option( options ); 1407 1408 // add id for Outlayer.getFromElement 1409 var id = ++GUID; 1410 this.element.outlayerGUID = id; // expando 1411 instances[ id ] = this; // associate via id 1412 1413 // kick it off 1414 this._create(); 1415 1416 var isInitLayout = this._getOption('initLayout'); 1417 if ( isInitLayout ) { 1418 this.layout(); 1419 } 1420} 1421 1422// settings are for internal use only 1423Outlayer.namespace = 'outlayer'; 1424Outlayer.Item = Item; 1425 1426// default options 1427Outlayer.defaults = { 1428 containerStyle: { 1429 position: 'relative' 1430 }, 1431 initLayout: true, 1432 originLeft: true, 1433 originTop: true, 1434 resize: true, 1435 resizeContainer: true, 1436 // item options 1437 transitionDuration: '0.4s', 1438 hiddenStyle: { 1439 opacity: 0, 1440 transform: 'scale(0.001)' 1441 }, 1442 visibleStyle: { 1443 opacity: 1, 1444 transform: 'scale(1)' 1445 } 1446}; 1447 1448var proto = Outlayer.prototype; 1449// inherit EvEmitter 1450utils.extend( proto, EvEmitter.prototype ); 1451 1452/** 1453 * set options 1454 * @param {Object} opts 1455 */ 1456proto.option = function( opts ) { 1457 utils.extend( this.options, opts ); 1458}; 1459 1460/** 1461 * get backwards compatible option value, check old name 1462 */ 1463proto._getOption = function( option ) { 1464 var oldOption = this.constructor.compatOptions[ option ]; 1465 return oldOption && this.options[ oldOption ] !== undefined ? 1466 this.options[ oldOption ] : this.options[ option ]; 1467}; 1468 1469Outlayer.compatOptions = { 1470 // currentName: oldName 1471 initLayout: 'isInitLayout', 1472 horizontal: 'isHorizontal', 1473 layoutInstant: 'isLayoutInstant', 1474 originLeft: 'isOriginLeft', 1475 originTop: 'isOriginTop', 1476 resize: 'isResizeBound', 1477 resizeContainer: 'isResizingContainer' 1478}; 1479 1480proto._create = function() { 1481 // get items from children 1482 this.reloadItems(); 1483 // elements that affect layout, but are not laid out 1484 this.stamps = []; 1485 this.stamp( this.options.stamp ); 1486 // set container style 1487 utils.extend( this.element.style, this.options.containerStyle ); 1488 1489 // bind resize method 1490 var canBindResize = this._getOption('resize'); 1491 if ( canBindResize ) { 1492 this.bindResize(); 1493 } 1494}; 1495 1496// goes through all children again and gets bricks in proper order 1497proto.reloadItems = function() { 1498 // collection of item elements 1499 this.items = this._itemize( this.element.children ); 1500}; 1501 1502 1503/** 1504 * turn elements into Outlayer.Items to be used in layout 1505 * @param {Array or NodeList or HTMLElement} elems 1506 * @returns {Array} items - collection of new Outlayer Items 1507 */ 1508proto._itemize = function( elems ) { 1509 1510 var itemElems = this._filterFindItemElements( elems ); 1511 var Item = this.constructor.Item; 1512 1513 // create new Outlayer Items for collection 1514 var items = []; 1515 for ( var i=0; i < itemElems.length; i++ ) { 1516 var elem = itemElems[i]; 1517 var item = new Item( elem, this ); 1518 items.push( item ); 1519 } 1520 1521 return items; 1522}; 1523 1524/** 1525 * get item elements to be used in layout 1526 * @param {Array or NodeList or HTMLElement} elems 1527 * @returns {Array} items - item elements 1528 */ 1529proto._filterFindItemElements = function( elems ) { 1530 return utils.filterFindElements( elems, this.options.itemSelector ); 1531}; 1532 1533/** 1534 * getter method for getting item elements 1535 * @returns {Array} elems - collection of item elements 1536 */ 1537proto.getItemElements = function() { 1538 return this.items.map( function( item ) { 1539 return item.element; 1540 }); 1541}; 1542 1543// ----- init & layout ----- // 1544 1545/** 1546 * lays out all items 1547 */ 1548proto.layout = function() { 1549 this._resetLayout(); 1550 this._manageStamps(); 1551 1552 // don't animate first layout 1553 var layoutInstant = this._getOption('layoutInstant'); 1554 var isInstant = layoutInstant !== undefined ? 1555 layoutInstant : !this._isLayoutInited; 1556 this.layoutItems( this.items, isInstant ); 1557 1558 // flag for initalized 1559 this._isLayoutInited = true; 1560}; 1561 1562// _init is alias for layout 1563proto._init = proto.layout; 1564 1565/** 1566 * logic before any new layout 1567 */ 1568proto._resetLayout = function() { 1569 this.getSize(); 1570}; 1571 1572 1573proto.getSize = function() { 1574 this.size = getSize( this.element ); 1575}; 1576 1577/** 1578 * get measurement from option, for columnWidth, rowHeight, gutter 1579 * if option is String -> get element from selector string, & get size of element 1580 * if option is Element -> get size of element 1581 * else use option as a number 1582 * 1583 * @param {String} measurement 1584 * @param {String} size - width or height 1585 * @private 1586 */ 1587proto._getMeasurement = function( measurement, size ) { 1588 var option = this.options[ measurement ]; 1589 var elem; 1590 if ( !option ) { 1591 // default to 0 1592 this[ measurement ] = 0; 1593 } else { 1594 // use option as an element 1595 if ( typeof option == 'string' ) { 1596 elem = this.element.querySelector( option ); 1597 } else if ( option instanceof HTMLElement ) { 1598 elem = option; 1599 } 1600 // use size of element, if element 1601 this[ measurement ] = elem ? getSize( elem )[ size ] : option; 1602 } 1603}; 1604 1605/** 1606 * layout a collection of item elements 1607 * @api public 1608 */ 1609proto.layoutItems = function( items, isInstant ) { 1610 items = this._getItemsForLayout( items ); 1611 1612 this._layoutItems( items, isInstant ); 1613 1614 this._postLayout(); 1615}; 1616 1617/** 1618 * get the items to be laid out 1619 * you may want to skip over some items 1620 * @param {Array} items 1621 * @returns {Array} items 1622 */ 1623proto._getItemsForLayout = function( items ) { 1624 return items.filter( function( item ) { 1625 return !item.isIgnored; 1626 }); 1627}; 1628 1629/** 1630 * layout items 1631 * @param {Array} items 1632 * @param {Boolean} isInstant 1633 */ 1634proto._layoutItems = function( items, isInstant ) { 1635 this._emitCompleteOnItems( 'layout', items ); 1636 1637 if ( !items || !items.length ) { 1638 // no items, emit event with empty array 1639 return; 1640 } 1641 1642 var queue = []; 1643 1644 items.forEach( function( item ) { 1645 // get x/y object from method 1646 var position = this._getItemLayoutPosition( item ); 1647 // enqueue 1648 position.item = item; 1649 position.isInstant = isInstant || item.isLayoutInstant; 1650 queue.push( position ); 1651 }, this ); 1652 1653 this._processLayoutQueue( queue ); 1654}; 1655 1656/** 1657 * get item layout position 1658 * @param {Outlayer.Item} item 1659 * @returns {Object} x and y position 1660 */ 1661proto._getItemLayoutPosition = function( /* item */ ) { 1662 return { 1663 x: 0, 1664 y: 0 1665 }; 1666}; 1667 1668/** 1669 * iterate over array and position each item 1670 * Reason being - separating this logic prevents 'layout invalidation' 1671 * thx @paul_irish 1672 * @param {Array} queue 1673 */ 1674proto._processLayoutQueue = function( queue ) { 1675 this.updateStagger(); 1676 queue.forEach( function( obj, i ) { 1677 this._positionItem( obj.item, obj.x, obj.y, obj.isInstant, i ); 1678 }, this ); 1679}; 1680 1681// set stagger from option in milliseconds number 1682proto.updateStagger = function() { 1683 var stagger = this.options.stagger; 1684 if ( stagger === null || stagger === undefined ) { 1685 this.stagger = 0; 1686 return; 1687 } 1688 this.stagger = getMilliseconds( stagger ); 1689 return this.stagger; 1690}; 1691 1692/** 1693 * Sets position of item in DOM 1694 * @param {Outlayer.Item} item 1695 * @param {Number} x - horizontal position 1696 * @param {Number} y - vertical position 1697 * @param {Boolean} isInstant - disables transitions 1698 */ 1699proto._positionItem = function( item, x, y, isInstant, i ) { 1700 if ( isInstant ) { 1701 // if not transition, just set CSS 1702 item.goTo( x, y ); 1703 } else { 1704 item.stagger( i * this.stagger ); 1705 item.moveTo( x, y ); 1706 } 1707}; 1708 1709/** 1710 * Any logic you want to do after each layout, 1711 * i.e. size the container 1712 */ 1713proto._postLayout = function() { 1714 this.resizeContainer(); 1715}; 1716 1717proto.resizeContainer = function() { 1718 var isResizingContainer = this._getOption('resizeContainer'); 1719 if ( !isResizingContainer ) { 1720 return; 1721 } 1722 var size = this._getContainerSize(); 1723 if ( size ) { 1724 this._setContainerMeasure( size.width, true ); 1725 this._setContainerMeasure( size.height, false ); 1726 } 1727}; 1728 1729/** 1730 * Sets width or height of container if returned 1731 * @returns {Object} size 1732 * @param {Number} width 1733 * @param {Number} height 1734 */ 1735proto._getContainerSize = noop; 1736 1737/** 1738 * @param {Number} measure - size of width or height 1739 * @param {Boolean} isWidth 1740 */ 1741proto._setContainerMeasure = function( measure, isWidth ) { 1742 if ( measure === undefined ) { 1743 return; 1744 } 1745 1746 var elemSize = this.size; 1747 // add padding and border width if border box 1748 if ( elemSize.isBorderBox ) { 1749 measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight + 1750 elemSize.borderLeftWidth + elemSize.borderRightWidth : 1751 elemSize.paddingBottom + elemSize.paddingTop + 1752 elemSize.borderTopWidth + elemSize.borderBottomWidth; 1753 } 1754 1755 measure = Math.max( measure, 0 ); 1756 this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px'; 1757}; 1758 1759/** 1760 * emit eventComplete on a collection of items events 1761 * @param {String} eventName 1762 * @param {Array} items - Outlayer.Items 1763 */ 1764proto._emitCompleteOnItems = function( eventName, items ) { 1765 var _this = this; 1766 function onComplete() { 1767 _this.dispatchEvent( eventName + 'Complete', null, [ items ] ); 1768 } 1769 1770 var count = items.length; 1771 if ( !items || !count ) { 1772 onComplete(); 1773 return; 1774 } 1775 1776 var doneCount = 0; 1777 function tick() { 1778 doneCount++; 1779 if ( doneCount == count ) { 1780 onComplete(); 1781 } 1782 } 1783 1784 // bind callback 1785 items.forEach( function( item ) { 1786 item.once( eventName, tick ); 1787 }); 1788}; 1789 1790/** 1791 * emits events via EvEmitter and jQuery events 1792 * @param {String} type - name of event 1793 * @param {Event} event - original event 1794 * @param {Array} args - extra arguments 1795 */ 1796proto.dispatchEvent = function( type, event, args ) { 1797 // add original event to arguments 1798 var emitArgs = event ? [ event ].concat( args ) : args; 1799 this.emitEvent( type, emitArgs ); 1800 1801 if ( jQuery ) { 1802 // set this.$element 1803 this.$element = this.$element || jQuery( this.element ); 1804 if ( event ) { 1805 // create jQuery event 1806 var $event = jQuery.Event( event ); 1807 $event.type = type; 1808 this.$element.trigger( $event, args ); 1809 } else { 1810 // just trigger with type if no event available 1811 this.$element.trigger( type, args ); 1812 } 1813 } 1814}; 1815 1816// -------------------------- ignore & stamps -------------------------- // 1817 1818 1819/** 1820 * keep item in collection, but do not lay it out 1821 * ignored items do not get skipped in layout 1822 * @param {Element} elem 1823 */ 1824proto.ignore = function( elem ) { 1825 var item = this.getItem( elem ); 1826 if ( item ) { 1827 item.isIgnored = true; 1828 } 1829}; 1830 1831/** 1832 * return item to layout collection 1833 * @param {Element} elem 1834 */ 1835proto.unignore = function( elem ) { 1836 var item = this.getItem( elem ); 1837 if ( item ) { 1838 delete item.isIgnored; 1839 } 1840}; 1841 1842/** 1843 * adds elements to stamps 1844 * @param {NodeList, Array, Element, or String} elems 1845 */ 1846proto.stamp = function( elems ) { 1847 elems = this._find( elems ); 1848 if ( !elems ) { 1849 return; 1850 } 1851 1852 this.stamps = this.stamps.concat( elems ); 1853 // ignore 1854 elems.forEach( this.ignore, this ); 1855}; 1856 1857/** 1858 * removes elements to stamps 1859 * @param {NodeList, Array, or Element} elems 1860 */ 1861proto.unstamp = function( elems ) { 1862 elems = this._find( elems ); 1863 if ( !elems ){ 1864 return; 1865 } 1866 1867 elems.forEach( function( elem ) { 1868 // filter out removed stamp elements 1869 utils.removeFrom( this.stamps, elem ); 1870 this.unignore( elem ); 1871 }, this ); 1872}; 1873 1874/** 1875 * finds child elements 1876 * @param {NodeList, Array, Element, or String} elems 1877 * @returns {Array} elems 1878 */ 1879proto._find = function( elems ) { 1880 if ( !elems ) { 1881 return; 1882 } 1883 // if string, use argument as selector string 1884 if ( typeof elems == 'string' ) { 1885 elems = this.element.querySelectorAll( elems ); 1886 } 1887 elems = utils.makeArray( elems ); 1888 return elems; 1889}; 1890 1891proto._manageStamps = function() { 1892 if ( !this.stamps || !this.stamps.length ) { 1893 return; 1894 } 1895 1896 this._getBoundingRect(); 1897 1898 this.stamps.forEach( this._manageStamp, this ); 1899}; 1900 1901// update boundingLeft / Top 1902proto._getBoundingRect = function() { 1903 // get bounding rect for container element 1904 var boundingRect = this.element.getBoundingClientRect(); 1905 var size = this.size; 1906 this._boundingRect = { 1907 left: boundingRect.left + size.paddingLeft + size.borderLeftWidth, 1908 top: boundingRect.top + size.paddingTop + size.borderTopWidth, 1909 right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ), 1910 bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth ) 1911 }; 1912}; 1913 1914/** 1915 * @param {Element} stamp 1916**/ 1917proto._manageStamp = noop; 1918 1919/** 1920 * get x/y position of element relative to container element 1921 * @param {Element} elem 1922 * @returns {Object} offset - has left, top, right, bottom 1923 */ 1924proto._getElementOffset = function( elem ) { 1925 var boundingRect = elem.getBoundingClientRect(); 1926 var thisRect = this._boundingRect; 1927 var size = getSize( elem ); 1928 var offset = { 1929 left: boundingRect.left - thisRect.left - size.marginLeft, 1930 top: boundingRect.top - thisRect.top - size.marginTop, 1931 right: thisRect.right - boundingRect.right - size.marginRight, 1932 bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom 1933 }; 1934 return offset; 1935}; 1936 1937// -------------------------- resize -------------------------- // 1938 1939// enable event handlers for listeners 1940// i.e. resize -> onresize 1941proto.handleEvent = utils.handleEvent; 1942 1943/** 1944 * Bind layout to window resizing 1945 */ 1946proto.bindResize = function() { 1947 window.addEventListener( 'resize', this ); 1948 this.isResizeBound = true; 1949}; 1950 1951/** 1952 * Unbind layout to window resizing 1953 */ 1954proto.unbindResize = function() { 1955 window.removeEventListener( 'resize', this ); 1956 this.isResizeBound = false; 1957}; 1958 1959proto.onresize = function() { 1960 this.resize(); 1961}; 1962 1963utils.debounceMethod( Outlayer, 'onresize', 100 ); 1964 1965proto.resize = function() { 1966 // don't trigger if size did not change 1967 // or if resize was unbound. See #9 1968 if ( !this.isResizeBound || !this.needsResizeLayout() ) { 1969 return; 1970 } 1971 1972 this.layout(); 1973}; 1974 1975/** 1976 * check if layout is needed post layout 1977 * @returns Boolean 1978 */ 1979proto.needsResizeLayout = function() { 1980 var size = getSize( this.element ); 1981 // check that this.size and size are there 1982 // IE8 triggers resize on body size change, so they might not be 1983 var hasSizes = this.size && size; 1984 return hasSizes && size.innerWidth !== this.size.innerWidth; 1985}; 1986 1987// -------------------------- methods -------------------------- // 1988 1989/** 1990 * add items to Outlayer instance 1991 * @param {Array or NodeList or Element} elems 1992 * @returns {Array} items - Outlayer.Items 1993**/ 1994proto.addItems = function( elems ) { 1995 var items = this._itemize( elems ); 1996 // add items to collection 1997 if ( items.length ) { 1998 this.items = this.items.concat( items ); 1999 } 2000 return items; 2001}; 2002 2003/** 2004 * Layout newly-appended item elements 2005 * @param {Array or NodeList or Element} elems 2006 */ 2007proto.appended = function( elems ) { 2008 var items = this.addItems( elems ); 2009 if ( !items.length ) { 2010 return; 2011 } 2012 // layout and reveal just the new items 2013 this.layoutItems( items, true ); 2014 this.reveal( items ); 2015}; 2016 2017/** 2018 * Layout prepended elements 2019 * @param {Array or NodeList or Element} elems 2020 */ 2021proto.prepended = function( elems ) { 2022 var items = this._itemize( elems ); 2023 if ( !items.length ) { 2024 return; 2025 } 2026 // add items to beginning of collection 2027 var previousItems = this.items.slice(0); 2028 this.items = items.concat( previousItems ); 2029 // start new layout 2030 this._resetLayout(); 2031 this._manageStamps(); 2032 // layout new stuff without transition 2033 this.layoutItems( items, true ); 2034 this.reveal( items ); 2035 // layout previous items 2036 this.layoutItems( previousItems ); 2037}; 2038 2039/** 2040 * reveal a collection of items 2041 * @param {Array of Outlayer.Items} items 2042 */ 2043proto.reveal = function( items ) { 2044 this._emitCompleteOnItems( 'reveal', items ); 2045 if ( !items || !items.length ) { 2046 return; 2047 } 2048 var stagger = this.updateStagger(); 2049 items.forEach( function( item, i ) { 2050 item.stagger( i * stagger ); 2051 item.reveal(); 2052 }); 2053}; 2054 2055/** 2056 * hide a collection of items 2057 * @param {Array of Outlayer.Items} items 2058 */ 2059proto.hide = function( items ) { 2060 this._emitCompleteOnItems( 'hide', items ); 2061 if ( !items || !items.length ) { 2062 return; 2063 } 2064 var stagger = this.updateStagger(); 2065 items.forEach( function( item, i ) { 2066 item.stagger( i * stagger ); 2067 item.hide(); 2068 }); 2069}; 2070 2071/** 2072 * reveal item elements 2073 * @param {Array}, {Element}, {NodeList} items 2074 */ 2075proto.revealItemElements = function( elems ) { 2076 var items = this.getItems( elems ); 2077 this.reveal( items ); 2078}; 2079 2080/** 2081 * hide item elements 2082 * @param {Array}, {Element}, {NodeList} items 2083 */ 2084proto.hideItemElements = function( elems ) { 2085 var items = this.getItems( elems ); 2086 this.hide( items ); 2087}; 2088 2089/** 2090 * get Outlayer.Item, given an Element 2091 * @param {Element} elem 2092 * @param {Function} callback 2093 * @returns {Outlayer.Item} item 2094 */ 2095proto.getItem = function( elem ) { 2096 // loop through items to get the one that matches 2097 for ( var i=0; i < this.items.length; i++ ) { 2098 var item = this.items[i]; 2099 if ( item.element == elem ) { 2100 // return item 2101 return item; 2102 } 2103 } 2104}; 2105 2106/** 2107 * get collection of Outlayer.Items, given Elements 2108 * @param {Array} elems 2109 * @returns {Array} items - Outlayer.Items 2110 */ 2111proto.getItems = function( elems ) { 2112 elems = utils.makeArray( elems ); 2113 var items = []; 2114 elems.forEach( function( elem ) { 2115 var item = this.getItem( elem ); 2116 if ( item ) { 2117 items.push( item ); 2118 } 2119 }, this ); 2120 2121 return items; 2122}; 2123 2124/** 2125 * remove element(s) from instance and DOM 2126 * @param {Array or NodeList or Element} elems 2127 */ 2128proto.remove = function( elems ) { 2129 var removeItems = this.getItems( elems ); 2130 2131 this._emitCompleteOnItems( 'remove', removeItems ); 2132 2133 // bail if no items to remove 2134 if ( !removeItems || !removeItems.length ) { 2135 return; 2136 } 2137
vendor: 3,919 bytes, lines 2138-2305
2138 removeItems.forEach( function( item ) { 2139 item.remove(); 2140 // remove item from collection 2141 utils.removeFrom( this.items, item ); 2142 }, this ); 2143}; 2144 2145// ----- destroy ----- // 2146 2147// remove and disable Outlayer instance 2148proto.destroy = function() { 2149 // clean up dynamic styles 2150 var style = this.element.style; 2151 style.height = ''; 2152 style.position = ''; 2153 style.width = ''; 2154 // destroy items 2155 this.items.forEach( function( item ) { 2156 item.destroy(); 2157 }); 2158 2159 this.unbindResize(); 2160 2161 var id = this.element.outlayerGUID; 2162 delete instances[ id ]; // remove reference to instance by id 2163 delete this.element.outlayerGUID; 2164 // remove data for jQuery 2165 if ( jQuery ) { 2166 jQuery.removeData( this.element, this.constructor.namespace ); 2167 } 2168 2169}; 2170 2171// -------------------------- data -------------------------- // 2172 2173/** 2174 * get Outlayer instance from element 2175 * @param {Element} elem 2176 * @returns {Outlayer} 2177 */ 2178Outlayer.data = function( elem ) { 2179 elem = utils.getQueryElement( elem ); 2180 var id = elem && elem.outlayerGUID; 2181 return id && instances[ id ]; 2182}; 2183 2184 2185// -------------------------- create Outlayer class -------------------------- // 2186 2187/** 2188 * create a layout class 2189 * @param {String} namespace 2190 */ 2191Outlayer.create = function( namespace, options ) { 2192 // sub-class Outlayer 2193 var Layout = subclass( Outlayer ); 2194 // apply new options and compatOptions 2195 Layout.defaults = utils.extend( {}, Outlayer.defaults ); 2196 utils.extend( Layout.defaults, options ); 2197 Layout.compatOptions = utils.extend( {}, Outlayer.compatOptions ); 2198 2199 Layout.namespace = namespace; 2200 2201 Layout.data = Outlayer.data; 2202 2203 // sub-class Item 2204 Layout.Item = subclass( Item ); 2205 2206 // -------------------------- declarative -------------------------- // 2207 2208 utils.htmlInit( Layout, namespace ); 2209 2210 // -------------------------- jQuery bridge -------------------------- // 2211 2212 // make into jQuery plugin 2213 if ( jQuery && jQuery.bridget ) { 2214 jQuery.bridget( namespace, Layout ); 2215 } 2216 2217 return Layout; 2218}; 2219 2220function subclass( Parent ) { 2221 function SubClass() { 2222 Parent.apply( this, arguments ); 2223 } 2224 2225 SubClass.prototype = Object.create( Parent.prototype ); 2226 SubClass.prototype.constructor = SubClass; 2227 2228 return SubClass; 2229} 2230 2231// ----- helpers ----- // 2232 2233// how many milliseconds are in each unit 2234var msUnits = { 2235 ms: 1, 2236 s: 1000 2237}; 2238 2239// munge time-like parameter into millisecond number 2240// '0.4s' -> 40 2241function getMilliseconds( time ) { 2242 if ( typeof time == 'number' ) { 2243 return time; 2244 } 2245 var matches = time.match( /(^\d*\.?\d*)(\w*)/ ); 2246 var num = matches && matches[1]; 2247 var unit = matches && matches[2]; 2248 if ( !num.length ) { 2249 return 0; 2250 } 2251 num = parseFloat( num ); 2252 var mult = msUnits[ unit ] || 1; 2253 return num * mult; 2254} 2255 2256// ----- fin ----- // 2257 2258// back in global 2259Outlayer.Item = Item; 2260 2261return Outlayer; 2262 2263})); 2264 2265/*! 2266 * Masonry v4.2.2 2267 * Cascading grid layout library 2268 * https://masonry.desandro.com 2269 * MIT License 2270 * by David DeSandro 2271 */ 2272 2273( function( window, factory ) { 2274 // universal module definition 2275 /* jshint strict: false */ /*globals define, module, require */ 2276 if ( typeof define == 'function' && define.amd ) { 2277 // AMD 2278 define( [ 2279 'outlayer/outlayer', 2280 'get-size/get-size' 2281 ], 2282 factory ); 2283 } else if ( typeof module == 'object' && module.exports ) { 2284 // CommonJS 2285 module.exports = factory( 2286 require('outlayer'), 2287 require('get-size') 2288 ); 2289 } else { 2290 // browser global 2291 window.Masonry = factory( 2292 window.Outlayer, 2293 window.getSize 2294 ); 2295 } 2296 2297}( window, function factory( Outlayer, getSize ) { 2298 2299 2300 2301// -------------------------- masonryDefinition -------------------------- // 2302 2303 // create an Outlayer layout class 2304 var Masonry = Outlayer.create('masonry'); 2305 // isFitWidth -> fitWidth
vendor: 6,711 bytes, lines 2306-2504
2306 Masonry.compatOptions.fitWidth = 'isFitWidth'; 2307 2308 var proto = Masonry.prototype; 2309 2310 proto._resetLayout = function() { 2311 this.getSize(); 2312 this._getMeasurement( 'columnWidth', 'outerWidth' ); 2313 this._getMeasurement( 'gutter', 'outerWidth' ); 2314 this.measureColumns(); 2315 2316 // reset column Y 2317 this.colYs = []; 2318 for ( var i=0; i < this.cols; i++ ) { 2319 this.colYs.push( 0 ); 2320 } 2321 2322 this.maxY = 0; 2323 this.horizontalColIndex = 0; 2324 }; 2325 2326 proto.measureColumns = function() { 2327 this.getContainerWidth(); 2328 // if columnWidth is 0, default to outerWidth of first item 2329 if ( !this.columnWidth ) { 2330 var firstItem = this.items[0]; 2331 var firstItemElem = firstItem && firstItem.element; 2332 // columnWidth fall back to item of first element 2333 this.columnWidth = firstItemElem && getSize( firstItemElem ).outerWidth || 2334 // if first elem has no width, default to size of container 2335 this.containerWidth; 2336 } 2337 2338 var columnWidth = this.columnWidth += this.gutter; 2339 2340 // calculate columns 2341 var containerWidth = this.containerWidth + this.gutter; 2342 var cols = containerWidth / columnWidth; 2343 // fix rounding errors, typically with gutters 2344 var excess = columnWidth - containerWidth % columnWidth; 2345 // if overshoot is less than a pixel, round up, otherwise floor it 2346 var mathMethod = excess && excess < 1 ? 'round' : 'floor'; 2347 cols = Math[ mathMethod ]( cols ); 2348 this.cols = Math.max( cols, 1 ); 2349 }; 2350 2351 proto.getContainerWidth = function() { 2352 // container is parent if fit width 2353 var isFitWidth = this._getOption('fitWidth'); 2354 var container = isFitWidth ? this.element.parentNode : this.element; 2355 // check that this.size and size are there 2356 // IE8 triggers resize on body size change, so they might not be 2357 var size = getSize( container ); 2358 this.containerWidth = size && size.innerWidth; 2359 }; 2360 2361 proto._getItemLayoutPosition = function( item ) { 2362 item.getSize(); 2363 // how many columns does this brick span 2364 var remainder = item.size.outerWidth % this.columnWidth; 2365 var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; 2366 // round if off by 1 pixel, otherwise use ceil 2367 var colSpan = Math[ mathMethod ]( item.size.outerWidth / this.columnWidth ); 2368 colSpan = Math.min( colSpan, this.cols ); 2369 // use horizontal or top column position 2370 var colPosMethod = this.options.horizontalOrder ? 2371 '_getHorizontalColPosition' : '_getTopColPosition'; 2372 var colPosition = this[ colPosMethod ]( colSpan, item ); 2373 // position the brick 2374 var position = { 2375 x: this.columnWidth * colPosition.col, 2376 y: colPosition.y 2377 }; 2378 // apply setHeight to necessary columns 2379 var setHeight = colPosition.y + item.size.outerHeight; 2380 var setMax = colSpan + colPosition.col; 2381 for ( var i = colPosition.col; i < setMax; i++ ) { 2382 this.colYs[i] = setHeight; 2383 } 2384 2385 return position; 2386 }; 2387 2388 proto._getTopColPosition = function( colSpan ) { 2389 var colGroup = this._getTopColGroup( colSpan ); 2390 // get the minimum Y value from the columns 2391 var minimumY = Math.min.apply( Math, colGroup ); 2392 2393 return { 2394 col: colGroup.indexOf( minimumY ), 2395 y: minimumY, 2396 }; 2397 }; 2398 2399 /** 2400 * @param {Number} colSpan - number of columns the element spans 2401 * @returns {Array} colGroup 2402 */ 2403 proto._getTopColGroup = function( colSpan ) { 2404 if ( colSpan < 2 ) { 2405 // if brick spans only one column, use all the column Ys 2406 return this.colYs; 2407 } 2408 2409 var colGroup = []; 2410 // how many different places could this brick fit horizontally 2411 var groupCount = this.cols + 1 - colSpan; 2412 // for each group potential horizontal position 2413 for ( var i = 0; i < groupCount; i++ ) { 2414 colGroup[i] = this._getColGroupY( i, colSpan ); 2415 } 2416 return colGroup; 2417 }; 2418 2419 proto._getColGroupY = function( col, colSpan ) { 2420 if ( colSpan < 2 ) { 2421 return this.colYs[ col ]; 2422 } 2423 // make an array of colY values for that one group 2424 var groupColYs = this.colYs.slice( col, col + colSpan ); 2425 // and get the max value of the array 2426 return Math.max.apply( Math, groupColYs ); 2427 }; 2428 2429 // get column position based on horizontal index. #873 2430 proto._getHorizontalColPosition = function( colSpan, item ) { 2431 var col = this.horizontalColIndex % this.cols; 2432 var isOver = colSpan > 1 && col + colSpan > this.cols; 2433 // shift to next row if item can't fit on current row 2434 col = isOver ? 0 : col; 2435 // don't let zero-size items take up space 2436 var hasSize = item.size.outerWidth && item.size.outerHeight; 2437 this.horizontalColIndex = hasSize ? col + colSpan : this.horizontalColIndex; 2438 2439 return { 2440 col: col, 2441 y: this._getColGroupY( col, colSpan ), 2442 }; 2443 }; 2444 2445 proto._manageStamp = function( stamp ) { 2446 var stampSize = getSize( stamp ); 2447 var offset = this._getElementOffset( stamp ); 2448 // get the columns that this stamp affects 2449 var isOriginLeft = this._getOption('originLeft'); 2450 var firstX = isOriginLeft ? offset.left : offset.right; 2451 var lastX = firstX + stampSize.outerWidth; 2452 var firstCol = Math.floor( firstX / this.columnWidth ); 2453 firstCol = Math.max( 0, firstCol ); 2454 var lastCol = Math.floor( lastX / this.columnWidth ); 2455 // lastCol should not go over if multiple of columnWidth #425 2456 lastCol -= lastX % this.columnWidth ? 0 : 1; 2457 lastCol = Math.min( this.cols - 1, lastCol ); 2458 // set colYs to bottom of the stamp 2459 2460 var isOriginTop = this._getOption('originTop'); 2461 var stampMaxY = ( isOriginTop ? offset.top : offset.bottom ) + 2462 stampSize.outerHeight; 2463 for ( var i = firstCol; i <= lastCol; i++ ) { 2464 this.colYs[i] = Math.max( stampMaxY, this.colYs[i] ); 2465 } 2466 }; 2467 2468 proto._getContainerSize = function() { 2469 this.maxY = Math.max.apply( Math, this.colYs ); 2470 var size = { 2471 height: this.maxY 2472 }; 2473 2474 if ( this._getOption('fitWidth') ) { 2475 size.width = this._getContainerFitWidth(); 2476 } 2477 2478 return size; 2479 }; 2480 2481 proto._getContainerFitWidth = function() { 2482 var unusedCols = 0; 2483 // count unused columns 2484 var i = this.cols; 2485 while ( --i ) { 2486 if ( this.colYs[i] !== 0 ) { 2487 break; 2488 } 2489 unusedCols++; 2490 } 2491 // fit container to columns that have been used 2492 return ( this.cols - unusedCols ) * this.columnWidth - this.gutter; 2493 }; 2494 2495 proto.needsResizeLayout = function() { 2496 var previousWidth = this.containerWidth; 2497 this.getContainerWidth(); 2498 return previousWidth != this.containerWidth; 2499 }; 2500 2501 return Masonry; 2502 2503})); 2504
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.