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