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