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