1 2( function ($) { 3/*! 4 * Packery PACKAGED v1.4.3 5 * bin-packing layout library 6 * 7 * Licensed GPLv3 for open source use 8 * or Flickity Commercial License for commercial use 9 * 10 * http://packery.metafizzy.co 11 * Copyright 2015 Metafizzy 12 */ 13 14/** 15 * Bridget makes jQuery widgets 16 * v1.1.0 17 * MIT license 18 */ 19 20( function( window ) { 21 22 23 24// -------------------------- utils -------------------------- // 25 26var slice = Array.prototype.slice; 27 28function noop() {} 29 30// -------------------------- definition -------------------------- // 31 32function defineBridget( $ ) { 33 34// bail if no jQuery 35if ( !$ ) { 36 return; 37} 38 39// -------------------------- addOptionMethod -------------------------- // 40 41/** 42 * adds option method -> $().plugin('option', {...}) 43 * @param {Function} PluginClass - constructor class 44 */ 45function addOptionMethod( PluginClass ) { 46 // don't overwrite original option method 47 if ( PluginClass.prototype.option ) { 48 return; 49 } 50 51 // option setter 52 PluginClass.prototype.option = function( opts ) { 53 // bail out if not an object 54 if ( !$.isPlainObject( opts ) ){ 55 return; 56 } 57 this.options = $.extend( true, this.options, opts ); 58 }; 59} 60 61// -------------------------- plugin bridge -------------------------- // 62 63// helper function for logging errors 64// $.error breaks jQuery chaining 65var logError = typeof console === 'undefined' ? noop : 66 function( message ) { 67 console.error( message ); 68 }; 69 70/** 71 * jQuery plugin bridge, access methods like $elem.plugin('method') 72 * @param {String} namespace - plugin name 73 * @param {Function} PluginClass - constructor class 74 */ 75function bridge( namespace, PluginClass ) { 76 // add to jQuery fn namespace 77 $.fn[ namespace ] = function( options ) { 78 if ( typeof options === 'string' ) { 79 // call plugin method when first argument is a string 80 // get arguments for method 81 var args = slice.call( arguments, 1 ); 82 83 for ( var i=0, len = this.length; i < len; i++ ) { 84 var elem = this[i]; 85 var instance = $.data( elem, namespace ); 86 if ( !instance ) { 87 logError( "cannot call methods on " + namespace + " prior to initialization; " + 88 "attempted to call '" + options + "'" ); 89 continue; 90 } 91 if ( !$.isFunction( instance[options] ) || options.charAt(0) === '_' ) { 92 logError( "no such method '" + options + "' for " + namespace + " instance" ); 93 continue; 94 } 95 96 // trigger method with arguments 97 var returnValue = instance[ options ].apply( instance, args ); 98 99 // break look and return first value if provided 100 if ( returnValue !== undefined ) { 101 return returnValue; 102 } 103 } 104 // return this if no return value 105 return this; 106 } else { 107 return this.each( function() { 108 var instance = $.data( this, namespace ); 109 if ( instance ) { 110 // apply options & init 111 instance.option( options ); 112 instance._init(); 113 } else { 114 // initialize new instance 115 instance = new PluginClass( this, options ); 116 $.data( this, namespace, instance ); 117 } 118 }); 119 } 120 }; 121 122} 123 124// -------------------------- bridget -------------------------- // 125 126/** 127 * converts a Prototypical class into a proper jQuery plugin 128 * the class must have a ._init method 129 * @param {String} namespace - plugin name, used in $().pluginName 130 * @param {Function} PluginClass - constructor class 131 */ 132$.bridget = function( namespace, PluginClass ) { 133 addOptionMethod( PluginClass ); 134 bridge( namespace, PluginClass ); 135}; 136 137return $.bridget; 138 139} 140 141// transport 142if ( typeof define === 'function' && define.amd ) { 143 // AMD 144 define( 'jquery-bridget/jquery.bridget',[ 'jquery' ], defineBridget ); 145} else if ( typeof exports === 'object' ) { 146 defineBridget( require('jquery') ); 147} else { 148 // get jquery from browser global 149 defineBridget( window.jQuery ); 150} 151 152})( window ); 153 154/*! 155 * classie v1.0.1 156 * class helper functions 157 * from bonzo https://github.com/ded/bonzo 158 * MIT license 159 * 160 * classie.has( elem, 'my-class' ) -> true/false 161 * classie.add( elem, 'my-new-class' ) 162 * classie.remove( elem, 'my-unwanted-class' ) 163 * classie.toggle( elem, 'my-class' ) 164 */ 165 166/*jshint browser: true, strict: true, undef: true, unused: true */ 167/*global define: false, module: false */ 168 169( function( window ) { 170 171 172 173// class helper functions from bonzo https://github.com/ded/bonzo 174 175function classReg( className ) { 176 return new RegExp("(^|\\s+)" + className + "(\\s+|$)"); 177} 178 179// classList support for class management 180// altho to be fair, the api sucks because it won't accept multiple classes at once 181var hasClass, addClass, removeClass; 182 183if ( 'classList' in document.documentElement ) { 184 hasClass = function( elem, c ) { 185 return elem.classList.contains( c ); 186 }; 187 addClass = function( elem, c ) { 188 elem.classList.add( c ); 189 }; 190 removeClass = function( elem, c ) { 191 elem.classList.remove( c ); 192 }; 193} 194else { 195 hasClass = function( elem, c ) { 196 return classReg( c ).test( elem.className ); 197 }; 198 addClass = function( elem, c ) { 199 if ( !hasClass( elem, c ) ) { 200 elem.className = elem.className + ' ' + c; 201 } 202 }; 203 removeClass = function( elem, c ) { 204 elem.className = elem.className.replace( classReg( c ), ' ' ); 205 }; 206} 207 208function toggleClass( elem, c ) { 209 var fn = hasClass( elem, c ) ? removeClass : addClass; 210 fn( elem, c ); 211} 212 213var classie = { 214 // full names 215 hasClass: hasClass, 216 addClass: addClass, 217 removeClass: removeClass, 218 toggleClass: toggleClass, 219 // short names 220 has: hasClass, 221 add: addClass, 222 remove: removeClass, 223 toggle: toggleClass 224}; 225 226// transport 227if ( typeof define === 'function' && define.amd ) { 228 // AMD 229 define( 'classie/classie',classie ); 230} else if ( typeof exports === 'object' ) { 231 // CommonJS 232 module.exports = classie; 233} else { 234 // browser global 235 window.classie = classie; 236} 237 238})( window ); 239 240/*! 241 * getStyleProperty v1.0.4 242 * original by kangax 243 * http://perfectionkills.com/feature-testing-css-properties/ 244 * MIT license 245 */ 246 247/*jshint browser: true, strict: true, undef: true */ 248/*global define: false, exports: false, module: false */ 249 250( function( window ) { 251 252 253 254var prefixes = 'Webkit Moz ms Ms O'.split(' '); 255var docElemStyle = document.documentElement.style; 256 257function getStyleProperty( propName ) { 258 if ( !propName ) { 259 return; 260 } 261 262 // test standard property first 263 if ( typeof docElemStyle[ propName ] === 'string' ) { 264 return propName; 265 } 266 267 // capitalize 268 propName = propName.charAt(0).toUpperCase() + propName.slice(1); 269 270 // test vendor specific properties 271 var prefixed; 272 for ( var i=0, len = prefixes.length; i < len; i++ ) { 273 prefixed = prefixes[i] + propName; 274 if ( typeof docElemStyle[ prefixed ] === 'string' ) { 275 return prefixed; 276 } 277 } 278} 279 280// transport 281if ( typeof define === 'function' && define.amd ) { 282 // AMD 283 define( 'get-style-property/get-style-property',[],function() { 284 return getStyleProperty; 285 }); 286} else if ( typeof exports === 'object' ) { 287 // CommonJS for Component 288 module.exports = getStyleProperty; 289} else { 290 // browser global 291 window.getStyleProperty = getStyleProperty; 292} 293 294})( window ); 295 296/*! 297 * getSize v1.2.2 298 * measure size of elements 299 * MIT license 300 */ 301 302/*jshint browser: true, strict: true, undef: true, unused: true */ 303/*global define: false, exports: false, require: false, module: false, console: false */ 304 305( function( window, undefined ) { 306 307 308 309// -------------------------- helpers -------------------------- // 310 311// get a number from a string, not a percentage 312function getStyleSize( value ) { 313 var num = parseFloat( value ); 314 // not a percent like '100%', and a number 315 var isValid = value.indexOf('%') === -1 && !isNaN( num ); 316 return isValid && num; 317} 318 319function noop() {} 320 321var logError = typeof console === 'undefined' ? noop : 322 function( message ) { 323 console.error( message ); 324 }; 325 326// -------------------------- measurements -------------------------- // 327 328var measurements = [ 329 'paddingLeft', 330 'paddingRight', 331 'paddingTop', 332 'paddingBottom', 333 'marginLeft', 334 'marginRight', 335 'marginTop', 336 'marginBottom', 337 'borderLeftWidth', 338 'borderRightWidth', 339 'borderTopWidth', 340 'borderBottomWidth' 341]; 342 343function getZeroSize() { 344 var size = { 345 width: 0, 346 height: 0, 347 innerWidth: 0, 348 innerHeight: 0, 349 outerWidth: 0, 350 outerHeight: 0 351 }; 352 for ( var i=0, len = measurements.length; i < len; i++ ) { 353 var measurement = measurements[i]; 354 size[ measurement ] = 0; 355 } 356 return size; 357} 358 359 360 361function defineGetSize( getStyleProperty ) { 362 363// -------------------------- setup -------------------------- // 364 365var isSetup = false;
366 367var getStyle, boxSizingProp, isBoxSizeOuter; 368 369/** 370 * setup vars and functions 371 * do it on initial getSize(), rather than on script load 372 * For Firefox bug https://bugzilla.mozilla.org/show_bug.cgi?id=548397 373 */ 374function setup() { 375 // setup once 376 if ( isSetup ) { 377 return; 378 } 379 isSetup = true; 380 381 var getComputedStyle = window.getComputedStyle; 382 getStyle = ( function() { 383 var getStyleFn = getComputedStyle ? 384 function( elem ) { 385 return getComputedStyle( elem, null ); 386 } : 387 function( elem ) { 388 return elem.currentStyle; 389 }; 390 391 return function getStyle( elem ) { 392 var style = getStyleFn( elem ); 393 if ( !style ) { 394 logError( 'Style returned ' + style + 395 '. Are you running this code in a hidden iframe on Firefox? ' + 396 'See http://bit.ly/getsizebug1' ); 397 } 398 return style; 399 }; 400 })(); 401 402 // -------------------------- box sizing -------------------------- // 403 404 boxSizingProp = getStyleProperty('boxSizing'); 405 406 /** 407 * WebKit measures the outer-width on style.width on border-box elems 408 * IE & Firefox measures the inner-width 409 */ 410 if ( boxSizingProp ) { 411 var div = document.createElement('div'); 412 div.style.width = '200px'; 413 div.style.padding = '1px 2px 3px 4px'; 414 div.style.borderStyle = 'solid'; 415 div.style.borderWidth = '1px 2px 3px 4px'; 416 div.style[ boxSizingProp ] = 'border-box'; 417 418 var body = document.body || document.documentElement; 419 body.appendChild( div ); 420 var style = getStyle( div ); 421 422 isBoxSizeOuter = getStyleSize( style.width ) === 200; 423 body.removeChild( div ); 424 } 425 426} 427 428// -------------------------- getSize -------------------------- // 429 430function getSize( elem ) { 431 setup(); 432 433 // use querySeletor if elem is string 434 if ( typeof elem === 'string' ) { 435 elem = document.querySelector( elem ); 436 } 437 438 // do not proceed on non-objects 439 if ( !elem || typeof elem !== 'object' || !elem.nodeType ) { 440 return; 441 } 442 443 var style = getStyle( elem ); 444 445 // if hidden, everything is 0 446 if ( style.display === 'none' ) { 447 return getZeroSize(); 448 } 449 450 var size = {}; 451 size.width = elem.offsetWidth; 452 size.height = elem.offsetHeight; 453 454 var isBorderBox = size.isBorderBox = !!( boxSizingProp && 455 style[ boxSizingProp ] && style[ boxSizingProp ] === 'border-box' ); 456 457 // get all measurements 458 for ( var i=0, len = measurements.length; i < len; i++ ) { 459 var measurement = measurements[i]; 460 var value = style[ measurement ]; 461 value = mungeNonPixel( elem, value ); 462 var num = parseFloat( value ); 463 // any 'auto', 'medium' value will be 0 464 size[ measurement ] = !isNaN( num ) ? num : 0; 465 } 466 467 var paddingWidth = size.paddingLeft + size.paddingRight; 468 var paddingHeight = size.paddingTop + size.paddingBottom; 469 var marginWidth = size.marginLeft + size.marginRight; 470 var marginHeight = size.marginTop + size.marginBottom; 471 var borderWidth = size.borderLeftWidth + size.borderRightWidth; 472 var borderHeight = size.borderTopWidth + size.borderBottomWidth; 473 474 var isBorderBoxSizeOuter = isBorderBox && isBoxSizeOuter; 475 476 // overwrite width and height if we can get it from style 477 var styleWidth = getStyleSize( style.width ); 478 if ( styleWidth !== false ) { 479 size.width = styleWidth + 480 // add padding and border unless it's already including it 481 ( isBorderBoxSizeOuter ? 0 : paddingWidth + borderWidth ); 482 } 483 484 var styleHeight = getStyleSize( style.height ); 485 if ( styleHeight !== false ) { 486 size.height = styleHeight + 487 // add padding and border unless it's already including it 488 ( isBorderBoxSizeOuter ? 0 : paddingHeight + borderHeight ); 489 } 490 491 size.innerWidth = size.width - ( paddingWidth + borderWidth ); 492 size.innerHeight = size.height - ( paddingHeight + borderHeight ); 493 494 size.outerWidth = size.width + marginWidth; 495 size.outerHeight = size.height + marginHeight; 496 497 return size; 498} 499 500// IE8 returns percent values, not pixels 501// taken from jQuery's curCSS 502function mungeNonPixel( elem, value ) { 503 // IE8 and has percent value 504 if ( window.getComputedStyle || value.indexOf('%') === -1 ) { 505 return value; 506 } 507 var style = elem.style; 508 // Remember the original values 509 var left = style.left; 510 var rs = elem.runtimeStyle; 511 var rsLeft = rs && rs.left; 512 513 // Put in the new values to get a computed value out 514 if ( rsLeft ) { 515 rs.left = elem.currentStyle.left; 516 } 517 style.left = value; 518 value = style.pixelLeft; 519 520 // Revert the changed values 521 style.left = left; 522 if ( rsLeft ) { 523 rs.left = rsLeft; 524 } 525 526 return value; 527} 528 529return getSize; 530 531} 532 533// transport 534if ( typeof define === 'function' && define.amd ) { 535 // AMD for RequireJS 536 define( 'get-size/get-size',[ 'get-style-property/get-style-property' ], defineGetSize ); 537} else if ( typeof exports === 'object' ) { 538 // CommonJS for Component 539 module.exports = defineGetSize( require('desandro-get-style-property') ); 540} else { 541 // browser global 542 window.getSize = defineGetSize( window.getStyleProperty ); 543} 544 545})( window ); 546 547/*! 548 * eventie v1.0.6 549 * event binding helper 550 * eventie.bind( elem, 'click', myFn ) 551 * eventie.unbind( elem, 'click', myFn ) 552 * MIT license 553 */ 554 555/*jshint browser: true, undef: true, unused: true */ 556/*global define: false, module: false */ 557 558( function( window ) { 559 560 561 562var docElem = document.documentElement; 563 564var bind = function() {}; 565 566function getIEEvent( obj ) { 567 var event = window.event; 568 // add event.target 569 event.target = event.target || event.srcElement || obj; 570 return event; 571} 572 573if ( docElem.addEventListener ) { 574 bind = function( obj, type, fn ) { 575 obj.addEventListener( type, fn, false ); 576 }; 577} else if ( docElem.attachEvent ) { 578 bind = function( obj, type, fn ) { 579 obj[ type + fn ] = fn.handleEvent ? 580 function() { 581 var event = getIEEvent( obj ); 582 fn.handleEvent.call( fn, event ); 583 } : 584 function() { 585 var event = getIEEvent( obj ); 586 fn.call( obj, event ); 587 }; 588 obj.attachEvent( "on" + type, obj[ type + fn ] ); 589 }; 590} 591 592var unbind = function() {}; 593 594if ( docElem.removeEventListener ) { 595 unbind = function( obj, type, fn ) { 596 obj.removeEventListener( type, fn, false ); 597 }; 598} else if ( docElem.detachEvent ) { 599 unbind = function( obj, type, fn ) { 600 obj.detachEvent( "on" + type, obj[ type + fn ] ); 601 try { 602 delete obj[ type + fn ]; 603 } catch ( err ) { 604 // can't delete window object properties 605 obj[ type + fn ] = undefined; 606 } 607 }; 608} 609 610var eventie = { 611 bind: bind, 612 unbind: unbind 613}; 614 615// ----- module definition ----- // 616 617if ( typeof define === 'function' && define.amd ) { 618 // AMD 619 define( 'eventie/eventie',eventie ); 620} else if ( typeof exports === 'object' ) { 621 // CommonJS 622 module.exports = eventie; 623} else { 624 // browser global 625 window.eventie = eventie; 626} 627 628})( window ); 629 630/*! 631 * EventEmitter v4.2.11 - git.io/ee 632 * Unlicense - http://unlicense.org/ 633 * Oliver Caldwell - http://oli.me.uk/ 634 * @preserve 635 */ 636 637;(function () { 638 639 640 /** 641 * Class for managing events. 642 * Can be extended to provide event functionality in other classes. 643 * 644 * @class EventEmitter Manages event registering and emitting. 645 */ 646 function EventEmitter() {} 647 648 // Shortcuts to improve speed and size 649 var proto = EventEmitter.prototype; 650 var exports = this; 651 var originalGlobalValue = exports.EventEmitter; 652 653 /** 654 * Finds the index of the listener for the event in its storage array. 655 * 656 * @param {Function[]} listeners Array of listeners to search through. 657 * @param {Function} listener Method to look for. 658 * @return {Number} Index of the specified listener, -1 if not found 659 * @api private 660 */ 661 function indexOfListener(listeners, listener) { 662 var i = listeners.length; 663 while (i--) { 664 if (listeners[i].listener === listener) { 665 return i; 666 } 667 } 668 669 return -1; 670 } 671 672 /** 673 * Alias a method while keeping the context correct, to allow for over
vendor: 16,384 bytes, lines 673-1076
673writing of target method. 674 * 675 * @param {String} name The name of the target method. 676 * @return {Function} The aliased method 677 * @api private 678 */ 679 function alias(name) { 680 return function aliasClosure() { 681 return this[name].apply(this, arguments); 682 }; 683 } 684 685 /** 686 * Returns the listener array for the specified event. 687 * Will initialise the event object and listener arrays if required. 688 * Will return an object if you use a regex search. The object contains keys for each matched event. So /ba[rz]/ might return an object containing bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. 689 * Each property in the object response is an array of listener functions. 690 * 691 * @param {String|RegExp} evt Name of the event to return the listeners from. 692 * @return {Function[]|Object} All listener functions for the event. 693 */ 694 proto.getListeners = function getListeners(evt) { 695 var events = this._getEvents(); 696 var response; 697 var key; 698 699 // Return a concatenated array of all matching events if 700 // the selector is a regular expression. 701 if (evt instanceof RegExp) { 702 response = {}; 703 for (key in events) { 704 if (events.hasOwnProperty(key) && evt.test(key)) { 705 response[key] = events[key]; 706 } 707 } 708 } 709 else { 710 response = events[evt] || (events[evt] = []); 711 } 712 713 return response; 714 }; 715 716 /** 717 * Takes a list of listener objects and flattens it into a list of listener functions. 718 * 719 * @param {Object[]} listeners Raw listener objects. 720 * @return {Function[]} Just the listener functions. 721 */ 722 proto.flattenListeners = function flattenListeners(listeners) { 723 var flatListeners = []; 724 var i; 725 726 for (i = 0; i < listeners.length; i += 1) { 727 flatListeners.push(listeners[i].listener); 728 } 729 730 return flatListeners; 731 }; 732 733 /** 734 * Fetches the requested listeners via getListeners but will always return the results inside an object. This is mainly for internal use but others may find it useful. 735 * 736 * @param {String|RegExp} evt Name of the event to return the listeners from. 737 * @return {Object} All listener functions for an event in an object. 738 */ 739 proto.getListenersAsObject = function getListenersAsObject(evt) { 740 var listeners = this.getListeners(evt); 741 var response; 742 743 if (listeners instanceof Array) { 744 response = {}; 745 response[evt] = listeners; 746 } 747 748 return response || listeners; 749 }; 750 751 /** 752 * Adds a listener function to the specified event. 753 * The listener will not be added if it is a duplicate. 754 * If the listener returns true then it will be removed after it is called. 755 * If you pass a regular expression as the event name then the listener will be added to all events that match it. 756 * 757 * @param {String|RegExp} evt Name of the event to attach the listener to. 758 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. 759 * @return {Object} Current instance of EventEmitter for chaining. 760 */ 761 proto.addListener = function addListener(evt, listener) { 762 var listeners = this.getListenersAsObject(evt); 763 var listenerIsWrapped = typeof listener === 'object'; 764 var key; 765 766 for (key in listeners) { 767 if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { 768 listeners[key].push(listenerIsWrapped ? listener : { 769 listener: listener, 770 once: false 771 }); 772 } 773 } 774 775 return this; 776 }; 777 778 /** 779 * Alias of addListener 780 */ 781 proto.on = alias('addListener'); 782 783 /** 784 * Semi-alias of addListener. It will add a listener that will be 785 * automatically removed after its first execution. 786 * 787 * @param {String|RegExp} evt Name of the event to attach the listener to. 788 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. 789 * @return {Object} Current instance of EventEmitter for chaining. 790 */ 791 proto.addOnceListener = function addOnceListener(evt, listener) { 792 return this.addListener(evt, { 793 listener: listener, 794 once: true 795 }); 796 }; 797 798 /** 799 * Alias of addOnceListener. 800 */ 801 proto.once = alias('addOnceListener'); 802 803 /** 804 * Defines an event name. This is required if you want to use a regex to add a listener to multiple events at once. If you don't do this then how do you expect it to know what event to add to? Should it just add to every possible match for a regex? No. That is scary and bad. 805 * You need to tell it what event names should be matched by a regex. 806 * 807 * @param {String} evt Name of the event to create. 808 * @return {Object} Current instance of EventEmitter for chaining. 809 */ 810 proto.defineEvent = function defineEvent(evt) { 811 this.getListeners(evt); 812 return this; 813 }; 814 815 /** 816 * Uses defineEvent to define multiple events. 817 * 818 * @param {String[]} evts An array of event names to define. 819 * @return {Object} Current instance of EventEmitter for chaining. 820 */ 821 proto.defineEvents = function defineEvents(evts) { 822 for (var i = 0; i < evts.length; i += 1) { 823 this.defineEvent(evts[i]); 824 } 825 return this; 826 }; 827 828 /** 829 * Removes a listener function from the specified event. 830 * When passed a regular expression as the event name, it will remove the listener from all events that match it. 831 * 832 * @param {String|RegExp} evt Name of the event to remove the listener from. 833 * @param {Function} listener Method to remove from the event. 834 * @return {Object} Current instance of EventEmitter for chaining. 835 */ 836 proto.removeListener = function removeListener(evt, listener) { 837 var listeners = this.getListenersAsObject(evt); 838 var index; 839 var key; 840 841 for (key in listeners) { 842 if (listeners.hasOwnProperty(key)) { 843 index = indexOfListener(listeners[key], listener); 844 845 if (index !== -1) { 846 listeners[key].splice(index, 1); 847 } 848 } 849 } 850 851 return this; 852 }; 853 854 /** 855 * Alias of removeListener 856 */ 857 proto.off = alias('removeListener'); 858 859 /** 860 * Adds listeners in bulk using the manipulateListeners method. 861 * If you pass an object as the second argument you can add to multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. You can also pass it an event name and an array of listeners to be added. 862 * You can also pass it a regular expression to add the array of listeners to all events that match it. 863 * Yeah, this function does quite a bit. That's probably a bad thing. 864 * 865 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add to multiple events at once. 866 * @param {Function[]} [listeners] An optional array of listener functions to add. 867 * @return {Object} Current instance of EventEmitter for chaining. 868 */ 869 proto.addListeners = function addListeners(evt, listeners) { 870 // Pass through to manipulateListeners 871 return this.manipulateListeners(false, evt, listeners); 872 }; 873 874 /** 875 * Removes listeners in bulk using the manipulateListeners method. 876 * If you pass an object as the second argument you can remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. 877 * You can also pass it an event name and an array of listeners to be removed. 878 * You can also pass it a regular expression to remove the listeners from all events that match it. 879 * 880 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to remove from multiple events at once. 881 * @param {Function[]} [listeners] An optional array of listener functions to remove. 882 * @return {Object} Current instance of EventEmitter for chaining. 883 */ 884 proto.removeListeners = function removeListeners(evt, listeners) { 885 // Pass through to manipulateListeners 886 return this.manipulateListeners(true, evt, listeners); 887 }; 888 889 /** 890 * Edits listeners in bulk. The addListeners and removeListeners methods both use this to do their job. You should really use those instead, this is a little lower level. 891 * The first argument will determine if the listeners are removed (true) or added (false). 892 * If you pass an object as the second argument you can add/remove from multiple events at once. The object should contain key value pairs of events and listeners or listener arrays. 893 * You can also pass it an event name and an array of listeners to be added/removed. 894 * You can also pass it a regular expression to manipulate the listeners of all events that match it. 895 * 896 * @param {Boolean} remove True if you want to remove listeners, false if you want to add. 897 * @param {String|Object|RegExp} evt An event name if you will pass an array of listeners next. An object if you wish to add/remove from multiple events at once. 898 * @param {Function[]} [listeners] An optional array of listener functions to add/remove. 899 * @return {Object} Current instance of EventEmitter for chaining. 900 */ 901 proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { 902 var i; 903 var value; 904 var single = remove ? this.removeListener : this.addListener; 905 var multiple = remove ? this.removeListeners : this.addListeners; 906 907 // If evt is an object then pass each of its properties to this method 908 if (typeof evt === 'object' && !(evt instanceof RegExp)) { 909 for (i in evt) { 910 if (evt.hasOwnProperty(i) && (value = evt[i])) { 911 // Pass the single listener straight through to the singular method 912 if (typeof value === 'function') { 913 single.call(this, i, value); 914 } 915 else { 916 // Otherwise pass back to the multiple function 917 multiple.call(this, i, value); 918 } 919 } 920 } 921 } 922 else { 923 // So evt must be a string 924 // And listeners must be an array of listeners 925 // Loop over it and pass each one to the multiple method 926 i = listeners.length; 927 while (i--) { 928 single.call(this, evt, listeners[i]); 929 } 930 } 931 932 return this; 933 }; 934 935 /** 936 * Removes all listeners from a specified event. 937 * If you do not specify an event then all listeners will be removed. 938 * That means every event will be emptied. 939 * You can also pass a regex to remove all events that match it. 940 * 941 * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. 942 * @return {Object} Current instance of EventEmitter for chaining. 943 */ 944 proto.removeEvent = function removeEvent(evt) { 945 var type = typeof evt; 946 var events = this._getEvents(); 947 var key; 948 949 // Remove different things depending on the state of evt 950 if (type === 'string') { 951 // Remove all listeners for the specified event 952 delete events[evt]; 953 } 954 else if (evt instanceof RegExp) { 955 // Remove all events matching the regex. 956 for (key in events) { 957 if (events.hasOwnProperty(key) && evt.test(key)) { 958 delete events[key]; 959 } 960 } 961 } 962 else { 963 // Remove all listeners in all events 964 delete this._events; 965 } 966 967 return this; 968 }; 969 970 /** 971 * Alias of removeEvent. 972 * 973 * Added to mirror the node API. 974 */ 975 proto.removeAllListeners = alias('removeEvent'); 976 977 /** 978 * Emits an event of your choice. 979 * When emitted, every listener attached to that event will be executed. 980 * If you pass the optional argument array then those arguments will be passed to every listener upon execution. 981 * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. 982 * So they will not arrive within the array on the other side, they will be separate. 983 * You can also pass a regular expression to emit to all events that match it. 984 * 985 * @param {String|RegExp} evt Name of the event to emit and execute listeners for. 986 * @param {Array} [args] Optional array of arguments to be passed to each listener. 987 * @return {Object} Current instance of EventEmitter for chaining. 988 */ 989 proto.emitEvent = function emitEvent(evt, args) { 990 var listeners = this.getListenersAsObject(evt); 991 var listener; 992 var i; 993 var key; 994 var response; 995 996 for (key in listeners) { 997 if (listeners.hasOwnProperty(key)) { 998 i = listeners[key].length; 999 1000 while (i--) { 1001 // If the listener returns true then it shall be removed from the event 1002 // The function is executed either with a basic call or an apply if there is an args array 1003 listener = listeners[key][i]; 1004 1005 if (listener.once === true) { 1006 this.removeListener(evt, listener.listener); 1007 } 1008 1009 response = listener.listener.apply(this, args || []); 1010 1011 if (response === this._getOnceReturnValue()) { 1012 this.removeListener(evt, listener.listener); 1013 } 1014 } 1015 } 1016 } 1017 1018 return this; 1019 }; 1020 1021 /** 1022 * Alias of emitEvent 1023 */ 1024 proto.trigger = alias('emitEvent'); 1025 1026 /** 1027 * Subtly different from emitEvent in that it will pass its arguments on to the listeners, as opposed to taking a single array of arguments to pass on. 1028 * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. 1029 * 1030 * @param {String|RegExp} evt Name of the event to emit and execute listeners for. 1031 * @param {...*} Optional additional arguments to be passed to each listener. 1032 * @return {Object} Current instance of EventEmitter for chaining. 1033 */ 1034 proto.emit = function emit(evt) { 1035 var args = Array.prototype.slice.call(arguments, 1); 1036 return this.emitEvent(evt, args); 1037 }; 1038 1039 /** 1040 * Sets the current value to check against when executing listeners. If a 1041 * listeners return value matches the one set here then it will be removed 1042 * after execution. This value defaults to true. 1043 * 1044 * @param {*} value The new value to check for when executing listeners. 1045 * @return {Object} Current instance of EventEmitter for chaining. 1046 */ 1047 proto.setOnceReturnValue = function setOnceReturnValue(value) { 1048 this._onceReturnValue = value; 1049 return this; 1050 }; 1051 1052 /** 1053 * Fetches the current value to check against when executing listeners. If 1054 * the listeners return value matches this one then it should be removed 1055 * automatically. It will return true by default. 1056 * 1057 * @return {*|Boolean} The current value to check for or the default, true. 1058 * @api private 1059 */ 1060 proto._getOnceReturnValue = function _getOnceReturnValue() { 1061 if (this.hasOwnProperty('_onceReturnValue')) { 1062 return this._onceReturnValue; 1063 } 1064 else { 1065 return true; 1066 } 1067 }; 1068 1069 /** 1070 * Fetches the events object and creates one if required. 1071 * 1072 * @return {Object} The events storage object. 1073 * @api private 1074 */ 1075 proto._getEvents = function _getEvents() { 1076 return this._events || (this
1076._events = {}); 1077 }; 1078 1079 /** 1080 * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. 1081 * 1082 * @return {Function} Non conflicting EventEmitter class. 1083 */ 1084 EventEmitter.noConflict = function noConflict() { 1085 exports.EventEmitter = originalGlobalValue; 1086 return EventEmitter; 1087 }; 1088 1089 // Expose the class either via AMD, CommonJS or the global object 1090 if (typeof define === 'function' && define.amd) { 1091 define('eventEmitter/EventEmitter',[],function () { 1092 return EventEmitter; 1093 }); 1094 } 1095 else if (typeof module === 'object' && module.exports){ 1096 module.exports = EventEmitter; 1097 } 1098 else { 1099 exports.EventEmitter = EventEmitter; 1100 } 1101}.call(this)); 1102 1103/*! 1104 * docReady v1.0.4 1105 * Cross browser DOMContentLoaded event emitter 1106 * MIT license 1107 */ 1108 1109/*jshint browser: true, strict: true, undef: true, unused: true*/ 1110/*global define: false, require: false, module: false */ 1111 1112( function( window ) { 1113 1114 1115 1116var document = window.document; 1117// collection of functions to be triggered on ready 1118var queue = []; 1119 1120function docReady( fn ) { 1121 // throw out non-functions 1122 if ( typeof fn !== 'function' ) { 1123 return; 1124 } 1125 1126 if ( docReady.isReady ) { 1127 // ready now, hit it 1128 fn(); 1129 } else { 1130 // queue function when ready 1131 queue.push( fn ); 1132 } 1133} 1134 1135docReady.isReady = false; 1136 1137// triggered on various doc ready events 1138function onReady( event ) { 1139 // bail if already triggered or IE8 document is not ready just yet 1140 var isIE8NotReady = event.type === 'readystatechange' && document.readyState !== 'complete'; 1141 if ( docReady.isReady || isIE8NotReady ) { 1142 return; 1143 } 1144 1145 trigger(); 1146} 1147 1148function trigger() { 1149 docReady.isReady = true; 1150 // process queue 1151 for ( var i=0, len = queue.length; i < len; i++ ) { 1152 var fn = queue[i]; 1153 fn(); 1154 } 1155} 1156 1157function defineDocReady( eventie ) { 1158 // trigger ready if page is ready 1159 if ( document.readyState === 'complete' ) { 1160 trigger(); 1161 } else { 1162 // listen for events 1163 eventie.bind( document, 'DOMContentLoaded', onReady ); 1164 eventie.bind( document, 'readystatechange', onReady ); 1165 eventie.bind( window, 'load', onReady ); 1166 } 1167 1168 return docReady; 1169} 1170 1171// transport 1172if ( typeof define === 'function' && define.amd ) { 1173 // AMD 1174 define( 'doc-ready/doc-ready',[ 'eventie/eventie' ], defineDocReady ); 1175} else if ( typeof exports === 'object' ) { 1176 module.exports = defineDocReady( require('eventie') ); 1177} else { 1178 // browser global 1179 window.docReady = defineDocReady( window.eventie ); 1180} 1181 1182})( window ); 1183 1184/** 1185 * matchesSelector v1.0.3 1186 * matchesSelector( element, '.selector' ) 1187 * MIT license 1188 */ 1189 1190/*jshint browser: true, strict: true, undef: true, unused: true */ 1191/*global define: false, module: false */ 1192 1193( function( ElemProto ) { 1194 1195 1196 1197 var matchesMethod = ( function() { 1198 // check for the standard method name first 1199 if ( ElemProto.matches ) { 1200 return 'matches'; 1201 } 1202 // check un-prefixed 1203 if ( ElemProto.matchesSelector ) { 1204 return 'matchesSelector'; 1205 } 1206 // check vendor prefixes 1207 var prefixes = [ 'webkit', 'moz', 'ms', 'o' ]; 1208 1209 for ( var i=0, len = prefixes.length; i < len; i++ ) { 1210 var prefix = prefixes[i]; 1211 var method = prefix + 'MatchesSelector'; 1212 if ( ElemProto[ method ] ) { 1213 return method; 1214 } 1215 } 1216 })(); 1217 1218 // ----- match ----- // 1219 1220 function match( elem, selector ) { 1221 return elem[ matchesMethod ]( selector ); 1222 } 1223 1224 // ----- appendToFragment ----- // 1225 1226 function checkParent( elem ) { 1227 // not needed if already has parent 1228 if ( elem.parentNode ) { 1229 return; 1230 } 1231 var fragment = document.createDocumentFragment(); 1232 fragment.appendChild( elem ); 1233 } 1234 1235 // ----- query ----- // 1236 1237 // fall back to using QSA 1238 // thx @jonathantneal https://gist.github.com/3062955 1239 function query( elem, selector ) { 1240 // append to fragment if no parent 1241 checkParent( elem ); 1242 1243 // match elem with all selected elems of parent 1244 var elems = elem.parentNode.querySelectorAll( selector ); 1245 for ( var i=0, len = elems.length; i < len; i++ ) { 1246 // return true if match 1247 if ( elems[i] === elem ) { 1248 return true; 1249 } 1250 } 1251 // otherwise return false 1252 return false;
1253 } 1254 1255 // ----- matchChild ----- // 1256 1257 function matchChild( elem, selector ) { 1258 checkParent( elem ); 1259 return match( elem, selector ); 1260 } 1261 1262 // ----- matchesSelector ----- // 1263 1264 var matchesSelector; 1265 1266 if ( matchesMethod ) { 1267 // IE9 supports matchesSelector, but doesn't work on orphaned elems 1268 // check for that 1269 var div = document.createElement('div'); 1270 var supportsOrphans = match( div, 'div' ); 1271 matchesSelector = supportsOrphans ? match : matchChild; 1272 } else { 1273 matchesSelector = query; 1274 } 1275 1276 // transport 1277 if ( typeof define === 'function' && define.amd ) { 1278 // AMD 1279 define( 'matches-selector/matches-selector',[],function() { 1280 return matchesSelector; 1281 }); 1282 } else if ( typeof exports === 'object' ) { 1283 module.exports = matchesSelector; 1284 } 1285 else { 1286 // browser global 1287 window.matchesSelector = matchesSelector; 1288 } 1289 1290})( Element.prototype ); 1291 1292/** 1293 * Fizzy UI utils v1.0.1 1294 * MIT license 1295 */ 1296 1297/*jshint browser: true, undef: true, unused: true, strict: true */ 1298 1299( function( window, factory ) { 1300 /*global define: false, module: false, require: false */ 1301 1302 // universal module definition 1303 1304 if ( typeof define == 'function' && define.amd ) { 1305 // AMD 1306 define( 'fizzy-ui-utils/utils',[ 1307 'doc-ready/doc-ready', 1308 'matches-selector/matches-selector' 1309 ], function( docReady, matchesSelector ) { 1310 return factory( window, docReady, matchesSelector ); 1311 }); 1312 } else if ( typeof exports == 'object' ) { 1313 // CommonJS 1314 module.exports = factory( 1315 window, 1316 require('doc-ready'), 1317 require('desandro-matches-selector') 1318 ); 1319 } else { 1320 // browser global 1321 window.fizzyUIUtils = factory( 1322 window, 1323 window.docReady, 1324 window.matchesSelector 1325 ); 1326 } 1327 1328}( window, function factory( window, docReady, matchesSelector ) { 1329 1330 1331 1332var utils = {}; 1333 1334// ----- extend ----- // 1335 1336// extends objects 1337utils.extend = function( a, b ) { 1338 for ( var prop in b ) { 1339 a[ prop ] = b[ prop ]; 1340 } 1341 return a; 1342}; 1343 1344// ----- modulo ----- // 1345 1346utils.modulo = function( num, div ) { 1347 return ( ( num % div ) + div ) % div; 1348}; 1349 1350// ----- isArray ----- // 1351 1352var objToString = Object.prototype.toString; 1353utils.isArray = function( obj ) { 1354 return objToString.call( obj ) == '[object Array]'; 1355}; 1356 1357// ----- makeArray ----- // 1358 1359// turn element or nodeList into an array 1360utils.makeArray = function( obj ) { 1361 var ary = []; 1362 if ( utils.isArray( obj ) ) { 1363 // use object if already an array 1364 ary = obj; 1365 } else if ( obj && typeof obj.length == 'number' ) { 1366 // convert nodeList to array 1367 for ( var i=0, len = obj.length; i < len; i++ ) { 1368 ary.push( obj[i] ); 1369 } 1370 } else { 1371 // array of single index 1372 ary.push( obj ); 1373 } 1374 return ary; 1375}; 1376 1377// ----- indexOf ----- // 1378 1379// index of helper cause IE8 1380utils.indexOf = Array.prototype.indexOf ? function( ary, obj ) { 1381 return ary.indexOf( obj ); 1382 } : function( ary, obj ) { 1383 for ( var i=0, len = ary.length; i < len; i++ ) { 1384 if ( ary[i] === obj ) { 1385 return i; 1386 } 1387 } 1388 return -1; 1389 }; 1390 1391// ----- removeFrom ----- // 1392 1393utils.removeFrom = function( ary, obj ) { 1394 var index = utils.indexOf( ary, obj ); 1395 if ( index != -1 ) { 1396 ary.splice( index, 1 ); 1397 } 1398}; 1399 1400// ----- isElement ----- // 1401 1402// http://stackoverflow.com/a/384380/182183 1403utils.isElement = ( typeof HTMLElement == 'function' || typeof HTMLElement == 'object' ) ? 1404 function isElementDOM2( obj ) { 1405 return obj instanceof HTMLElement; 1406 } : 1407 function isElementQuirky( obj ) { 1408 return obj && typeof obj == 'object' && 1409 obj.nodeType == 1 && typeof obj.nodeName == 'string'; 1410 }; 1411 1412// ----- setText ----- // 1413 1414utils.setText = ( function() { 1415 var setTextProperty; 1416 function setText( elem, text ) { 1417 // only check setTextProperty once 1418 setTextProperty = setTextProperty || ( document.documentElement.textContent !== undefined ? 'textContent' : 'innerText' ); 1419 elem[ setTextProperty ] = text; 1420 } 1421 return setText; 1422})(); 1423 1424// ----- getParent ----- // 1425 1426utils.getParent = function( elem, selector ) { 1427 while ( elem != document.body ) { 1428 elem = elem.parentNode; 1429 if ( matchesSelector( elem, selector ) ) { 1430 return elem; 1431 } 1432 } 1433}; 1434 1435// ----- getQueryElement ----- // 1436 1437// use element as selector string 1438utils.getQueryElement = function( elem ) { 1439 if ( typeof elem == 'string' ) { 1440 return document.querySelector( elem ); 1441 } 1442 return elem; 1443}; 1444 1445// ----- handleEvent ----- // 1446 1447// enable .ontype to trigger from .addEventListener( elem, 'type' ) 1448utils.handleEvent = function( event ) { 1449 var method = 'on' + event.type; 1450 if ( this[ method ] ) { 1451 this[ method ]( event ); 1452 } 1453}; 1454 1455// ----- filterFindElements ----- // 1456 1457utils.filterFindElements = function( elems, selector ) { 1458 // make array of elems 1459 elems = utils.makeArray( elems ); 1460 var ffElems = []; 1461 1462 for ( var i=0, len = elems.length; i < len; i++ ) { 1463 var elem = elems[i]; 1464 // check that elem is an actual element 1465 if ( !utils.isElement( elem ) ) { 1466 continue; 1467 } 1468 // filter & find items if we have a selector 1469 if ( selector ) { 1470 // filter siblings 1471 if ( matchesSelector( elem, selector ) ) { 1472 ffElems.push( elem ); 1473 } 1474 // find children 1475 var childElems = elem.querySelectorAll( selector ); 1476 // concat childElems to filterFound array 1477 for ( var j=0, jLen = childElems.length; j < jLen; j++ ) { 1478 ffElems.push( childElems[j] ); 1479 } 1480 } else { 1481 ffElems.push( elem ); 1482 } 1483 } 1484 1485 return ffElems; 1486}; 1487 1488// ----- debounceMethod ----- // 1489 1490utils.debounceMethod = function( _class, methodName, threshold ) { 1491 // original method 1492 var method = _class.prototype[ methodName ]; 1493 var timeoutName = methodName + 'Timeout'; 1494 1495 _class.prototype[ methodName ] = function() { 1496 var timeout = this[ timeoutName ]; 1497 if ( timeout ) { 1498 clearTimeout( timeout ); 1499 } 1500 var args = arguments; 1501 1502 var _this = this; 1503 this[ timeoutName ] = setTimeout( function() { 1504 method.apply( _this, args ); 1505 delete _this[ timeoutName ]; 1506 }, threshold || 100 ); 1507 }; 1508}; 1509 1510// ----- htmlInit ----- // 1511 1512// http://jamesroberts.name/blog/2010/02/22/string-functions-for-javascript-trim-to-camel-case-to-dashed-and-to-underscore/ 1513utils.toDashed = function( str ) { 1514 return str.replace( /(.)([A-Z])/g, function( match, $1, $2 ) { 1515 return $1 + '-' + $2; 1516 }).toLowerCase(); 1517}; 1518
1519var console = window.console; 1520/** 1521 * allow user to initialize classes via .js-namespace class 1522 * htmlInit( Widget, 'widgetName' ) 1523 * options are parsed from data-namespace-option attribute 1524 */ 1525utils.htmlInit = function( WidgetClass, namespace ) { 1526 docReady( function() { 1527 var dashedNamespace = utils.toDashed( namespace ); 1528 var elems = document.querySelectorAll( '.js-' + dashedNamespace ); 1529 var dataAttr = 'data-' + dashedNamespace + '-options'; 1530 1531 for ( var i=0, len = elems.length; i < len; i++ ) { 1532 var elem = elems[i]; 1533 var attr = elem.getAttribute( dataAttr ); 1534 var options; 1535 try { 1536 options = attr && JSON.parse( attr ); 1537 } catch ( error ) { 1538 // log error, do not initialize 1539 if ( console ) { 1540 console.error( 'Error parsing ' + dataAttr + ' on ' + 1541 elem.nodeName.toLowerCase() + ( elem.id ? '#' + elem.id : '' ) + ': ' + 1542 error ); 1543 } 1544 continue; 1545 } 1546 // initialize 1547 var instance = new WidgetClass( elem, options ); 1548 // make available via $().data('layoutname') 1549 var jQuery = window.jQuery; 1550 if ( jQuery ) { 1551 jQuery.data( elem, namespace, instance ); 1552 } 1553 } 1554 }); 1555}; 1556 1557// ----- ----- // 1558 1559return utils; 1560 1561})); 1562 1563/** 1564 * Outlayer Item 1565 */ 1566 1567( function( window, factory ) { 1568 1569 // universal module definition 1570 if ( typeof define === 'function' && define.amd ) { 1571 // AMD 1572 define( 'outlayer/item',[ 1573 'eventEmitter/EventEmitter', 1574 'get-size/get-size', 1575 'get-style-property/get-style-property', 1576 'fizzy-ui-utils/utils' 1577 ], 1578 function( EventEmitter, getSize, getStyleProperty, utils ) { 1579 return factory( window, EventEmitter, getSize, getStyleProperty, utils ); 1580 } 1581 ); 1582 } else if (typeof exports === 'object') { 1583 // CommonJS 1584 module.exports = factory( 1585 window, 1586 require('wolfy87-eventemitter'), 1587 require('get-size'), 1588 require('desandro-get-style-property'), 1589 require('fizzy-ui-utils') 1590 ); 1591 } else { 1592 // browser global 1593 window.Outlayer = {}; 1594 window.Outlayer.Item = factory( 1595 window, 1596 window.EventEmitter, 1597 window.getSize, 1598 window.getStyleProperty, 1599 window.fizzyUIUtils 1600 ); 1601 } 1602 1603}( window, function factory( window, EventEmitter, getSize, getStyleProperty, utils ) { 1604 1605 1606// ----- helpers ----- // 1607 1608var getComputedStyle = window.getComputedStyle; 1609var getStyle = getComputedStyle ? 1610 function( elem ) { 1611 return getComputedStyle( elem, null ); 1612 } : 1613 function( elem ) { 1614 return elem.currentStyle; 1615 }; 1616 1617 1618function isEmptyObj( obj ) { 1619 for ( var prop in obj ) { 1620 return false; 1621 } 1622 prop = null; 1623 return true; 1624} 1625 1626// -------------------------- CSS3 support -------------------------- // 1627 1628var transitionProperty = getStyleProperty('transition'); 1629var transformProperty = getStyleProperty('transform'); 1630var supportsCSS3 = transitionProperty && transformProperty; 1631var is3d = !!getStyleProperty('perspective'); 1632 1633var transitionEndEvent = { 1634 WebkitTransition: 'webkitTransitionEnd', 1635 MozTransition: 'transitionend', 1636 OTransition: 'otransitionend', 1637 transition: 'transitionend' 1638}[ transitionProperty ]; 1639 1640// properties that could have vendor prefix 1641var prefixableProperties = [ 1642 'transform', 1643 'transition', 1644 'transitionDuration', 1645 'transitionProperty' 1646]; 1647 1648// cache all vendor properties 1649var vendorProperties = ( function() { 1650 var cache = {}; 1651 for ( var i=0, len = prefixableProperties.length; i < len; i++ ) { 1652 var prop = prefixableProperties[i]; 1653 var supportedProp = getStyleProperty( prop ); 1654 if ( supportedProp && supportedProp !== prop ) { 1655 cache[ prop ] = supportedProp; 1656 } 1657 } 1658 return cache; 1659})(); 1660 1661// -------------------------- Item -------------------------- // 1662 1663function Item( element, layout ) { 1664 if ( !element ) { 1665 return; 1666 } 1667 1668 this.element = element; 1669 // parent layout class, i.e. Masonry, Isotope, or Packery 1670 this.layout = layout; 1671 this.position = { 1672 x: 0, 1673 y: 0 1674 }; 1675 1676 this._create(); 1677} 1678 1679// inherit EventEmitter 1680utils.extend( Item.prototype, EventEmitter.prototype ); 1681 1682Item.prototype._create = function() { 1683 // transition objects 1684 this._transn = { 1685 ingProperties: {}, 1686 clean: {}, 1687 onEnd: {} 1688 }; 1689 1690 this.css({ 1691 position: 'absolute' 1692 }); 1693}; 1694 1695// trigger specified handler for event type 1696Item.prototype.handleEvent = function( event ) { 1697 var method = 'on' + event.type; 1698 if ( this[ method ] ) { 1699 this[ method ]( event ); 1700 } 1701}; 1702 1703Item.prototype.getSize = function() { 1704 this.size = getSize( this.element ); 1705}; 1706 1707/** 1708 * apply CSS styles to element 1709 * @param {Object} style 1710 */ 1711Item.prototype.css = function( style ) { 1712 var elemStyle = this.element.style; 1713 1714 for ( var prop in style ) { 1715 // use vendor property if available
1716 var supportedProp = vendorProperties[ prop ] || prop; 1717 elemStyle[ supportedProp ] = style[ prop ]; 1718 } 1719}; 1720 1721 // measure position, and sets it 1722Item.prototype.getPosition = function() { 1723 var style = getStyle( this.element ); 1724 var layoutOptions = this.layout.options; 1725 var isOriginLeft = layoutOptions.isOriginLeft; 1726 var isOriginTop = layoutOptions.isOriginTop; 1727 var xValue = style[ isOriginLeft ? 'left' : 'right' ]; 1728 var yValue = style[ isOriginTop ? 'top' : 'bottom' ]; 1729 // convert percent to pixels 1730 var layoutSize = this.layout.size; 1731 var x = xValue.indexOf('%') != -1 ? 1732 ( parseFloat( xValue ) / 100 ) * layoutSize.width : parseInt( xValue, 10 ); 1733 var y = yValue.indexOf('%') != -1 ? 1734 ( parseFloat( yValue ) / 100 ) * layoutSize.height : parseInt( yValue, 10 ); 1735 1736 // clean up 'auto' or other non-integer values 1737 x = isNaN( x ) ? 0 : x; 1738 y = isNaN( y ) ? 0 : y; 1739 // remove padding from measurement 1740 x -= isOriginLeft ? layoutSize.paddingLeft : layoutSize.paddingRight; 1741 y -= isOriginTop ? layoutSize.paddingTop : layoutSize.paddingBottom; 1742 1743 this.position.x = x; 1744 this.position.y = y; 1745}; 1746 1747// set settled position, apply padding 1748Item.prototype.layoutPosition = function() { 1749 var layoutSize = this.layout.size; 1750 var layoutOptions = this.layout.options; 1751 var style = {}; 1752 1753 // x 1754 var xPadding = layoutOptions.isOriginLeft ? 'paddingLeft' : 'paddingRight'; 1755 var xProperty = layoutOptions.isOriginLeft ? 'left' : 'right'; 1756 var xResetProperty = layoutOptions.isOriginLeft ? 'right' : 'left'; 1757 1758 var x = this.position.x + layoutSize[ xPadding ]; 1759 // set in percentage or pixels 1760 style[ xProperty ] = this.getXValue( x ); 1761 // reset other property 1762 style[ xResetProperty ] = ''; 1763 1764 // y 1765 var yPadding = layoutOptions.isOriginTop ? 'paddingTop' : 'paddingBottom'; 1766 var yProperty = layoutOptions.isOriginTop ? 'top' : 'bottom'; 1767 var yResetProperty = layoutOptions.isOriginTop ? 'bottom' : 'top'; 1768 1769 var y = this.position.y + layoutSize[ yPadding ]; 1770 // set in percentage or pixels 1771 style[ yProperty ] = this.getYValue( y ); 1772 // reset other property 1773 style[ yResetProperty ] = ''; 1774 1775 this.css( style ); 1776 this.emitEvent( 'layout', [ this ] ); 1777}; 1778 1779Item.prototype.getXValue = function( x ) { 1780 var layoutOptions = this.layout.options; 1781 return layoutOptions.percentPosition && !layoutOptions.isHorizontal ? 1782 ( ( x / this.layout.size.width ) * 100 ) + '%' : x + 'px'; 1783}; 1784 1785Item.prototype.getYValue = function( y ) { 1786 var layoutOptions = this.layout.options; 1787 return layoutOptions.percentPosition && layoutOptions.isHorizontal ? 1788 ( ( y / this.layout.size.height ) * 100 ) + '%' : y + 'px'; 1789}; 1790 1791 1792Item.prototype._transitionTo = function( x, y ) { 1793 this.getPosition(); 1794 // get current x & y from top/left 1795 var curX = this.position.x; 1796 var curY = this.position.y; 1797 1798 var compareX = parseInt( x, 10 ); 1799 var compareY = parseInt( y, 10 ); 1800 var didNotMove = compareX === this.position.x && compareY === this.position.y; 1801 1802 // save end position 1803 this.setPosition( x, y ); 1804 1805 // if did not move and not transitioning, just go to layout 1806 if ( didNotMove && !this.isTransitioning ) { 1807 this.layoutPosition(); 1808 return; 1809 } 1810 1811 var transX = x - curX; 1812 var transY = y - curY; 1813 var transitionStyle = {}; 1814 transitionStyle.transform = this.getTranslate( transX, transY ); 1815 1816 this.transition({ 1817 to: transitionStyle, 1818 onTransitionEnd: { 1819 transform: this.layoutPosition 1820 }, 1821 isCleaning: true 1822 }); 1823}; 1824 1825Item.prototype.getTranslate = function( x, y ) { 1826 // flip cooridinates if origin on right or bottom 1827 var layoutOptions = this.layout.options; 1828 x = layoutOptions.isOriginLeft ? x : -x; 1829 y = layoutOptions.isOriginTop ? y : -y; 1830 1831 if ( is3d ) { 1832 return 'translate3d(' + x + 'px, ' + y + 'px, 0)'; 1833 } 1834 1835 return 'translate(' + x + 'px, ' + y + 'px)'; 1836}; 1837 1838// non transition + transform support 1839Item.prototype.goTo = function( x, y ) { 1840 this.setPosition( x, y ); 1841 this.layoutPosition(); 1842}; 1843 1844// use transition and transforms if supported 1845Item.prototype.moveTo = supportsCSS3 ? 1846 Item.prototype._transitionTo : Item.prototype.goTo; 1847 1848Item.prototype.setPosition = function( x, y ) { 1849 this.position.x = parseInt( x, 10 ); 1850 this.position.y = parseInt( y, 10 ); 1851}; 1852 1853// ----- transition ----- // 1854 1855/** 1856 * @param {Object} style - CSS 1857 * @param {Function} onTransitionEnd 1858 */ 1859 1860// non transition, just trigger callback 1861Item.prototype._nonTransition = function( args ) { 1862 this.css( args.to ); 1863 if ( args.isCleaning ) { 1864 this._removeStyles( args.to ); 1865 } 1866 for ( var prop in args.onTransitionEnd ) { 1867 args.onTransitionEnd[ prop ].call( this ); 1868 } 1869}; 1870 1871/** 1872 * proper transition 1873 * @param {Object} args - arguments 1874 * @param {Object} to - style to transition to 1875 * @param {Object} from - style to start transition from 1876 * @param {Boolean} isCleaning - removes transition styles after transition 1877 * @param {Function} onTransitionEnd - callback 1878 */ 1879Item.prototype._transition = function( args ) { 1880 // redirect to nonTransition if no transition duration 1881 if ( !parseFloat( this.layout.options.transitionDuration ) ) { 1882 this._nonTransition( args ); 1883 return; 1884 } 1885 1886 var _transition = this._transn; 1887 // keep track of onTransitionEnd callback by css property 1888 for ( var prop in args.onTransitionEnd ) { 1889 _transition.onEnd[ prop ] = args.onTransitionEnd[ prop ]; 1890 } 1891 // keep track of properties that are transitioning 1892 for ( prop in args.to ) { 1893 _transition.ingProperties[ prop ] = true; 1894 // keep track of properties to clean up when transition is done 1895 if ( args.isCleaning ) { 1896 _transition.clean[ prop ] = true; 1897 } 1898 } 1899 1900 // set from styles 1901 if ( args.from ) { 1902 this.css( args.from ); 1903 // force redraw. http://blog.alexmaccaw.com/css-transitions 1904 var h = this.element.offsetHeight; 1905 // hack for JSHint to hush about unused var 1906 h = null; 1907 } 1908 // enable transition 1909 this.enableTransition( args.to ); 1910 // set styles that are transitioning 1911 this.css( args.to ); 1912 1913 this.isTransitioning = true; 1914 1915}; 1916 1917// dash before all cap letters, including first for 1918// WebkitTransform => -webkit-transform 1919function toDashedAll( str ) { 1920 return str.replace( /([A-Z])/g, function( $1 ) { 1921 return '-' + $1.toLowerCase(); 1922 }); 1923} 1924 1925var transitionProps = 'opacity,' +
vendor: 11,162 bytes, lines 1926-2372
1926 toDashedAll( vendorProperties.transform || 'transform' ); 1927 1928Item.prototype.enableTransition = function(/* style */) { 1929 // HACK changing transitionProperty during a transition 1930 // will cause transition to jump 1931 if ( this.isTransitioning ) { 1932 return; 1933 } 1934 1935 // make `transition: foo, bar, baz` from style object 1936 // HACK un-comment this when enableTransition can work 1937 // while a transition is happening 1938 // var transitionValues = []; 1939 // for ( var prop in style ) { 1940 // // dash-ify camelCased properties like WebkitTransition 1941 // prop = vendorProperties[ prop ] || prop; 1942 // transitionValues.push( toDashedAll( prop ) ); 1943 // } 1944 // enable transition styles 1945 this.css({ 1946 transitionProperty: transitionProps, 1947 transitionDuration: this.layout.options.transitionDuration 1948 }); 1949 // listen for transition end event 1950 this.element.addEventListener( transitionEndEvent, this, false ); 1951}; 1952 1953Item.prototype.transition = Item.prototype[ transitionProperty ? '_transition' : '_nonTransition' ]; 1954 1955// ----- events ----- // 1956 1957Item.prototype.onwebkitTransitionEnd = function( event ) { 1958 this.ontransitionend( event ); 1959}; 1960 1961Item.prototype.onotransitionend = function( event ) { 1962 this.ontransitionend( event ); 1963}; 1964 1965// properties that I munge to make my life easier 1966var dashedVendorProperties = { 1967 '-webkit-transform': 'transform', 1968 '-moz-transform': 'transform', 1969 '-o-transform': 'transform' 1970}; 1971 1972Item.prototype.ontransitionend = function( event ) { 1973 // disregard bubbled events from children 1974 if ( event.target !== this.element ) { 1975 return; 1976 } 1977 var _transition = this._transn; 1978 // get property name of transitioned property, convert to prefix-free 1979 var propertyName = dashedVendorProperties[ event.propertyName ] || event.propertyName; 1980 1981 // remove property that has completed transitioning 1982 delete _transition.ingProperties[ propertyName ]; 1983 // check if any properties are still transitioning 1984 if ( isEmptyObj( _transition.ingProperties ) ) { 1985 // all properties have completed transitioning 1986 this.disableTransition(); 1987 } 1988 // clean style 1989 if ( propertyName in _transition.clean ) { 1990 // clean up style 1991 this.element.style[ event.propertyName ] = ''; 1992 delete _transition.clean[ propertyName ]; 1993 } 1994 // trigger onTransitionEnd callback 1995 if ( propertyName in _transition.onEnd ) { 1996 var onTransitionEnd = _transition.onEnd[ propertyName ]; 1997 onTransitionEnd.call( this ); 1998 delete _transition.onEnd[ propertyName ]; 1999 } 2000 2001 this.emitEvent( 'transitionEnd', [ this ] ); 2002}; 2003 2004Item.prototype.disableTransition = function() { 2005 this.removeTransitionStyles(); 2006 this.element.removeEventListener( transitionEndEvent, this, false ); 2007 this.isTransitioning = false; 2008}; 2009 2010/** 2011 * removes style property from element 2012 * @param {Object} style 2013**/ 2014Item.prototype._removeStyles = function( style ) { 2015 // clean up transition styles 2016 var cleanStyle = {}; 2017 for ( var prop in style ) { 2018 cleanStyle[ prop ] = ''; 2019 } 2020 this.css( cleanStyle ); 2021}; 2022 2023var cleanTransitionStyle = { 2024 transitionProperty: '', 2025 transitionDuration: '' 2026}; 2027 2028Item.prototype.removeTransitionStyles = function() { 2029 // remove transition 2030 this.css( cleanTransitionStyle ); 2031}; 2032 2033// ----- show/hide/remove ----- // 2034 2035// remove element from DOM 2036Item.prototype.removeElem = function() { 2037 this.element.parentNode.removeChild( this.element ); 2038 // remove display: none 2039 this.css({ display: '' }); 2040 this.emitEvent( 'remove', [ this ] ); 2041}; 2042 2043Item.prototype.remove = function() { 2044 // just remove element if no transition support or no transition 2045 if ( !transitionProperty || !parseFloat( this.layout.options.transitionDuration ) ) { 2046 this.removeElem(); 2047 return; 2048 } 2049 2050 // start transition 2051 var _this = this; 2052 this.once( 'transitionEnd', function() { 2053 _this.removeElem(); 2054 }); 2055 this.hide(); 2056}; 2057 2058Item.prototype.reveal = function() { 2059 delete this.isHidden; 2060 // remove display: none 2061 this.css({ display: '' }); 2062 2063 var options = this.layout.options; 2064 2065 var onTransitionEnd = {}; 2066 var transitionEndProperty = this.getHideRevealTransitionEndProperty('visibleStyle'); 2067 onTransitionEnd[ transitionEndProperty ] = this.onRevealTransitionEnd; 2068 2069 this.transition({ 2070 from: options.hiddenStyle, 2071 to: options.visibleStyle, 2072 isCleaning: true, 2073 onTransitionEnd: onTransitionEnd 2074 }); 2075}; 2076 2077Item.prototype.onRevealTransitionEnd = function() { 2078 // check if still visible 2079 // during transition, item may have been hidden 2080 if ( !this.isHidden ) { 2081 this.emitEvent('reveal'); 2082 } 2083}; 2084 2085/** 2086 * get style property use for hide/reveal transition end 2087 * @param {String} styleProperty - hiddenStyle/visibleStyle 2088 * @returns {String} 2089 */ 2090Item.prototype.getHideRevealTransitionEndProperty = function( styleProperty ) { 2091 var optionStyle = this.layout.options[ styleProperty ]; 2092 // use opacity 2093 if ( optionStyle.opacity ) { 2094 return 'opacity'; 2095 } 2096 // get first property 2097 for ( var prop in optionStyle ) { 2098 return prop; 2099 } 2100}; 2101 2102Item.prototype.hide = function() { 2103 // set flag 2104 this.isHidden = true; 2105 // remove display: none 2106 this.css({ display: '' }); 2107 2108 var options = this.layout.options; 2109 2110 var onTransitionEnd = {}; 2111 var transitionEndProperty = this.getHideRevealTransitionEndProperty('hiddenStyle'); 2112 onTransitionEnd[ transitionEndProperty ] = this.onHideTransitionEnd; 2113 2114 this.transition({ 2115 from: options.visibleStyle, 2116 to: options.hiddenStyle, 2117 // keep hidden stuff hidden 2118 isCleaning: true, 2119 onTransitionEnd: onTransitionEnd 2120 }); 2121}; 2122 2123Item.prototype.onHideTransitionEnd = function() { 2124 // check if still hidden 2125 // during transition, item may have been un-hidden 2126 if ( this.isHidden ) { 2127 this.css({ display: 'none' }); 2128 this.emitEvent('hide'); 2129 } 2130}; 2131 2132Item.prototype.destroy = function() { 2133 this.css({ 2134 position: '', 2135 left: '', 2136 right: '', 2137 top: '', 2138 bottom: '', 2139 transition: '', 2140 transform: '' 2141 }); 2142}; 2143 2144return Item; 2145 2146})); 2147 2148/*! 2149 * Outlayer v1.4.2 2150 * the brains and guts of a layout library 2151 * MIT license 2152 */ 2153 2154( function( window, factory ) { 2155 2156 // universal module definition 2157 2158 if ( typeof define == 'function' && define.amd ) { 2159 // AMD 2160 define( 'outlayer/outlayer',[ 2161 'eventie/eventie', 2162 'eventEmitter/EventEmitter', 2163 'get-size/get-size', 2164 'fizzy-ui-utils/utils', 2165 './item' 2166 ], 2167 function( eventie, EventEmitter, getSize, utils, Item ) { 2168 return factory( window, eventie, EventEmitter, getSize, utils, Item); 2169 } 2170 ); 2171 } else if ( typeof exports == 'object' ) { 2172 // CommonJS 2173 module.exports = factory( 2174 window, 2175 require('eventie'), 2176 require('wolfy87-eventemitter'), 2177 require('get-size'), 2178 require('fizzy-ui-utils'), 2179 require('./item') 2180 ); 2181 } else { 2182 // browser global 2183 window.Outlayer = factory( 2184 window, 2185 window.eventie, 2186 window.EventEmitter, 2187 window.getSize, 2188 window.fizzyUIUtils, 2189 window.Outlayer.Item 2190 ); 2191 } 2192 2193}( window, function factory( window, eventie, EventEmitter, getSize, utils, Item ) { 2194 2195 2196// ----- vars ----- // 2197 2198var console = window.console; 2199var jQuery = window.jQuery; 2200var noop = function() {}; 2201 2202// -------------------------- Outlayer -------------------------- // 2203 2204// globally unique identifiers 2205var GUID = 0; 2206// internal store of all Outlayer intances 2207var instances = {}; 2208 2209 2210/** 2211 * @param {Element, String} element 2212 * @param {Object} options 2213 * @constructor 2214 */ 2215function Outlayer( element, options ) { 2216 var queryElement = utils.getQueryElement( element ); 2217 if ( !queryElement ) { 2218 if ( console ) { 2219 console.error( 'Bad element for ' + this.constructor.namespace + 2220 ': ' + ( queryElement || element ) ); 2221 } 2222 return; 2223 } 2224 this.element = queryElement; 2225 // add jQuery 2226 if ( jQuery ) { 2227 this.$element = jQuery( this.element ); 2228 } 2229 2230 // options 2231 this.options = utils.extend( {}, this.constructor.defaults ); 2232 this.option( options ); 2233 2234 // add id for Outlayer.getFromElement 2235 var id = ++GUID; 2236 this.element.outlayerGUID = id; // expando 2237 instances[ id ] = this; // associate via id 2238 2239 // kick it off 2240 this._create(); 2241 2242 if ( this.options.isInitLayout ) { 2243 this.layout(); 2244 } 2245} 2246 2247// settings are for internal use only 2248Outlayer.namespace = 'outlayer'; 2249Outlayer.Item = Item; 2250 2251// default options 2252Outlayer.defaults = { 2253 containerStyle: { 2254 position: 'relative' 2255 }, 2256 isInitLayout: true, 2257 isOriginLeft: true, 2258 isOriginTop: true, 2259 isResizeBound: true, 2260 isResizingContainer: true, 2261 // item options 2262 transitionDuration: '0.4s', 2263 hiddenStyle: { 2264 opacity: 0, 2265 transform: 'scale(0.001)' 2266 }, 2267 visibleStyle: { 2268 opacity: 1, 2269 transform: 'scale(1)' 2270 } 2271}; 2272 2273// inherit EventEmitter 2274utils.extend( Outlayer.prototype, EventEmitter.prototype ); 2275 2276/** 2277 * set options 2278 * @param {Object} opts 2279 */ 2280Outlayer.prototype.option = function( opts ) { 2281 utils.extend( this.options, opts ); 2282}; 2283 2284Outlayer.prototype._create = function() { 2285 // get items from children 2286 this.reloadItems(); 2287 // elements that affect layout, but are not laid out 2288 this.stamps = []; 2289 this.stamp( this.options.stamp ); 2290 // set container style 2291 utils.extend( this.element.style, this.options.containerStyle ); 2292 2293 // bind resize method 2294 if ( this.options.isResizeBound ) { 2295 this.bindResize(); 2296 } 2297}; 2298 2299// goes through all children again and gets bricks in proper order 2300Outlayer.prototype.reloadItems = function() { 2301 // collection of item elements 2302 this.items = this._itemize( this.element.children ); 2303}; 2304 2305 2306/** 2307 * turn elements into Outlayer.Items to be used in layout 2308 * @param {Array or NodeList or HTMLElement} elems 2309 * @returns {Array} items - collection of new Outlayer Items 2310 */ 2311Outlayer.prototype._itemize = function( elems ) { 2312 2313 var itemElems = this._filterFindItemElements( elems ); 2314 var Item = this.constructor.Item; 2315 2316 // create new Outlayer Items for collection 2317 var items = []; 2318 for ( var i=0, len = itemElems.length; i < len; i++ ) { 2319 var elem = itemElems[i]; 2320 var item = new Item( elem, this ); 2321 items.push( item ); 2322 } 2323 2324 return items; 2325}; 2326 2327/** 2328 * get item elements to be used in layout 2329 * @param {Array or NodeList or HTMLElement} elems 2330 * @returns {Array} items - item elements 2331 */ 2332Outlayer.prototype._filterFindItemElements = function( elems ) { 2333 return utils.filterFindElements( elems, this.options.itemSelector ); 2334}; 2335 2336/** 2337 * getter method for getting item elements 2338 * @returns {Array} elems - collection of item elements 2339 */ 2340Outlayer.prototype.getItemElements = function() { 2341 var elems = []; 2342 for ( var i=0, len = this.items.length; i < len; i++ ) { 2343 elems.push( this.items[i].element ); 2344 } 2345 return elems; 2346}; 2347 2348// ----- init & layout ----- // 2349 2350/** 2351 * lays out all items 2352 */ 2353Outlayer.prototype.layout = function() { 2354 this._resetLayout(); 2355 this._manageStamps(); 2356 2357 // don't animate first layout 2358 var isInstant = this.options.isLayoutInstant !== undefined ? 2359 this.options.isLayoutInstant : !this._isLayoutInited; 2360 this.layoutItems( this.items, isInstant ); 2361 2362 // flag for initalized 2363 this._isLayoutInited = true; 2364}; 2365 2366// _init is alias for layout 2367Outlayer.prototype._init = Outlayer.prototype.layout; 2368 2369/** 2370 * logic before any new layout 2371 */ 2372Outlayer.prototype._resetLayout = function() {
vendor: 6,719 bytes, lines 2373-2649
2373 this.getSize(); 2374}; 2375 2376 2377Outlayer.prototype.getSize = function() { 2378 this.size = getSize( this.element ); 2379}; 2380 2381/** 2382 * get measurement from option, for columnWidth, rowHeight, gutter 2383 * if option is String -> get element from selector string, & get size of element 2384 * if option is Element -> get size of element 2385 * else use option as a number 2386 * 2387 * @param {String} measurement 2388 * @param {String} size - width or height 2389 * @private 2390 */ 2391Outlayer.prototype._getMeasurement = function( measurement, size ) { 2392 var option = this.options[ measurement ]; 2393 var elem; 2394 if ( !option ) { 2395 // default to 0 2396 this[ measurement ] = 0; 2397 } else { 2398 // use option as an element 2399 if ( typeof option === 'string' ) { 2400 elem = this.element.querySelector( option ); 2401 } else if ( utils.isElement( option ) ) { 2402 elem = option; 2403 } 2404 // use size of element, if element 2405 this[ measurement ] = elem ? getSize( elem )[ size ] : option; 2406 } 2407}; 2408 2409/** 2410 * layout a collection of item elements 2411 * @api public 2412 */ 2413Outlayer.prototype.layoutItems = function( items, isInstant ) { 2414 items = this._getItemsForLayout( items ); 2415 2416 this._layoutItems( items, isInstant ); 2417 2418 this._postLayout(); 2419}; 2420 2421/** 2422 * get the items to be laid out 2423 * you may want to skip over some items 2424 * @param {Array} items 2425 * @returns {Array} items 2426 */ 2427Outlayer.prototype._getItemsForLayout = function( items ) { 2428 var layoutItems = []; 2429 for ( var i=0, len = items.length; i < len; i++ ) { 2430 var item = items[i]; 2431 if ( !item.isIgnored ) { 2432 layoutItems.push( item ); 2433 } 2434 } 2435 return layoutItems; 2436}; 2437 2438/** 2439 * layout items 2440 * @param {Array} items 2441 * @param {Boolean} isInstant 2442 */ 2443Outlayer.prototype._layoutItems = function( items, isInstant ) { 2444 this._emitCompleteOnItems( 'layout', items ); 2445 2446 if ( !items || !items.length ) { 2447 // no items, emit event with empty array 2448 return; 2449 } 2450 2451 var queue = []; 2452 2453 for ( var i=0, len = items.length; i < len; i++ ) { 2454 var item = items[i]; 2455 // get x/y object from method 2456 var position = this._getItemLayoutPosition( item ); 2457 // enqueue 2458 position.item = item; 2459 position.isInstant = isInstant || item.isLayoutInstant; 2460 queue.push( position ); 2461 } 2462 2463 this._processLayoutQueue( queue ); 2464}; 2465 2466/** 2467 * get item layout position 2468 * @param {Outlayer.Item} item 2469 * @returns {Object} x and y position 2470 */ 2471Outlayer.prototype._getItemLayoutPosition = function( /* item */ ) { 2472 return { 2473 x: 0, 2474 y: 0 2475 }; 2476}; 2477 2478/** 2479 * iterate over array and position each item 2480 * Reason being - separating this logic prevents 'layout invalidation' 2481 * thx @paul_irish 2482 * @param {Array} queue 2483 */ 2484Outlayer.prototype._processLayoutQueue = function( queue ) { 2485 for ( var i=0, len = queue.length; i < len; i++ ) { 2486 var obj = queue[i]; 2487 this._positionItem( obj.item, obj.x, obj.y, obj.isInstant ); 2488 } 2489}; 2490 2491/** 2492 * Sets position of item in DOM 2493 * @param {Outlayer.Item} item 2494 * @param {Number} x - horizontal position 2495 * @param {Number} y - vertical position 2496 * @param {Boolean} isInstant - disables transitions 2497 */ 2498Outlayer.prototype._positionItem = function( item, x, y, isInstant ) { 2499 if ( isInstant ) { 2500 // if not transition, just set CSS 2501 item.goTo( x, y ); 2502 } else { 2503 item.moveTo( x, y ); 2504 } 2505}; 2506 2507/** 2508 * Any logic you want to do after each layout, 2509 * i.e. size the container 2510 */ 2511Outlayer.prototype._postLayout = function() { 2512 this.resizeContainer(); 2513}; 2514 2515Outlayer.prototype.resizeContainer = function() { 2516 if ( !this.options.isResizingContainer ) { 2517 return; 2518 } 2519 var size = this._getContainerSize(); 2520 if ( size ) { 2521 this._setContainerMeasure( size.width, true ); 2522 this._setContainerMeasure( size.height, false ); 2523 } 2524}; 2525 2526/** 2527 * Sets width or height of container if returned 2528 * @returns {Object} size 2529 * @param {Number} width 2530 * @param {Number} height 2531 */ 2532Outlayer.prototype._getContainerSize = noop; 2533 2534/** 2535 * @param {Number} measure - size of width or height 2536 * @param {Boolean} isWidth 2537 */ 2538Outlayer.prototype._setContainerMeasure = function( measure, isWidth ) { 2539 if ( measure === undefined ) { 2540 return; 2541 } 2542 2543 var elemSize = this.size; 2544 // add padding and border width if border box 2545 if ( elemSize.isBorderBox ) { 2546 measure += isWidth ? elemSize.paddingLeft + elemSize.paddingRight + 2547 elemSize.borderLeftWidth + elemSize.borderRightWidth : 2548 elemSize.paddingBottom + elemSize.paddingTop + 2549 elemSize.borderTopWidth + elemSize.borderBottomWidth; 2550 } 2551 2552 measure = Math.max( measure, 0 ); 2553 this.element.style[ isWidth ? 'width' : 'height' ] = measure + 'px'; 2554}; 2555 2556/** 2557 * emit eventComplete on a collection of items events 2558 * @param {String} eventName 2559 * @param {Array} items - Outlayer.Items 2560 */ 2561Outlayer.prototype._emitCompleteOnItems = function( eventName, items ) { 2562 var _this = this; 2563 function onComplete() { 2564 _this.dispatchEvent( eventName + 'Complete', null, [ items ] ); 2565 } 2566 2567 var count = items.length; 2568 if ( !items || !count ) { 2569 onComplete(); 2570 return; 2571 } 2572 2573 var doneCount = 0; 2574 function tick() { 2575 doneCount++; 2576 if ( doneCount === count ) { 2577 onComplete(); 2578 } 2579 } 2580 2581 // bind callback 2582 for ( var i=0, len = items.length; i < len; i++ ) { 2583 var item = items[i]; 2584 item.once( eventName, tick ); 2585 } 2586}; 2587 2588/** 2589 * emits events via eventEmitter and jQuery events 2590 * @param {String} type - name of event 2591 * @param {Event} event - original event 2592 * @param {Array} args - extra arguments 2593 */ 2594Outlayer.prototype.dispatchEvent = function( type, event, args ) { 2595 // add original event to arguments 2596 var emitArgs = event ? [ event ].concat( args ) : args; 2597 this.emitEvent( type, emitArgs ); 2598 2599 if ( jQuery ) { 2600 // set this.$element 2601 this.$element = this.$element || jQuery( this.element ); 2602 if ( event ) { 2603 // create jQuery event 2604 var $event = jQuery.Event( event ); 2605 $event.type = type; 2606 this.$element.trigger( $event, args ); 2607 } else { 2608 // just trigger with type if no event available 2609 this.$element.trigger( type, args ); 2610 } 2611 } 2612}; 2613 2614// -------------------------- ignore & stamps -------------------------- // 2615 2616 2617/** 2618 * keep item in collection, but do not lay it out 2619 * ignored items do not get skipped in layout 2620 * @param {Element} elem 2621 */ 2622Outlayer.prototype.ignore = function( elem ) { 2623 var item = this.getItem( elem ); 2624 if ( item ) { 2625 item.isIgnored = true; 2626 } 2627}; 2628 2629/** 2630 * return item to layout collection 2631 * @param {Element} elem 2632 */ 2633Outlayer.prototype.unignore = function( elem ) { 2634 var item = this.getItem( elem ); 2635 if ( item ) { 2636 delete item.isIgnored; 2637 } 2638}; 2639 2640/** 2641 * adds elements to stamps 2642 * @param {NodeList, Array, Element, or String} elems 2643 */ 2644Outlayer.prototype.stamp = function( elems ) { 2645 elems = this._find( elems ); 2646 if ( !elems ) { 2647 return; 2648 } 2649
2650 this.stamps = this.stamps.concat( elems ); 2651 // ignore 2652 for ( var i=0, len = elems.length; i < len; i++ ) { 2653 var elem = elems[i]; 2654 this.ignore( elem ); 2655 } 2656}; 2657 2658/** 2659 * removes elements to stamps 2660 * @param {NodeList, Array, or Element} elems 2661 */ 2662Outlayer.prototype.unstamp = function( elems ) { 2663 elems = this._find( elems ); 2664 if ( !elems ){ 2665 return; 2666 } 2667 2668 for ( var i=0, len = elems.length; i < len; i++ ) { 2669 var elem = elems[i]; 2670 // filter out removed stamp elements 2671 utils.removeFrom( this.stamps, elem ); 2672 this.unignore( elem ); 2673 } 2674 2675}; 2676 2677/** 2678 * finds child elements 2679 * @param {NodeList, Array, Element, or String} elems 2680 * @returns {Array} elems 2681 */ 2682Outlayer.prototype._find = function( elems ) { 2683 if ( !elems ) { 2684 return; 2685 } 2686 // if string, use argument as selector string 2687 if ( typeof elems === 'string' ) { 2688 elems = this.element.querySelectorAll( elems ); 2689 } 2690 elems = utils.makeArray( elems ); 2691 return elems; 2692}; 2693 2694Outlayer.prototype._manageStamps = function() { 2695 if ( !this.stamps || !this.stamps.length ) { 2696 return; 2697 } 2698 2699 this._getBoundingRect(); 2700 2701 for ( var i=0, len = this.stamps.length; i < len; i++ ) { 2702 var stamp = this.stamps[i]; 2703 this._manageStamp( stamp ); 2704 } 2705}; 2706 2707// update boundingLeft / Top 2708Outlayer.prototype._getBoundingRect = function() { 2709 // get bounding rect for container element 2710 var boundingRect = this.element.getBoundingClientRect(); 2711 var size = this.size; 2712 this._boundingRect = { 2713 left: boundingRect.left + size.paddingLeft + size.borderLeftWidth, 2714 top: boundingRect.top + size.paddingTop + size.borderTopWidth, 2715 right: boundingRect.right - ( size.paddingRight + size.borderRightWidth ), 2716 bottom: boundingRect.bottom - ( size.paddingBottom + size.borderBottomWidth ) 2717 }; 2718}; 2719 2720/** 2721 * @param {Element} stamp 2722**/ 2723Outlayer.prototype._manageStamp = noop; 2724 2725/** 2726 * get x/y position of element relative to container element 2727 * @param {Element} elem 2728 * @returns {Object} offset - has left, top, right, bottom 2729 */ 2730Outlayer.prototype._getElementOffset = function( elem ) { 2731 var boundingRect = elem.getBoundingClientRect(); 2732 var thisRect = this._boundingRect; 2733 var size = getSize( elem ); 2734 var offset = { 2735 left: boundingRect.left - thisRect.left - size.marginLeft, 2736 top: boundingRect.top - thisRect.top - size.marginTop, 2737 right: thisRect.right - boundingRect.right - size.marginRight, 2738 bottom: thisRect.bottom - boundingRect.bottom - size.marginBottom 2739 }; 2740 return offset; 2741}; 2742 2743// -------------------------- resize -------------------------- // 2744 2745// enable event handlers for listeners 2746// i.e. resize -> onresize 2747Outlayer.prototype.handleEvent = function( event ) { 2748 var method = 'on' + event.type; 2749 if ( this[ method ] ) { 2750 this[ method ]( event ); 2751 } 2752}; 2753 2754/** 2755 * Bind layout to window resizing 2756 */ 2757Outlayer.prototype.bindResize = function() { 2758 // bind just one listener 2759 if ( this.isResizeBound ) { 2760 return; 2761 } 2762 eventie.bind( window, 'resize', this ); 2763 this.isResizeBound = true; 2764}; 2765 2766/** 2767 * Unbind layout to window resizing 2768 */ 2769Outlayer.prototype.unbindResize = function() { 2770 if ( this.isResizeBound ) { 2771 eventie.unbind( window, 'resize', this ); 2772 } 2773 this.isResizeBound = false; 2774}; 2775 2776// original debounce by John Hann 2777// http://unscriptable.com/index.php/2009/03/20/debouncing-javascript-methods/ 2778 2779// this fires every resize 2780Outlayer.prototype.onresize = function() { 2781 if ( this.resizeTimeout ) { 2782 clearTimeout( this.resizeTimeout ); 2783 } 2784 2785 var _this = this; 2786 function delayed() { 2787 _this.resize(); 2788 delete _this.resizeTimeout; 2789 } 2790 2791 this.resizeTimeout = setTimeout( delayed, 100 ); 2792}; 2793 2794// debounced, layout on resize 2795Outlayer.prototype.resize = function() { 2796 // don't trigger if size did not change 2797 // or if resize was unbound. See #9 2798 if ( !this.isResizeBound || !this.needsResizeLayout() ) { 2799 return; 2800 } 2801 2802 this.layout(); 2803}; 2804 2805/** 2806 * check if layout is needed post layout 2807 * @returns Boolean 2808 */ 2809Outlayer.prototype.needsResizeLayout = function() { 2810 var size = getSize( this.element ); 2811 // check that this.size and size are there 2812 // IE8 triggers resize on body size change, so they might not be 2813 var hasSizes = this.size && size; 2814 return hasSizes && size.innerWidth !== this.size.innerWidth; 2815}; 2816 2817// -------------------------- methods -------------------------- // 2818 2819/** 2820 * add items to Outlayer instance 2821 * @param {Array or NodeList or Element} elems 2822 * @returns {Array} items - Outlayer.Items 2823**/ 2824Outlayer.prototype.addItems = function( elems ) { 2825 var items = this._itemize( elems ); 2826 // add items to collection 2827 if ( items.length ) { 2828 this.items = this.items.concat( items ); 2829 } 2830 return items; 2831}; 2832 2833/** 2834 * Layout newly-appended item elements 2835 * @param {Array or NodeList or Element} elems 2836 */ 2837Outlayer.prototype.appended = function( elems ) { 2838 var items = this.addItems( elems ); 2839 if ( !items.length ) { 2840 return; 2841 } 2842 // layout and reveal just the new items 2843 this.layoutItems( items, true ); 2844 this.reveal( items ); 2845}; 2846 2847/** 2848 * Layout prepended elements 2849 * @param {Array or NodeList or Element} elems 2850 */ 2851Outlayer.prototype.prepended = function( elems ) { 2852 var items = this._itemize( elems ); 2853 if ( !items.length ) { 2854 return; 2855 } 2856 // add items to beginning of collection 2857 var previousItems = this.items.slice(0); 2858 this.items = items.concat( previousItems ); 2859 // start new layout 2860 this._resetLayout(); 2861 this._manageStamps(); 2862 // layout new stuff without transition 2863 this.layoutItems( items, true ); 2864 this.reveal( items ); 2865 // layout previous items 2866 this.layoutItems( previousItems ); 2867}; 2868 2869/** 2870 * reveal a collection of items 2871 * @param {Array of Outlayer.Items} items 2872 */ 2873Outlayer.prototype.reveal = function( items ) { 2874 this._emitCompleteOnItems( 'reveal', items ); 2875 2876 var len = items && items.length; 2877 for ( var i=0; len && i < len; i++ ) { 2878 var item = items[i]; 2879 item.reveal(); 2880 } 2881}; 2882 2883/** 2884 * hide a collection of items 2885 * @param {Array of Outlayer.Items} items 2886 */ 2887Outlayer.prototype.hide = function( items ) { 2888 this._emitCompleteOnItems( 'hide', items ); 2889 2890 var len = items && items.length; 2891 for ( var i=0; len && i < len; i++ ) { 2892 var item = items[i]; 2893 item.hide(); 2894 } 2895}; 2896 2897/** 2898 * reveal item elements 2899 * @param {Array}, {Element}, {NodeList} items 2900 */ 2901Outlayer.prototype.revealItemElements = function( elems ) { 2902 var items = this.getItems( elems ); 2903 this.reveal( items ); 2904}; 2905 2906/** 2907 * hide item elements 2908 * @param {Array}, {Element}, {NodeList} items 2909 */ 2910Outlayer.prototype.hideItemElements = function( elems ) { 2911 var items = this.getItems( elems ); 2912 this.hide( items ); 2913}; 2914 2915/** 2916 * get Outlayer.Item, given an Element 2917 * @param {Element} elem 2918 * @param {Function} callback 2919 * @returns {Outlayer.Item} item 2920 */ 2921Outlayer.prototype.getItem = function( elem ) { 2922 // loop through items to get the one that matches 2923 for ( var i=0, len = this.items.length; i < len; i++ ) { 2924 var item = this.items[i]; 2925 if ( item.element === elem ) { 2926 // return item 2927 return item; 2928 } 2929 } 2930}; 2931 2932/** 2933 * get collection of Outlayer.Items, given Elements 2934 * @param {Array} elems 2935 * @returns {Array} items - Outlayer.Items 2936 */ 2937Outlayer.prototype.getItems = function( elems ) { 2938 elems = utils.makeArray( elems ); 2939 var items = []; 2940 for ( var i=0, len = elems.length; i < len; i++ ) { 2941 var elem = elems[i]; 2942 var item = this.getItem( elem ); 2943 if ( item ) { 2944 items.push( item ); 2945 } 2946 } 2947 2948 return items; 2949}; 2950 2951/**
2952 * remove element(s) from instance and DOM 2953 * @param {Array or NodeList or Element} elems 2954 */ 2955Outlayer.prototype.remove = function( elems ) { 2956 var removeItems = this.getItems( elems ); 2957 2958 this._emitCompleteOnItems( 'remove', removeItems ); 2959 2960 // bail if no items to remove 2961 if ( !removeItems || !removeItems.length ) { 2962 return; 2963 } 2964 2965 for ( var i=0, len = removeItems.length; i < len; i++ ) { 2966 var item = removeItems[i]; 2967 item.remove(); 2968 // remove item from collection 2969 utils.removeFrom( this.items, item ); 2970 } 2971}; 2972 2973// ----- destroy ----- // 2974 2975// remove and disable Outlayer instance 2976Outlayer.prototype.destroy = function() { 2977 // clean up dynamic styles 2978 var style = this.element.style; 2979 style.height = ''; 2980 style.position = ''; 2981 style.width = ''; 2982 // destroy items 2983 for ( var i=0, len = this.items.length; i < len; i++ ) { 2984 var item = this.items[i]; 2985 item.destroy(); 2986 } 2987 2988 this.unbindResize(); 2989 2990 var id = this.element.outlayerGUID; 2991 delete instances[ id ]; // remove reference to instance by id 2992 delete this.element.outlayerGUID; 2993 // remove data for jQuery 2994 if ( jQuery ) { 2995 jQuery.removeData( this.element, this.constructor.namespace ); 2996 } 2997 2998}; 2999 3000// -------------------------- data -------------------------- // 3001 3002/** 3003 * get Outlayer instance from element 3004 * @param {Element} elem 3005 * @returns {Outlayer} 3006 */ 3007Outlayer.data = function( elem ) { 3008 elem = utils.getQueryElement( elem ); 3009 var id = elem && elem.outlayerGUID; 3010 return id && instances[ id ]; 3011}; 3012 3013 3014// -------------------------- create Outlayer class -------------------------- // 3015 3016/** 3017 * create a layout class 3018 * @param {String} namespace 3019 */ 3020Outlayer.create = function( namespace, options ) { 3021 // sub-class Outlayer 3022 function Layout() { 3023 Outlayer.apply( this, arguments ); 3024 } 3025 // inherit Outlayer prototype, use Object.create if there 3026 if ( Object.create ) { 3027 Layout.prototype = Object.create( Outlayer.prototype ); 3028 } else { 3029 utils.extend( Layout.prototype, Outlayer.prototype ); 3030 } 3031 // set contructor, used for namespace and Item 3032 Layout.prototype.constructor = Layout; 3033 3034 Layout.defaults = utils.extend( {}, Outlayer.defaults ); 3035 // apply new options 3036 utils.extend( Layout.defaults, options ); 3037 // keep prototype.settings for backwards compatibility (Packery v1.2.0) 3038 Layout.prototype.settings = {}; 3039 3040 Layout.namespace = namespace; 3041 3042 Layout.data = Outlayer.data; 3043 3044 // sub-class Item 3045 Layout.Item = function LayoutItem() { 3046 Item.apply( this, arguments ); 3047 }; 3048 3049 Layout.Item.prototype = new Item(); 3050 3051 // -------------------------- declarative -------------------------- // 3052 3053 utils.htmlInit( Layout, namespace ); 3054 3055 // -------------------------- jQuery bridge -------------------------- // 3056 3057 // make into jQuery plugin 3058 if ( jQuery && jQuery.bridget ) { 3059 jQuery.bridget( namespace, Layout ); 3060 } 3061 3062 return Layout; 3063}; 3064 3065// ----- fin ----- // 3066 3067// back in global 3068Outlayer.Item = Item; 3069 3070return Outlayer; 3071 3072})); 3073 3074 3075/** 3076 * Rect 3077 * low-level utility class for basic geometry 3078 */ 3079 3080( function( window, factory ) { 3081 3082 // universal module definition 3083 if ( typeof define == 'function' && define.amd ) { 3084 // AMD 3085 define( 'packery/js/rect',factory ); 3086 } else if ( typeof exports == 'object' ) { 3087 // CommonJS 3088 module.exports = factory(); 3089 } else { 3090 // browser global 3091 window.Packery = window.Packery || {}; 3092 window.Packery.Rect = factory(); 3093 } 3094 3095}( window, function factory() { 3096 3097 3098// -------------------------- Packery -------------------------- // 3099 3100// global namespace 3101var Packery = window.Packery = function() {}; 3102 3103// -------------------------- Rect -------------------------- // 3104 3105function Rect( props ) { 3106 // extend properties from defaults 3107 for ( var prop in Rect.defaults ) { 3108 this[ prop ] = Rect.defaults[ prop ]; 3109 } 3110 3111 for ( prop in props ) { 3112 this[ prop ] = props[ prop ]; 3113 } 3114 3115} 3116 3117// make available 3118Packery.Rect = Rect; 3119 3120Rect.defaults = { 3121 x: 0, 3122 y: 0, 3123 width: 0, 3124 height: 0 3125}; 3126 3127/** 3128 * Determines whether or not this rectangle wholly encloses another rectangle or point. 3129 * @param {Rect} rect 3130 * @returns {Boolean} 3131**/ 3132Rect.prototype.contains = function( rect ) { 3133 // points don't have width or height 3134 var otherWidth = rect.width || 0; 3135 var otherHeight = rect.height || 0; 3136 return this.x <= rect.x && 3137 this.y <= rect.y && 3138 this.x + this.width >= rect.x + otherWidth && 3139 this.y + this.height >= rect.y + otherHeight; 3140}; 3141 3142/** 3143 * Determines whether or not the rectangle intersects with another. 3144 * @param {Rect} rect 3145 * @returns {Boolean} 3146**/ 3147Rect.prototype.overlaps = function( rect ) { 3148 var thisRight = this.x + this.width; 3149 var thisBottom = this.y + this.height; 3150 var rectRight = rect.x + rect.width; 3151 var rectBottom = rect.y + rect.height; 3152 3153 // http://stackoverflow.com/a/306332 3154 return this.x < rectRight && 3155 thisRight > rect.x && 3156 this.y < rectBottom && 3157 thisBottom > rect.y; 3158}; 3159 3160/** 3161 * @param {Rect} rect - the overlapping rect 3162 * @returns {Array} freeRects - rects representing the area around the rect 3163**/ 3164Rect.prototype.getMaximalFreeRects = function( rect ) { 3165 3166 // if no intersection, return false 3167 if ( !this.overlaps( rect ) ) { 3168 return false;
vendor: 6,336 bytes, lines 3169-3443
3169 } 3170 3171 var freeRects = []; 3172 var freeRect; 3173 3174 var thisRight = this.x + this.width; 3175 var thisBottom = this.y + this.height; 3176 var rectRight = rect.x + rect.width; 3177 var rectBottom = rect.y + rect.height; 3178 3179 // top 3180 if ( this.y < rect.y ) { 3181 freeRect = new Rect({ 3182 x: this.x, 3183 y: this.y, 3184 width: this.width, 3185 height: rect.y - this.y 3186 }); 3187 freeRects.push( freeRect ); 3188 } 3189 3190 // right 3191 if ( thisRight > rectRight ) { 3192 freeRect = new Rect({ 3193 x: rectRight, 3194 y: this.y, 3195 width: thisRight - rectRight, 3196 height: this.height 3197 }); 3198 freeRects.push( freeRect ); 3199 } 3200 3201 // bottom 3202 if ( thisBottom > rectBottom ) { 3203 freeRect = new Rect({ 3204 x: this.x, 3205 y: rectBottom, 3206 width: this.width, 3207 height: thisBottom - rectBottom 3208 }); 3209 freeRects.push( freeRect ); 3210 } 3211 3212 // left 3213 if ( this.x < rect.x ) { 3214 freeRect = new Rect({ 3215 x: this.x, 3216 y: this.y, 3217 width: rect.x - this.x, 3218 height: this.height 3219 }); 3220 freeRects.push( freeRect ); 3221 } 3222 3223 return freeRects; 3224}; 3225 3226Rect.prototype.canFit = function( rect ) { 3227 return this.width >= rect.width && this.height >= rect.height; 3228}; 3229 3230return Rect; 3231 3232})); 3233 3234/** 3235 * Packer 3236 * bin-packing algorithm 3237 */ 3238 3239( function( window, factory ) { 3240 3241 // universal module definition 3242 if ( typeof define == 'function' && define.amd ) { 3243 // AMD 3244 define( 'packery/js/packer',[ './rect' ], factory ); 3245 } else if ( typeof exports == 'object' ) { 3246 // CommonJS 3247 module.exports = factory( 3248 require('./rect') 3249 ); 3250 } else { 3251 // browser global 3252 var Packery = window.Packery = window.Packery || {}; 3253 Packery.Packer = factory( Packery.Rect ); 3254 } 3255 3256}( window, function factory( Rect ) { 3257 3258 3259// -------------------------- Packer -------------------------- // 3260 3261/** 3262 * @param {Number} width 3263 * @param {Number} height 3264 * @param {String} sortDirection 3265 * topLeft for vertical, leftTop for horizontal 3266 */ 3267function Packer( width, height, sortDirection ) { 3268 this.width = width || 0; 3269 this.height = height || 0; 3270 this.sortDirection = sortDirection || 'downwardLeftToRight'; 3271 3272 this.reset(); 3273} 3274 3275Packer.prototype.reset = function() { 3276 this.spaces = []; 3277 this.newSpaces = []; 3278 3279 var initialSpace = new Rect({ 3280 x: 0, 3281 y: 0, 3282 width: this.width, 3283 height: this.height 3284 }); 3285 3286 this.spaces.push( initialSpace ); 3287 // set sorter 3288 this.sorter = sorters[ this.sortDirection ] || sorters.downwardLeftToRight; 3289}; 3290 3291// change x and y of rect to fit with in Packer's available spaces 3292Packer.prototype.pack = function( rect ) { 3293 for ( var i=0, len = this.spaces.length; i < len; i++ ) { 3294 var space = this.spaces[i]; 3295 if ( space.canFit( rect ) ) { 3296 this.placeInSpace( rect, space ); 3297 break; 3298 } 3299 } 3300}; 3301 3302Packer.prototype.placeInSpace = function( rect, space ) { 3303 // place rect in space 3304 rect.x = space.x; 3305 rect.y = space.y; 3306 3307 this.placed( rect ); 3308}; 3309 3310// update spaces with placed rect 3311Packer.prototype.placed = function( rect ) { 3312 // update spaces 3313 var revisedSpaces = []; 3314 for ( var i=0, len = this.spaces.length; i < len; i++ ) { 3315 var space = this.spaces[i]; 3316 var newSpaces = space.getMaximalFreeRects( rect ); 3317 // add either the original space or the new spaces to the revised spaces 3318 if ( newSpaces ) { 3319 revisedSpaces.push.apply( revisedSpaces, newSpaces ); 3320 } else { 3321 revisedSpaces.push( space ); 3322 } 3323 } 3324 3325 this.spaces = revisedSpaces; 3326 3327 this.mergeSortSpaces(); 3328}; 3329 3330Packer.prototype.mergeSortSpaces = function() { 3331 // remove redundant spaces 3332 Packer.mergeRects( this.spaces ); 3333 this.spaces.sort( this.sorter ); 3334}; 3335 3336// add a space back 3337Packer.prototype.addSpace = function( rect ) { 3338 this.spaces.push( rect ); 3339 this.mergeSortSpaces(); 3340}; 3341 3342// -------------------------- utility functions -------------------------- // 3343 3344/** 3345 * Remove redundant rectangle from array of rectangles 3346 * @param {Array} rects: an array of Rects 3347 * @returns {Array} rects: an array of Rects 3348**/ 3349Packer.mergeRects = function( rects ) { 3350 for ( var i=0, len = rects.length; i < len; i++ ) { 3351 var rect = rects[i]; 3352 // skip over this rect if it was already removed 3353 if ( !rect ) { 3354 continue; 3355 } 3356 // clone rects we're testing, remove this rect 3357 var compareRects = rects.slice(0); 3358 // do not compare with self 3359 compareRects.splice( i, 1 ); 3360 // compare this rect with others 3361 var removedCount = 0; 3362 for ( var j=0, jLen = compareRects.length; j < jLen; j++ ) { 3363 var compareRect = compareRects[j]; 3364 // if this rect contains another, 3365 // remove that rect from test collection 3366 var indexAdjust = i > j ? 0 : 1; 3367 if ( rect.contains( compareRect ) ) { 3368 // console.log( 'current test rects:' + testRects.length, testRects ); 3369 // console.log( i, j, indexAdjust, rect, compareRect ); 3370 rects.splice( j + indexAdjust - removedCount, 1 ); 3371 removedCount++; 3372 } 3373 } 3374 } 3375 3376 return rects; 3377}; 3378 3379 3380// -------------------------- sorters -------------------------- // 3381 3382// functions for sorting rects in order 3383var sorters = { 3384 // top down, then left to right 3385 downwardLeftToRight: function( a, b ) { 3386 return a.y - b.y || a.x - b.x; 3387 }, 3388 // left to right, then top down 3389 rightwardTopToBottom: function( a, b ) { 3390 return a.x - b.x || a.y - b.y; 3391 } 3392}; 3393 3394 3395// -------------------------- -------------------------- // 3396 3397return Packer; 3398 3399})); 3400/** 3401 * Packery Item Element 3402**/ 3403 3404( function( window, factory ) { 3405 3406 // universal module definition 3407 3408 if ( typeof define == 'function' && define.amd ) { 3409 // AMD 3410 define( 'packery/js/item',[ 3411 'get-style-property/get-style-property', 3412 'outlayer/outlayer', 3413 './rect' 3414 ], 3415 factory ); 3416 } else if ( typeof exports == 'object' ) { 3417 // CommonJS 3418 module.exports = factory( 3419 require('desandro-get-style-property'), 3420 require('outlayer'), 3421 require('./rect') 3422 ); 3423 } else { 3424 // browser global 3425 window.Packery.Item = factory( 3426 window.getStyleProperty, 3427 window.Outlayer, 3428 window.Packery.Rect 3429 ); 3430 } 3431 3432}( window, function factory( getStyleProperty, Outlayer, Rect ) { 3433 3434 3435// -------------------------- Item -------------------------- // 3436 3437var transformProperty = getStyleProperty('transform'); 3438 3439// sub-class Item 3440var Item = function PackeryItem() { 3441 Outlayer.Item.apply( this, arguments ); 3442}; 3443
3444Item.prototype = new Outlayer.Item(); 3445 3446var protoCreate = Item.prototype._create; 3447Item.prototype._create = function() { 3448 // call default _create logic 3449 protoCreate.call( this ); 3450 this.rect = new Rect(); 3451 // rect used for placing, in drag or Packery.fit() 3452 this.placeRect = new Rect(); 3453}; 3454 3455// -------------------------- drag -------------------------- // 3456 3457Item.prototype.dragStart = function() { 3458 this.getPosition(); 3459 this.removeTransitionStyles(); 3460 // remove transform property from transition 3461 if ( this.isTransitioning && transformProperty ) { 3462 this.element.style[ transformProperty ] = 'none'; 3463 } 3464 this.getSize(); 3465 // create place rect, used for position when dragged then dropped 3466 // or when positioning 3467 this.isPlacing = true; 3468 this.needsPositioning = false; 3469 this.positionPlaceRect( this.position.x, this.position.y ); 3470 this.isTransitioning = false; 3471 this.didDrag = false; 3472}; 3473 3474/** 3475 * handle item when it is dragged 3476 * @param {Number} x - horizontal position of dragged item 3477 * @param {Number} y - vertical position of dragged item 3478 */ 3479Item.prototype.dragMove = function( x, y ) { 3480 this.didDrag = true; 3481 var packerySize = this.layout.size; 3482 x -= packerySize.paddingLeft; 3483 y -= packerySize.paddingTop; 3484 this.positionPlaceRect( x, y ); 3485}; 3486 3487Item.prototype.dragStop = function() { 3488 this.getPosition(); 3489 var isDiffX = this.position.x != this.placeRect.x; 3490 var isDiffY = this.position.y != this.placeRect.y; 3491 // set post-drag positioning flag 3492 this.needsPositioning = isDiffX || isDiffY; 3493 // reset flag 3494 this.didDrag = false; 3495}; 3496 3497// -------------------------- placing -------------------------- // 3498 3499/** 3500 * position a rect that will occupy space in the packer 3501 * @param {Number} x 3502 * @param {Number} y 3503 * @param {Boolean} isMaxYContained 3504 */ 3505Item.prototype.positionPlaceRect = function( x, y, isMaxYOpen ) { 3506 this.placeRect.x = this.getPlaceRectCoord( x, true ); 3507 this.placeRect.y = this.getPlaceRectCoord( y, false, isMaxYOpen ); 3508}; 3509 3510/** 3511 * get x/y coordinate for place rect 3512 * @param {Number} coord - x or y 3513 * @param {Boolean} isX 3514 * @param {Boolean} isMaxOpen - does not limit value to outer bound 3515 * @returns {Number} coord - processed x or y 3516 */ 3517Item.prototype.getPlaceRectCoord = function( coord, isX, isMaxOpen ) { 3518 var measure = isX ? 'Width' : 'Height'; 3519 var size = this.size[ 'outer' + measure ]; 3520 var segment = this.layout[ isX ? 'columnWidth' : 'rowHeight' ]; 3521 var parentSize = this.layout.size[ 'inner' + measure ]; 3522 3523 // additional parentSize calculations for Y 3524 if ( !isX ) { 3525 parentSize = Math.max( parentSize, this.layout.maxY ); 3526 // prevent gutter from bumping up height when non-vertical grid 3527 if ( !this.layout.rowHeight ) { 3528 parentSize -= this.layout.gutter; 3529 } 3530 } 3531 3532 var max; 3533 3534 if ( segment ) { 3535 segment += this.layout.gutter; 3536 // allow for last column to reach the edge 3537 parentSize += isX ? this.layout.gutter : 0; 3538 // snap to closest segment 3539 coord = Math.round( coord / segment ); 3540 // contain to outer bound 3541 // contain non-growing bound, allow growing bound to grow 3542 var mathMethod; 3543 if ( this.layout.options.isHorizontal ) { 3544 mathMethod = !isX ? 'floor' : 'ceil'; 3545 } else { 3546 mathMethod = isX ? 'floor' : 'ceil'; 3547 } 3548 var maxSegments = Math[ mathMethod ]( parentSize / segment ); 3549 maxSegments -= Math.ceil( size / segment ); 3550 max = maxSegments; 3551 } else { 3552 max = parentSize - size; 3553 } 3554
vendor: 3,406 bytes, lines 3555-3705
3555 coord = isMaxOpen ? coord : Math.min( coord, max ); 3556 coord *= segment || 1; 3557 3558 return Math.max( 0, coord ); 3559}; 3560 3561Item.prototype.copyPlaceRectPosition = function() { 3562 this.rect.x = this.placeRect.x; 3563 this.rect.y = this.placeRect.y; 3564}; 3565 3566// ----- ----- // 3567 3568// remove element from DOM 3569Item.prototype.removeElem = function() { 3570 this.element.parentNode.removeChild( this.element ); 3571 // add space back to packer 3572 this.layout.packer.addSpace( this.rect ); 3573 this.emitEvent( 'remove', [ this ] ); 3574}; 3575 3576// ----- ----- // 3577 3578return Item; 3579 3580})); 3581 3582/*! 3583 * Packery v1.4.3 3584 * bin-packing layout library 3585 * 3586 * Licensed GPLv3 for open source use 3587 * or Flickity Commercial License for commercial use 3588 * 3589 * http://packery.metafizzy.co 3590 * Copyright 2015 Metafizzy 3591 */ 3592 3593( function( window, factory ) { 3594 3595 // universal module definition 3596 if ( typeof define == 'function' && define.amd ) { 3597 // AMD 3598 define( [ 3599 'classie/classie', 3600 'get-size/get-size', 3601 'outlayer/outlayer', 3602 'packery/js/rect', 3603 'packery/js/packer', 3604 'packery/js/item' 3605 ], 3606 factory ); 3607 } else if ( typeof exports == 'object' ) { 3608 // CommonJS 3609 module.exports = factory( 3610 require('desandro-classie'), 3611 require('get-size'), 3612 require('outlayer'), 3613 require('./rect'), 3614 require('./packer'), 3615 require('./item') 3616 ); 3617 } else { 3618 // browser global 3619 window.Packery = factory( 3620 window.classie, 3621 window.getSize, 3622 window.Outlayer, 3623 window.Packery.Rect, 3624 window.Packery.Packer, 3625 window.Packery.Item 3626 ); 3627 } 3628 3629}( window, function factory( classie, getSize, Outlayer, Rect, Packer, Item ) { 3630 3631 3632// ----- Rect ----- // 3633 3634// allow for pixel rounding errors IE8-IE11 & Firefox; #227 3635Rect.prototype.canFit = function( rect ) { 3636 return this.width >= rect.width - 1 && this.height >= rect.height - 1; 3637}; 3638 3639// -------------------------- Packery -------------------------- // 3640 3641// create an Outlayer layout class 3642var Packery = Outlayer.create('packery'); 3643Packery.Item = Item; 3644 3645Packery.prototype._create = function() { 3646 // call super 3647 Outlayer.prototype._create.call( this ); 3648 3649 // initial properties 3650 this.packer = new Packer(); 3651 3652 // Left over from v1.0 3653 this.stamp( this.options.stamped ); 3654 3655 // create drag handlers 3656 var _this = this; 3657 this.handleDraggabilly = { 3658 dragStart: function() { 3659 _this.itemDragStart( this.element ); 3660 }, 3661 dragMove: function() { 3662 _this.itemDragMove( this.element, this.position.x, this.position.y ); 3663 }, 3664 dragEnd: function() { 3665 _this.itemDragEnd( this.element ); 3666 } 3667 }; 3668 3669 this.handleUIDraggable = { 3670 start: function handleUIDraggableStart( event, ui ) { 3671 // HTML5 may trigger dragstart, dismiss HTML5 dragging 3672 if ( !ui ) { 3673 return; 3674 } 3675 _this.itemDragStart( event.currentTarget ); 3676 }, 3677 drag: function handleUIDraggableDrag( event, ui ) { 3678 if ( !ui ) { 3679 return; 3680 } 3681 _this.itemDragMove( event.currentTarget, ui.position.left, ui.position.top ); 3682 }, 3683 stop: function handleUIDraggableStop( event, ui ) { 3684 if ( !ui ) { 3685 return; 3686 } 3687 _this.itemDragEnd( event.currentTarget ); 3688 } 3689 }; 3690 3691}; 3692 3693 3694// ----- init & layout ----- // 3695 3696/** 3697 * logic before any new layout 3698 */ 3699Packery.prototype._resetLayout = function() { 3700 this.getSize(); 3701 3702 this._getMeasurements(); 3703 3704 // reset packer 3705 var packer = this.packer;
3706 // packer settings, if horizontal or vertical 3707 if ( this.options.isHorizontal ) { 3708 packer.width = Number.POSITIVE_INFINITY; 3709 packer.height = this.size.innerHeight + this.gutter; 3710 packer.sortDirection = 'rightwardTopToBottom'; 3711 } else { 3712 packer.width = this.size.innerWidth + this.gutter; 3713 packer.height = Number.POSITIVE_INFINITY; 3714 packer.sortDirection = 'downwardLeftToRight'; 3715 } 3716 3717 packer.reset(); 3718 3719 // layout 3720 this.maxY = 0; 3721 this.maxX = 0; 3722}; 3723 3724/** 3725 * update columnWidth, rowHeight, & gutter 3726 * @private 3727 */ 3728Packery.prototype._getMeasurements = function() { 3729 this._getMeasurement( 'columnWidth', 'width' ); 3730 this._getMeasurement( 'rowHeight', 'height' ); 3731 this._getMeasurement( 'gutter', 'width' ); 3732}; 3733 3734Packery.prototype._getItemLayoutPosition = function( item ) { 3735 this._packItem( item ); 3736 return item.rect; 3737}; 3738 3739 3740/** 3741 * layout item in packer 3742 * @param {Packery.Item} item 3743 */ 3744Packery.prototype._packItem = function( item ) { 3745 this._setRectSize( item.element, item.rect ); 3746 // pack the rect in the packer 3747 this.packer.pack( item.rect ); 3748 this._setMaxXY( item.rect ); 3749}; 3750 3751/** 3752 * set max X and Y value, for size of container 3753 * @param {Packery.Rect} rect 3754 * @private 3755 */ 3756Packery.prototype._setMaxXY = function( rect ) { 3757 this.maxX = Math.max( rect.x + rect.width, this.maxX ); 3758 this.maxY = Math.max( rect.y + rect.height, this.maxY ); 3759}; 3760 3761/** 3762 * set the width and height of a rect, applying columnWidth and rowHeight 3763 * @param {Element} elem 3764 * @param {Packery.Rect} rect 3765 */ 3766Packery.prototype._setRectSize = function( elem, rect ) { 3767 var size = getSize( elem ); 3768 var w = size.outerWidth; 3769 var h = size.outerHeight; 3770 // size for columnWidth and rowHeight, if available 3771 // only check if size is non-zero, #177 3772 if ( w || h ) { 3773 w = this._applyGridGutter( w, this.columnWidth ); 3774 h = this._applyGridGutter( h, this.rowHeight ); 3775 } 3776 // rect must fit in packer 3777 rect.width = Math.min( w, this.packer.width ); 3778 rect.height = Math.min( h, this.packer.height ); 3779}; 3780 3781/** 3782 * fits item to columnWidth/rowHeight and adds gutter 3783 * @param {Number} measurement - item width or height 3784 * @param {Number} gridSize - columnWidth or rowHeight 3785 * @returns measurement 3786 */ 3787Packery.prototype._applyGridGutter = function( measurement, gridSize ) { 3788 // just add gutter if no gridSize 3789 if ( !gridSize ) { 3790 return measurement + this.gutter; 3791 } 3792 gridSize += this.gutter; 3793 // fit item to columnWidth/rowHeight 3794 var remainder = measurement % gridSize; 3795 var mathMethod = remainder && remainder < 1 ? 'round' : 'ceil'; 3796 measurement = Math[ mathMethod ]( measurement / gridSize ) * gridSize; 3797 return measurement; 3798}; 3799 3800Packery.prototype._getContainerSize = function() { 3801 if ( this.options.isHorizontal ) { 3802 return { 3803 width: this.maxX - this.gutter 3804 }; 3805 } else { 3806 return { 3807 height: this.maxY - this.gutter 3808 }; 3809 } 3810}; 3811 3812 3813// -------------------------- stamp -------------------------- // 3814 3815/** 3816 * makes space for element 3817 * @param {Element} elem 3818 */ 3819Packery.prototype._manageStamp = function( elem ) { 3820 3821 var item = this.getItem( elem ); 3822 var rect; 3823 if ( item && item.isPlacing ) { 3824 rect = item.placeRect; 3825 } else { 3826 var offset = this._getElementOffset( elem ); 3827 rect = new Rect({ 3828 x: this.options.isOriginLeft ? offset.left : offset.right, 3829 y: this.options.isOriginTop ? offset.top : offset.bottom 3830 }); 3831 } 3832 3833 this._setRectSize( elem, rect ); 3834 // save its space in the packer 3835 this.packer.placed( rect ); 3836 this._setMaxXY( rect ); 3837}; 3838 3839// -------------------------- methods -------------------------- // 3840 3841function verticalSorter( a, b ) { 3842 return a.position.y - b.position.y || a.position.x - b.position.x; 3843} 3844 3845function horizontalSorter( a, b ) { 3846 return a.position.x - b.position.x || a.position.y - b.position.y; 3847} 3848 3849Packery.prototype.sortItemsByPosition = function() { 3850 var sorter = this.options.isHorizontal ? horizontalSorter : verticalSorter; 3851 this.items.sort( sorter ); 3852}; 3853 3854/** 3855 * Fit item element in its current position 3856 * Packery will position elements around it 3857 * useful for expanding elements 3858 * 3859 * @param {Element} elem 3860 * @param {Number} x - horizontal destination position, optional 3861 * @param {Number} y - vertical destination position, optional 3862 */ 3863Packery.prototype.fit = function( elem, x, y ) { 3864 var item = this.getItem( elem ); 3865 if ( !item ) { 3866 return; 3867 } 3868 3869 // prepare internal properties 3870 this._getMeasurements(); 3871 3872 // stamp item to get it out of layout 3873 this.stamp( item.element ); 3874 // required for positionPlaceRect 3875 item.getSize(); 3876 // set placing flag 3877 item.isPlacing = true; 3878 // fall back to current position for fitting 3879 x = x === undefined ? item.rect.x: x; 3880 y = y === undefined ? item.rect.y: y; 3881 3882 // position it best at its destination 3883 item.positionPlaceRect( x, y, true ); 3884 3885 this._bindFitEvents( item ); 3886 item.moveTo( item.placeRect.x, item.placeRect.y ); 3887 // layout everything else 3888 this.layout(); 3889 3890 // return back to regularly scheduled programming 3891 this.unstamp( item.element );
3892 this.sortItemsByPosition(); 3893 // un set placing flag, back to normal 3894 item.isPlacing = false; 3895 // copy place rect position 3896 item.copyPlaceRectPosition(); 3897}; 3898 3899/** 3900 * emit event when item is fit and other items are laid out 3901 * @param {Packery.Item} item 3902 * @private 3903 */ 3904Packery.prototype._bindFitEvents = function( item ) { 3905 var _this = this; 3906 var ticks = 0; 3907 function tick() { 3908 ticks++; 3909 if ( ticks != 2 ) { 3910 return; 3911 } 3912 _this.dispatchEvent( 'fitComplete', null, [ item ] ); 3913 } 3914 // when item is laid out 3915 item.on( 'layout', function() { 3916 tick(); 3917 return true; 3918 }); 3919 // when all items are laid out 3920 this.on( 'layoutComplete', function() { 3921 tick(); 3922 return true; 3923 }); 3924}; 3925 3926// -------------------------- resize -------------------------- // 3927 3928// debounced, layout on resize 3929Packery.prototype.resize = function() { 3930 // don't trigger if size did not change 3931 var size = getSize( this.element ); 3932 // check that this.size and size are there 3933 // IE8 triggers resize on body size change, so they might not be 3934 var hasSizes = this.size && size; 3935 var innerSize = this.options.isHorizontal ? 'innerHeight' : 'innerWidth'; 3936 if ( hasSizes && size[ innerSize ] == this.size[ innerSize ] ) { 3937 return; 3938 } 3939 3940 this.layout(); 3941}; 3942 3943// -------------------------- drag -------------------------- // 3944 3945/** 3946 * handle an item drag start event 3947 * @param {Element} elem 3948 */ 3949Packery.prototype.itemDragStart = function( elem ) { 3950 this.stamp( elem ); 3951 var item = this.getItem( elem ); 3952 if ( item ) { 3953 item.dragStart(); 3954 } 3955}; 3956 3957/** 3958 * handle an item drag move event 3959 * @param {Element} elem 3960 * @param {Number} x - horizontal change in position 3961 * @param {Number} y - vertical change in position 3962 */ 3963Packery.prototype.itemDragMove = function( elem, x, y ) { 3964 var item = this.getItem( elem ); 3965 if ( item ) { 3966 item.dragMove( x, y ); 3967 } 3968 3969 // debounce 3970 var _this = this; 3971 // debounce triggering layout 3972 function delayed() { 3973 _this.layout(); 3974 delete _this.dragTimeout; 3975 } 3976 3977 this.clearDragTimeout(); 3978 3979 this.dragTimeout = setTimeout( delayed, 40 ); 3980}; 3981 3982Packery.prototype.clearDragTimeout = function() { 3983 if ( this.dragTimeout ) { 3984 clearTimeout( this.dragTimeout ); 3985 } 3986}; 3987 3988/** 3989 * handle an item drag end event 3990 * @param {Element} elem 3991 */ 3992Packery.prototype.itemDragEnd = function( elem ) { 3993 var item = this.getItem( elem ); 3994 var itemDidDrag; 3995 if ( item ) { 3996 itemDidDrag = item.didDrag; 3997 item.dragStop(); 3998 } 3999 // if elem didn't move, or if it doesn't need positioning 4000 // unignore and unstamp and call it a day 4001 if ( !item || ( !itemDidDrag && !item.needsPositioning ) ) { 4002 this.unstamp( elem ); 4003 return; 4004 } 4005 // procced with dragged item 4006 4007 classie.add( item.element, 'is-positioning-post-drag' ); 4008 4009 // save this var, as it could get reset in dragStart 4010 var onLayoutComplete = this._getDragEndLayoutComplete( elem, item ); 4011 4012 if ( item.needsPositioning ) { 4013 item.on( 'layout', onLayoutComplete ); 4014 item.moveTo( item.placeRect.x, item.placeRect.y ); 4015 } else if ( item ) { 4016 // item didn't need placement 4017 item.copyPlaceRectPosition(); 4018 } 4019 4020 this.clearDragTimeout(); 4021 this.on( 'layoutComplete', onLayoutComplete ); 4022 this.layout(); 4023 4024}; 4025 4026/** 4027 * get drag end callback 4028 * @param {Element} elem 4029 * @param {Packery.Item} item 4030 * @returns {Function} onLayoutComplete 4031 */ 4032Packery.prototype._getDragEndLayoutComplete = function( elem, item ) { 4033 var itemNeedsPositioning = item && item.needsPositioning; 4034 var completeCount = 0; 4035 var asyncCount = itemNeedsPositioning ? 2 : 1; 4036 var _this = this; 4037 4038 return function onLayoutComplete() { 4039 completeCount++; 4040 // don't proceed if not complete 4041 if ( completeCount != asyncCount ) { 4042 return true; 4043 } 4044 // reset item 4045 if ( item ) { 4046 classie.remove( item.element, 'is-positioning-post-drag' ); 4047 item.isPlacing = false; 4048 item.copyPlaceRectPosition(); 4049 } 4050 4051 _this.unstamp( elem ); 4052 // only sort when item moved 4053 _this.sortItemsByPosition(); 4054 4055 // emit item drag event now that everything is done 4056 if ( itemNeedsPositioning ) { 4057 _this.dispatchEvent( 'dragItemPositioned', null, [ item ] ); 4058 } 4059 // listen once 4060 return true; 4061 }; 4062}; 4063 4064/** 4065 * binds Draggabilly events 4066 * @param {Draggabilly} draggie 4067 */ 4068Packery.prototype.bindDraggabillyEvents = function( draggie ) { 4069 draggie.on( 'dragStart', this.handleDraggabilly.dragStart ); 4070 draggie.on( 'dragMove', this.handleDraggabilly.dragMove ); 4071 draggie.on( 'dragEnd', this.handleDraggabilly.dragEnd ); 4072}; 4073 4074/** 4075 * binds jQuery UI Draggable events 4076 * @param {jQuery} $elems 4077 */ 4078Packery.prototype.bindUIDraggableEvents = function( $elems ) { 4079 $elems 4080 .on( 'dragstart', this.handleUIDraggable.start ) 4081 .on( 'drag', this.handleUIDraggable.drag ) 4082 .on( 'dragstop', this.handleUIDraggable.stop ); 4083}; 4084 4085Packery.Rect = Rect; 4086Packery.Packer = Packer; 4087 4088return Packery; 4089 4090})); 4091 4092})(window.uberGridjQuery || window.jQuery || window.$ || jQuery || $ );
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.