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