1/*! 2 * imagesLoaded PACKAGED v3.1.8 3 * JavaScript is all like "You images are done yet or what?" 4 * MIT License 5 */ 6(function () { 7 8 /** 9 * Class for managing events. 10 * Can be extended to provide event functionality in other classes. 11 * 12 * @class EventEmitter Manages event registering and emitting. 13 */ 14 function EventEmitter() {} 15 16 // Shortcuts to improve speed and size 17 var proto = EventEmitter.prototype; 18 var exports = this; 19 var originalGlobalValue = exports.EventEmitter; 20 21 /** 22 * Finds the index of the listener for the event in it's storage array. 23 * 24 * @param {Function[]} listeners Array of listeners to search through. 25 * @param {Function} listener Method to look for. 26 * @return {Number} Index of the specified listener, -1 if not found 27 * @api private 28 */ 29 function indexOfListener(listeners, listener) { 30 var i = listeners.length; 31 while (i--) { 32 if (listeners[i].listener === listener) { 33 return i; 34 } 35 } 36 37 return -1; 38 } 39 40 /** 41 * Alias a method while keeping the context correct, to allow for overwriting of target method. 42 * 43 * @param {String} name The name of the target method. 44 * @return {Function} The aliased method 45 * @api private 46 */ 47 function alias(name) { 48 return function aliasClosure() { 49 return this[name].apply(this, arguments); 50 }; 51 } 52 53 /** 54 * Returns the listener array for the specified event. 55 * Will initialise the event object and listener arrays if required. 56 * 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 c
56ontaining bar and baz. But only if you have either defined them with defineEvent or added some listeners to them. 57 * Each property in the object response is an array of listener functions. 58 * 59 * @param {String|RegExp} evt Name of the event to return the listeners from. 60 * @return {Function[]|Object} All listener functions for the event. 61 */ 62 proto.getListeners = function getListeners(evt) { 63 var events = this._getEvents(); 64 var response; 65 var key; 66 67 // Return a concatenated array of all matching events if 68 // the selector is a regular expression. 69 if (typeof evt === 'object') { 70 response = {}; 71 for (key in events) { 72 if (events.hasOwnProperty(key) && evt.test(key)) { 73 response[key] = events[key]; 74 } 75 } 76 } 77 else { 78 response = events[evt] || (events[evt] = []); 79 } 80 81 return response; 82 }; 83 84 /** 85 * Takes a list of listener objects and flattens it into a list of listener functions. 86 * 87 * @param {Object[]} listeners Raw listener objects. 88 * @return {Function[]} Just the listener functions. 89 */ 90 proto.flattenListeners = function flattenListeners(listeners) { 91 var flatListeners = []; 92 var i; 93 94 for (i = 0; i < listeners.length; i += 1) { 95 flatListeners.push(listeners[i].listener); 96 } 97 98 return flatListeners; 99 }; 100 101 /** 102 * 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. 103 * 104 * @param {String|RegExp} evt Name of the event to return the listeners from. 105 * @return {Object} All listener functions for an event in an object. 106 */ 107 proto.getListenersAsObject = function getListenersAsObject(evt) { 108 var listeners = this.getListeners(evt); 109 var response; 110 111 if (listeners instanceof Array) { 112 response = {}; 113 response[evt] = listeners; 114 } 115 116 return response || listeners; 117 }; 118 119 /** 120 * Adds a listener function to the specified event. 121 * The listener will not be added if it is a duplicate. 122 * If the listener returns true then it will be removed after it is called. 123 * If you pass a regular expression as the event name then the listener will be added to all events that match it. 124 * 125 * @param {String|RegExp} evt Name of the event to attach the listener to. 126 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. 127 * @return {Object} Current instance of EventEmitter for chaining. 128 */ 129 proto.addListener = function addListener(evt, listener) { 130 var listeners = this.getListenersAsObject(evt); 131 var listenerIsWrapped = typeof listener === 'object'; 132 var key; 133 134 for (key in listeners) { 135 if (listeners.hasOwnProperty(key) && indexOfListener(listeners[key], listener) === -1) { 136 listeners[key].push(listenerIsWrapped ? listener : { 137 listener: listener, 138 once: false 139 }); 140 } 141 } 142 143 return this; 144 }; 145 146 /** 147 * Alias of addListener 148 */ 149 proto.on = alias('addListener'); 150 151 /** 152 * Semi-alias of addListener. It will add a listener that will be 153 * automatically removed after it's first execution. 154 * 155 * @param {String|RegExp} evt Name of the event to attach the listener to. 156 * @param {Function} listener Method to be called when the event is emitted. If the function returns true then it will be removed after calling. 157 * @return {Object} Current instance of EventEmitter for chaining. 158 */ 159 proto.addOnceListener = function addOnceListener(evt, listener) { 160 return this.addListener(evt, { 161 listener: listener, 162 once: true 163 }); 164 }; 165 166 /** 167 * Alias of addOnceListener. 168 */ 169 proto.once = alias('addOnceListener'); 170 171 /** 172 * 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. 173 * You need to tell it what event names should be matched by a regex. 174 * 175 * @param {String} evt Name of the event to create. 176 * @return {Object} Current instance of EventEmitter for chaining. 177 */ 178 proto.defineEvent = function defineEvent(evt) { 179 this.getListeners(evt); 180 return this; 181 }; 182 183 /** 184 * Uses defineEvent to define multiple events. 185 * 186 * @param {String[]} evts An array of event names to define. 187 * @return {Object} Current instance of EventEmitter for chaining. 188 */ 189 proto.defineEvents = function defineEvents(evts) { 190 for (var i = 0; i < evts.length; i += 1) { 191 this.defineEvent(evts[i]); 192 } 193 return this; 194 }; 195 196 /** 197 * Removes a listener function from the specified event. 198 * When passed a regular expression as the event name, it will remove the listener from all events that match it. 199 * 200 * @param {String|RegExp} evt Name of the event to remove the listener from. 201 * @param {Function} listener Method to remove from the event. 202 * @return {Object} Current instance of EventEmitter for chaining. 203 */ 204 proto.removeListener = function removeListener(evt, listener) { 205 var listeners = this.getListenersAsObject(evt); 206 var index; 207 var key; 208 209 for (key in listeners) { 210 if (listeners.hasOwnProperty(key)) { 211 index = indexOfListener(listeners[key], listener); 212 213 if (index !== -1) { 214 listeners[key].splice(index, 1); 215 } 216 } 217 } 218 219 return this; 220 }; 221 222 /** 223 * Alias of removeListener 224 */ 225 proto.off = alias('removeListener'); 226 227 /** 228 * Adds listeners in bulk using the manipulateListeners method. 229 * 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. 230 * You can also pass it a regular expression to add the array of listeners to all events that match it. 231 * Yeah, this function does quite a bit. That's probably a bad thing. 232 * 233 * @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. 234 * @param {Function[]} [listeners] An optional array of listener functions to add. 235 * @return {Object} Current instance of EventEmitter for chaining. 236 */ 237 proto.addListeners = function addListeners(evt, listeners) { 238 // Pass through to manipulateListeners 239 return this.manipulateListeners(false, evt, listeners); 240 }; 241 242 /** 243 * Removes listeners in bulk using the manipulateListeners method. 244 * 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. 245 * You can also pass it an event name and an array of listeners to be removed. 246 * You can also pass it a regular expression to remove the listeners from all events that match it. 247 * 248 * @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. 249 * @param {Function[]} [listeners] An optional array of listener functions to remove. 250 * @return {Object} Current instance of EventEmitter for chaining. 251 */ 252 proto.removeListeners = function removeListeners(evt, listeners) { 253 // Pass through to manipulateListeners 254 return this.manipulateListeners(true, evt, listeners); 255 }; 256 257 /** 258 * 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. 259 * The first argument will determine if the listeners are removed (true) or added (false). 260 * 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. 261 * You can also pass it an event name and an array of listeners to be added/removed. 262 * You can also pass it a regular expression to manipulate the listeners of all events that match it. 263 * 264 * @param {Boolean} remove True if you want to remove listeners, false if you want to add. 265 * @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. 266 * @param {Function[]} [listeners] An optional array of listener functions to add/remove. 267 * @return {Object} Current instance of EventEmitter for chaining. 268 */ 269 proto.manipulateListeners = function manipulateListeners(remove, evt, listeners) { 270 var i; 271 var value; 272 var single = remove ? this.removeListener : this.addListener; 273 var multiple = remove ? this.removeListeners : this.addListeners; 274 275 // If evt is an object then pass each of it's properties to this method 276 if (typeof evt === 'object' && !(evt instanceof RegExp)) { 277 for (i in evt) { 278 if (evt.hasOwnProperty(i) && (value = evt[i])) { 279 // Pass the single listener straight through to the singular method 280 if (typeof value === 'function') { 281 single.call(this, i, value); 282 } 283 else { 284 // Otherwise pass back to the multiple function 285 multiple.call(this, i, value); 286 } 287 } 288 } 289 } 290 else { 291 // So evt must be a string 292 // And listeners must be an array of listeners 293 // Loop over it and pass each one to the multiple method 294 i = listeners.length; 295 while (i--) { 296 single.call(this, evt, listeners[i]); 297 } 298 } 299 300 return this; 301 }; 302 303 /** 304 * Removes all listeners from a specified event. 305 * If you do not specify an event then all listeners will be removed. 306 * That means every event will be emptied. 307 * You can also pass a regex to remove all events that match it. 308 * 309 * @param {String|RegExp} [evt] Optional name of the event to remove all listeners for. Will remove from every event if not passed. 310 * @return {Object} Current instance of EventEmitter for chaining. 311 */ 312 proto.removeEvent = function removeEvent(evt) { 313 var type = typeof evt; 314 var events = this._getEvents(); 315 var key; 316 317 // Remove different things depending on the state of evt 318 if (type === 'string') { 319 // Remove all listeners for the specified event 320 delete events[evt]; 321 } 322 else if (type === 'object') { 323 // Remove all events matching the regex. 324 for (key in events) { 325 if (events.hasOwnProperty(key) && evt.test(key)) { 326 delete events[key]; 327 } 328 } 329 } 330 else { 331 // Remove all listeners in all events 332 delete this._events; 333 } 334 335 return this; 336 }; 337 338 /** 339 * Alias of removeEvent. 340 * 341 * Added to mirror the node API. 342 */ 343 proto.removeAllListeners = alias('removeEvent'); 344 345 /** 346 * Emits an event of your choice. 347 * When emitted, every listener attached to that event will be executed. 348 * If you pass the optional argument array then those arguments will be passed to every listener upon execution. 349 * Because it uses `apply`, your array of arguments will be passed as if you wrote them out separately. 350 * So they will not arrive within the array on the other side, they will be separate. 351 * You can also pass a regular expression to emit to all events that match it. 352 * 353 * @param {String|RegExp} evt Name of the event to emit and execute listeners for. 354 * @param {Array} [args] Optional array of arguments to be passed to each listener. 355 * @return {Object} Current instance of EventEmitter for chaining. 356 */ 357 proto.emitEvent = function emitEvent(evt, args) { 358 var listeners = this.getListenersAsObject(evt); 359 var listener; 360 var i; 361 var key; 362 var response; 363 364 for (key in listeners) { 365 if (listeners.hasOwnProperty(key)) { 366 i = listeners[key].length; 367 368 while (i--) { 369 // If the listener returns true then it shall be removed from the event 370 // The function is executed either with a basic call or an apply if there is an args array 371 listener = listeners[key][i]; 372 373 if (listener.once === true) { 374 this.removeListener(evt, listener.listener); 375 } 376 377 response = listener.listener.apply(this, args || []); 378 379 if (response === this._getOnceReturnValue()) { 380 this.removeListener(evt, listener.listener); 381 } 382 } 383 } 384 } 385 386 return this; 387 }; 388 389 /** 390 * Alias of emitEvent 391 */ 392 proto.trigger = alias('emitEvent'); 393 394 /** 395 * 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. 396 * As with emitEvent, you can pass a regex in place of the event name to emit to all events that match it. 397 * 398 * @param {String|RegExp} evt Name of the event to emit and execute listeners for. 399 * @param {...*} Optional additional arguments to be passed to each listener. 400 * @return {Object} Current instance of EventEmitter for chaining. 401 */ 402 proto.emit = function emit(evt) { 403 var args = Array.prototype.slice.call(arguments, 1); 404 return this.emitEvent(evt, args); 405 }; 406 407 /** 408 * Sets the current value to check against when executing listeners. If a 409 * listeners return value matches the one set here then it will be removed 410 * after execution. This value defaults to true. 411 * 412 * @param {*} value The new value to check for when executing listeners. 413 * @return {Object} Current instance of EventEmitter for chaining. 414 */ 415 proto.setOnceReturnValue = function setOnceReturnValue(value) { 416 this._onceReturnValue = value; 417 return this; 418 }; 419 420 /** 421 * Fetches the current value to check against when executing listeners. If 422 * the listeners return value matches this one then it should be removed 423 * automatically. It will return true by default. 424 * 425 * @return {*|Boolean} The current value to check for or the default, true. 426 * @api private 427 */ 428 proto._getOnceReturnValue = function _getOnceReturnValue() { 429 if (this.hasOwnProperty('_onceReturnValue')) { 430 return this._onceReturnValue; 431 } 432 else { 433 return true; 434 } 435 }; 436 437 /** 438 * Fetches the events object and creates one if required. 439 * 440 * @return {Object} The events storage object. 441 * @api private 442 */ 443 proto._getEvents = function _getEvents() { 444 return this._events || (this._events = {}); 445 }; 446 447 /** 448 * Reverts the global {@link EventEmitter} to its previous value and returns a reference to this version. 449 * 450 * @return {Function} Non conflicting EventEmitter class. 451 */ 452 EventEmitter.noConflict = function noConflict() { 453 exports.EventEmitter = originalGlobalValue; 454 return EventEmitter; 455 }; 456 457 // Expose the class either via AMD, CommonJS or the global object 458 if (typeof define === 'function' && define.amd) { 459 define('eventEmitter/EventEmitter',[],function () { 460 return EventEmitter; 461 }); 462 } 463 else if (typeof module === 'object' && module.exports){ 464 module.exports = EventEmitter; 465 } 466 else { 467 this.EventEmitter = EventEmitter; 468 } 469}.call(this)); 470 471/*! 472 * eventie v1.0.4 473 * event binding helper 474 * eventie.bind( elem, 'click', myFn ) 475 * eventie.unbind( elem, 'click', myFn ) 476 */ 477 478/*jshint browser: true, undef: true, unused: true */ 479/*global define: false */ 480 481( function( window ) { 482 483 484 485var docElem = document.documentElement; 486 487var bind = function() {}; 488 489function getIEEvent( obj ) { 490 var event = window.event; 491 // add event.target 492 event.target = event.target || event.srcElement || obj; 493 return event; 494} 495 496if ( docElem.addEventListener ) { 497 bind = function( obj, type, fn ) { 498 obj.addEventListener( type, fn, false ); 499 }; 500} else if ( docElem.attachEvent ) { 501 bind = function( obj, type, fn ) { 502 obj[ type + fn ] = fn.handleEvent ? 503 function() { 504 var event = getIEEvent( obj ); 505 fn.handleEvent.call( fn, event ); 506 } : 507 function() { 508 var event = getIEEvent( obj ); 509 fn.call( obj, event ); 510 }; 511 obj.attachEvent( "on" + type, obj[ type + fn ] ); 512 }; 513} 514 515var unbind = function() {}; 516 517if ( docElem.removeEventListener ) { 518 unbind = function( obj, type, fn ) { 519 obj.removeEventListener( type, fn, false ); 520 }; 521} else if (
521docElem.detachEvent ) { 522 unbind = function( obj, type, fn ) { 523 obj.detachEvent( "on" + type, obj[ type + fn ] ); 524 try { 525 delete obj[ type + fn ]; 526 } catch ( err ) { 527 // can't delete window object properties 528 obj[ type + fn ] = undefined; 529 } 530 }; 531} 532 533var eventie = { 534 bind: bind, 535 unbind: unbind 536}; 537 538// transport 539if ( typeof define === 'function' && define.amd ) { 540 // AMD 541 define( 'eventie/eventie',eventie ); 542} else { 543 // browser global 544 window.eventie = eventie; 545} 546 547})( this ); 548 549/*! 550 * imagesLoaded v3.1.8 551 * JavaScript is all like "You images are done yet or what?" 552 * MIT License 553 */ 554 555( function( window, factory ) { 556 // universal module definition 557 558 /*global define: false, module: false, require: false */ 559 560 if ( typeof define === 'function' && define.amd ) { 561 // AMD 562 define( [ 563 'eventEmitter/EventEmitter', 564 'eventie/eventie' 565 ], function( EventEmitter, eventie ) { 566 return factory( window, EventEmitter, eventie ); 567 }); 568 } else if ( typeof exports === 'object' ) { 569 // CommonJS 570 module.exports = factory( 571 window, 572 require('wolfy87-eventemitter'), 573 require('eventie') 574 ); 575 } else { 576 // browser global 577 window.imagesLoaded = factory( 578 window, 579 window.EventEmitter, 580 window.eventie 581 ); 582 } 583 584})( window, 585 586// -------------------------- factory -------------------------- // 587 588function factory( window, EventEmitter, eventie ) { 589 590 591 592var $ = window.jQuery; 593var console = window.console; 594var hasConsole = typeof console !== 'undefined'; 595 596// -------------------------- helpers -------------------------- // 597 598// extend objects 599function extend( a, b ) { 600 for ( var prop in b ) { 601 a[ prop ] = b[ prop ]; 602 } 603 return a; 604} 605 606var objToString = Object.prototype.toString; 607function isArray( obj ) { 608 return objToString.call( obj ) === '[object Array]'; 609} 610 611// turn element or nodeList into an array 612function makeArray( obj ) { 613 var ary = []; 614 if ( isArray( obj ) ) { 615 // use object if already an array 616 ary = obj; 617 } else if ( typeof obj.length === 'number' ) { 618 // convert nodeList to array 619 for ( var i=0, len = obj.length; i < len; i++ ) { 620 ary.push( obj[i] ); 621 } 622 } else { 623 // array of single index 624 ary.push( obj ); 625 } 626 return ary; 627} 628 629 // -------------------------- imagesLoaded -------------------------- // 630 631 /** 632 * @param {Array, Element, NodeList, String} elem 633 * @param {Object or Function} options - if function, use as callback 634 * @param {Function} onAlways - callback function 635 */ 636 function ImagesLoaded( elem, options, onAlways ) { 637 // coerce ImagesLoaded() without new, to be new ImagesLoaded() 638 if ( !( this instanceof ImagesLoaded ) ) { 639 return new ImagesLoaded( elem, options ); 640 } 641 // use elem as selector string 642 if ( typeof elem === 'string' ) { 643 elem = document.querySelectorAll( elem ); 644 } 645 646 this.elements = makeArray( elem ); 647 this.options = extend( {}, this.options ); 648 649 if ( typeof options === 'function' ) { 650 onAlways = options; 651 } else { 652 extend( this.options, options ); 653 } 654 655 if ( onAlways ) { 656 this.on( 'always', onAlways ); 657 } 658 659 this.getImages(); 660 661 if ( $ ) { 662 // add jQuery Deferred object 663 this.jqDeferred = new $.Deferred(); 664 } 665 666 // HACK check async to allow time to bind listeners 667 var _this = this; 668 setTimeout( function() { 669 _this.check(); 670 }); 671 } 672 673 ImagesLoaded.prototype = new EventEmitter(); 674 675 ImagesLoaded.prototype.options = {}; 676 677 ImagesLoaded.prototype.getImages = function() { 678 this.images = []; 679 680 // filter & find items if we have an item selector 681 for ( var i=0, len = this.elements.length; i < len; i++ ) { 682 var elem = this.elements[i]; 683 // filter siblings 684 if ( elem.nodeName === 'IMG' ) { 685 this.addImage( elem ); 686 } 687 // find children 688 // no non-element nodes, #143 689 var nodeType = elem.nodeType; 690 if ( !nodeType || !( nodeType === 1 || nodeType === 9 || nodeType === 11 ) ) { 691 continue; 692 } 693 var childElems = elem.querySelectorAll('img'); 694 // concat childElems to filterFound array 695 for ( var j=0, jLen = childElems.length; j < jLen; j++ ) { 696 var img = childElems[j]; 697 this.addImage( img ); 698 } 699 } 700 }; 701 702 /** 703 * @param {Image} img 704 */ 705 ImagesLoaded.prototype.addImage = function( img ) { 706 var loadingImage = new LoadingImage( img ); 707 this.images.push( loadingImage ); 708 }; 709
710 ImagesLoaded.prototype.check = function() { 711 var _this = this; 712 var checkedCount = 0; 713 var length = this.images.length; 714 this.hasAnyBroken = false; 715 // complete if no images 716 if ( !length ) { 717 this.complete(); 718 return; 719 } 720 721 function onConfirm( image, message ) { 722 if ( _this.options.debug && hasConsole ) { 723 console.log( 'confirm', image, message ); 724 } 725 726 _this.progress( image ); 727 checkedCount++; 728 if ( checkedCount === length ) { 729 _this.complete(); 730 } 731 return true; // bind once 732 } 733 734 for ( var i=0; i < length; i++ ) { 735 var loadingImage = this.images[i]; 736 loadingImage.on( 'confirm', onConfirm ); 737 loadingImage.check(); 738 } 739 }; 740 741 ImagesLoaded.prototype.progress = function( image ) { 742 this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded; 743 // HACK - Chrome triggers event before object properties have changed. #83 744 var _this = this; 745 setTimeout( function() { 746 _this.emit( 'progress', _this, image ); 747 if ( _this.jqDeferred && _this.jqDeferred.notify ) { 748 _this.jqDeferred.notify( _this, image ); 749 } 750 }); 751 }; 752 753 ImagesLoaded.prototype.complete = function() { 754 var eventName = this.hasAnyBroken ? 'fail' : 'done'; 755 this.isComplete = true; 756 var _this = this; 757 // HACK - another setTimeout so that confirm happens after progress 758 setTimeout( function() { 759 _this.emit( eventName, _this ); 760 _this.emit( 'always', _this ); 761 if ( _this.jqDeferred ) { 762 var jqMethod = _this.hasAnyBroken ? 'reject' : 'resolve'; 763 _this.jqDeferred[ jqMethod ]( _this ); 764 } 765 }); 766 }; 767 768 // -------------------------- jquery -------------------------- // 769 770 if ( $ ) { 771 $.fn.imagesLoaded = function( options, callback ) { 772 var instance = new ImagesLoaded( this, options, callback ); 773 return instance.jqDeferred.promise( $(this) ); 774 }; 775 } 776 777 778 // -------------------------- -------------------------- // 779 780 function LoadingImage( img ) { 781 this.img = img; 782 } 783 784 LoadingImage.prototype = new EventEmitter(); 785 786 LoadingImage.prototype.check = function() { 787 // first check cached any previous images that have same src 788 var resource = cache[ this.img.src ] || new Resource( this.img.src ); 789 if ( resource.isConfirmed ) { 790 this.confirm( resource.isLoaded, 'cached was confirmed' ); 791 return; 792 } 793 794 // If complete is true and browser supports natural sizes, 795 // try to check for image status manually. 796 if ( this.img.complete && this.img.naturalWidth !== undefined ) { 797 // report based on naturalWidth 798 this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); 799 return; 800 } 801 802 // If none of the checks above matched, simulate loading on detached element. 803 var _this = this; 804 resource.on( 'confirm', function( resrc, message ) { 805 _this.confirm( resrc.isLoaded, message ); 806 return true; 807 }); 808 809 resource.check(); 810 }; 811 812 LoadingImage.prototype.confirm = function( isLoaded, message ) { 813 this.isLoaded = isLoaded; 814 this.emit( 'confirm', this, message ); 815 }; 816 817 // -------------------------- Resource -------------------------- // 818 819 // Resource checks each src, only once 820 // separate class from LoadingImage to prevent memory leaks. See #115 821 822 var cache = {}; 823 824 function Resource( src ) { 825 this.src = src; 826 // add to cache 827 cache[ src ] = this; 828 } 829 830 Resource.prototype = new EventEmitter(); 831 832 Resource.prototype.check = function() { 833 // only trigger checking once 834 if ( this.isChecked ) { 835 return; 836 } 837 // simulate loading on detached element 838 var proxyImage = new Image(); 839 eventie.bind( proxyImage, 'load', this ); 840 eventie.bind( proxyImage, 'error', this ); 841 proxyImage.src = this.src; 842 // set flag 843 this.isChecked = true; 844 }; 845 846 // ----- events ----- // 847 848 // trigger specified handler for event type 849 Resource.prototype.handleEvent = function( event ) { 850 var method = 'on' + event.type; 851 if ( this[ method ] ) { 852 this[ method ]( event ); 853 } 854 }; 855 856 Resource.prototype.onload = function( event ) { 857 this.confirm( true, 'onload' ); 858 this.unbindProxyEvents( event ); 859 }; 860 861 Resource.prototype.onerror = function( event ) { 862 this.confirm( false, 'onerror' ); 863 this.unbindProxyEvents( event ); 864 }; 865 866 // ----- confirm ----- // 867 868 Resource.prototype.confirm = function( isLoaded, message ) { 869 this.isConfirmed = true; 870 this.isLoaded = isLoaded;
871 this.emit( 'confirm', this, message ); 872 }; 873 874 Resource.prototype.unbindProxyEvents = function( event ) { 875 eventie.unbind( event.target, 'load', this ); 876 eventie.unbind( event.target, 'error', this ); 877 }; 878 879 // ----- ----- // 880 881 return ImagesLoaded; 882 883}); 884 885/*global jQuery */ 886/*jshint browser:true */ 887/*! 888* FitVids 1.1 889* 890* Copyright 2013, Chris Coyier - http://css-tricks.com + Dave Rupert - http://daverupert.com 891* Credit to Thierry Koblentz - http://www.alistapart.com/articles/creating-intrinsic-ratios-for-video/ 892* Released under the WTFPL license - http://sam.zoy.org/wtfpl/ 893* 894*/ 895 896;(function( $ ){ 897 898 'use strict'; 899 900 $.fn.fitVids = function( options ) { 901 var settings = { 902 customSelector: null, 903 ignore: null 904 }; 905 906 if(!document.getElementById('fit-vids-style')) { 907 // appendStyles: https://github.com/toddmotto/fluidvids/blob/master/dist/fluidvids.js 908 var head = document.head || document.getElementsByTagName('head')[0]; 909 var css = '.fluid-width-video-wrapper{width:100%;position:relative;padding:0;}.fluid-width-video-wrapper iframe,.fluid-width-video-wrapper object,.fluid-width-video-wrapper embed {position:absolute;top:0;left:0;width:100%;height:100%;}'; 910 var div = document.createElement("div"); 911 div.innerHTML = '<p>x</p><style id="fit-vids-style">' + css + '</style>'; 912 head.appendChild(div.childNodes[1]); 913 } 914 915 if ( options ) { 916 $.extend( settings, options ); 917 } 918 919 return this.each(function(){ 920 var selectors = [ 921 'iframe[src*="player.vimeo.com"]', 922 'iframe[src*="youtube.com"]', 923 'iframe[src*="youtube-nocookie.com"]', 924 'iframe[src*="kickstarter.com"][src*="video.html"]', 925 'object', 926 'embed' 927 ]; 928 929 if (settings.customSelector) { 930 selectors.push(settings.customSelector); 931 } 932 933 var ignoreList = '.fitvidsignore'; 934 935 if(settings.ignore) { 936 ignoreList = ignoreList + ', ' + settings.ignore; 937 } 938 939 var $allVideos = $(this).find(selectors.join(',')); 940 $allVideos = $allVideos.not('object object'); // SwfObj conflict patch 941 $allVideos = $allVideos.not(ignoreList); // Disable FitVids on this video. 942 943 $allVideos.each(function(count){ 944 var $this = $(this); 945 if($this.parents(ignoreList).length > 0) { 946 return; // Disable FitVids on this video. 947 } 948 if (this.tagName.toLowerCase() === 'embed' && $this.parent('object').length || $this.parent('.fluid-width-video-wrapper').length) { return; } 949 if ((!$this.css('height') && !$this.css('width')) && (isNaN($this.attr('height')) || isNaN($this.attr('width')))) 950 { 951 $this.attr('height', 9); 952 $this.attr('width', 16); 953 } 954 var height = ( this.tagName.toLowerCase() === 'object' || ($this.attr('height') && !isNaN(parseInt($this.attr('height'), 10))) ) ? parseInt($this.attr('height'), 10) : $this.height(), 955 width = !isNaN(parseInt($this.attr('width'), 10)) ? parseInt($this.attr('width'), 10) : $this.width(), 956 aspectRatio = height / width; 957 if(!$this.attr('id')){ 958 var videoID = 'fitvid' + count; 959 $this.attr('id', videoID); 960 } 961 $this.wrap('<div class="fluid-width-video-wrapper"></div>').parent('.fluid-width-video-wrapper').css('padding-top', (aspectRatio * 100)+'%'); 962 $this.removeAttr('height').removeAttr('width'); 963 }); 964 }); 965 }; 966// Works with either jQuery or Zepto 967})( window.jQuery || window.Zepto ); 968 969/* 970 Sticky-kit v1.1.1 | WTFPL | Leaf Corcoran 2014 | http://leafo.net 971*/ 972(function(){var k,e;k=this.jQuery||window.jQuery;e=k(window);k.fn.stick_in_parent=function(d){var v,y,n,p,h,C,s,G,q,H;null==d&&(d={});s=d.sticky_class;y=d.inner_scrolling;C=d.recalc_every;h=d.parent;p=d.offset_top;n=d.spacer;v=d.bottoming;null==p&&(p=0);null==h&&(h=void 0);null==y&&(y=!0);null==s&&(s="is_stuck");null==v&&(v=!0);G=function(a,d,q,z,D,t,r,E){var u,F,m,A,c,f,B,w,x,g,b;if(!a.data("sticky_kit")){a.data("sticky_kit",!0);f=a.parent();null!=h&&(f=f.closest(h));if(!f.length)throw"failed to find stick parent"; 973u=m=!1;(g=null!=n?n&&a.closest(n):k("<div />"))&&g.css("position",a.css("position"));B=function(){var c,e,l;if(!E&&(c=parseInt(f.css("border-top-width"),10),e=parseInt(f.css("padding-top"),10),d=parseInt(f.css("padding-bottom"),10),q=f.offset().top+c+e,z=f.height(),m&&(u=m=!1,null==n&&(a.insertAfter(g),g.detach()),a.css({position:"",top:"",width:"",bottom:""}).removeClass(s),l=!0),D=a.offset().top-parseInt(a.css("margin-top"),10)-p,t=a.outerHeight(!0),r=a.css("float"),g&&g.css({width:a.outerWidth(!0), 974height:t,display:a.css("display"),"vertical-align":a.css("vertical-align"),"float":r}),l))return b()};B();if(t!==z)return A=void 0,c=p,x=C,b=function(){var b,k,l,h;if(!E&&(null!=x&&(--x,0>=x&&(x=C,B())),l=e.scrollTop(),null!=A&&(k=l-A),A=l,m?(v&&(h=l+t+c>z+q,u&&!h&&(u=!1,a.css({position:"fixed",bottom:"",top:c}).trigger("sticky_kit:unbottom"))),l<D&&(m=!1,c=p,null==n&&("left"!==r&&"right"!==r||a.insertAfter(g),g.detach()),b={position:"",width:"",top:""},a.css(b).removeClass(s).trigger("sticky_kit:unstick")), 975y&&(b=e.height(),t+p>b&&!u&&(c-=k,c=Math.max(b-t,c),c=Math.min(p,c),m&&a.css({top:c+"px"})))):l>D&&(m=!0,b={position:"fixed",top:c},b.width="border-box"===a.css("box-sizing")?a.outerWidth()+"px":a.width()+"px",a.css(b).addClass(s),null==n&&(a.after(g),"left"!==r&&"right"!==r||g.append(a)),a.trigger("sticky_kit:stick")),m&&v&&(null==h&&(h=l+t+c>z+q),!u&&h)))return u=!0,"static"===f.css("position")&&f.css({position:"relative"}),a.css({position:"absolute",bottom:d,top:"auto"}).trigger("sticky_kit:bottom")}, 976w=function(){B();return b()},F=function(){E=!0;e.off("touchmove",b);e.off("scroll",b);e.off("resize",w);k(document.body).off("sticky_kit:recalc",w);a.off("sticky_kit:detach",F);a.removeData("sticky_kit");a.css({position:"",bottom:"",top:"",width:""});f.position("position","");if(m)return null==n&&("left"!==r&&"right"!==r||a.insertAfter(g),g.remove()),a.removeClass(s)},e.on("touchmove",b),e.on("scroll",b),e.on("resize",w),k(document.body).on("sticky_kit:recalc",w),a.on("sticky_kit:detach",F),setTimeout(b, 9770)}};q=0;for(H=this.length;q<H;q++)d=this[q],G(k(d));return this}}).call(this); 978 979
vendor: 9,028 bytes, lines 980-986
980/*! 981Waypoints - 4.0.1 982Copyright © 2011-2016 Caleb Troughton 983Licensed under the MIT license. 984https://github.com/imakewebthings/waypoints/blob/master/licenses.txt 985*/ 986!function(){"use strict";function t(o){if(!o)throw new Error("No options passed to Waypoint constructor");if(!o.element)throw new Error("No element option passed to Waypoint constructor");if(!o.handler)throw new Error("No handler option passed to Waypoint constructor");this.key="waypoint-"+e,this.options=t.Adapter.extend({},t.defaults,o),this.element=this.options.element,this.adapter=new t.Adapter(this.element),this.callback=o.handler,this.axis=this.options.horizontal?"horizontal":"vertical",this.enabled=this.options.enabled,this.triggerPoint=null,this.group=t.Group.findOrCreate({name:this.options.group,axis:this.axis}),this.context=t.Context.findOrCreateByElement(this.options.context),t.offsetAliases[this.options.offset]&&(this.options.offset=t.offsetAliases[this.options.offset]),this.group.add(this),this.context.add(this),i[this.key]=this,e+=1}var e=0,i={};t.prototype.queueTrigger=function(t){this.group.queueTrigger(this,t)},t.prototype.trigger=function(t){this.enabled&&this.callback&&this.callback.apply(this,t)},t.prototype.destroy=function(){this.context.remove(this),this.group.remove(this),delete i[this.key]},t.prototype.disable=function(){return this.enabled=!1,this},t.prototype.enable=function(){return this.context.refresh(),this.enabled=!0,this},t.prototype.next=function(){return this.group.next(this)},t.prototype.previous=function(){return this.group.previous(this)},t.invokeAll=function(t){var e=[];for(var o in i)e.push(i[o]);for(var n=0,r=e.length;r>n;n++)e[n][t]()},t.destroyAll=function(){t.invokeAll("destroy")},t.disableAll=function(){t.invokeAll("disable")},t.enableAll=function(){t.Context.refreshAll();for(var e in i)i[e].enabled=!0;return this},t.refreshAll=function(){t.Context.refreshAll()},t.viewportHeight=function(){return window.innerHeight||document.documentElement.clientHeight},t.viewportWidth=function(){return document.documentElement.clientWidth},t.adapters=[],t.defaults={context:window,continuous:!0,enabled:!0,group:"default",horizontal:!1,offset:0},t.offsetAliases={"bottom-in-view":function(){return this.context.innerHeight()-this.adapter.outerHeight()},"right-in-view":function(){return this.context.innerWidth()-this.adapter.outerWidth()}},window.Waypoint=t}(),function(){"use strict";function t(t){window.setTimeout(t,1e3/60)}function e(t){this.element=t,this.Adapter=n.Adapter,this.adapter=new this.Adapter(t),this.key="waypoint-context-"+i,this.didScroll=!1,this.didResize=!1,this.oldScroll={x:this.adapter.scrollLeft(),y:this.adapter.scrollTop()},this.waypoints={vertical:{},horizontal:{}},t.waypointContextKey=this.key,o[t.waypointContextKey]=this,i+=1,n.windowContext||(n.windowContext=!0,n.windowContext=new e(window)),this.createThrottledScrollHandler(),this.createThrottledResizeHandler()}var i=0,o={},n=window.Waypoint,r=window.onload;e.prototype.add=function(t){var e=t.options.horizontal?"horizontal":"vertical";this.waypoints[e][t.key]=t,this.refresh()},e.prototype.checkEmpty=function(){var t=this.Adapter.isEmptyObject(this.waypoints.horizontal),e=this.Adapter.isEmptyObject(this.waypoints.vertical),i=this.element==this.element.window;t&&e&&!i&&(this.adapter.off(".waypoints"),delete o[this.key])},e.prototype.createThrottledResizeHandler=function(){function t(){e.handleResize(),e.didResize=!1}var e=this;this.adapter.on("resize.waypoints",function(){e.didResize||(e.didResize=!0,n.requestAnimationFrame(t))})},e.prototype.createThrottledScrollHandler=function(){function t(){e.handleScroll(),e.didScroll=!1}var e=this;this.adapter.on("scroll.waypoints",function(){(!e.didScroll||n.isTouch)&&(e.didScroll=!0,n.requestAnimationFrame(t))})},e.prototype.handleResize=function(){n.Context.refreshAll()},e.prototype.handleScroll=function(){var t={},e={horizontal:{newScroll:this.adapter.scrollLeft(),oldScroll:this.oldScroll.x,forward:"right",backward:"left"},vertical:{newScroll:this.adapter.scrollTop(),oldScroll:this.oldScroll.y,forward:"down",backward:"up"}};for(var i in e){var o=e[i],n=o.newScroll>o.oldScroll,r=n?o.forward:o.backward;for(var s in this.waypoints[i]){var a=this.waypoints[i][s];if(null!==a.triggerPoint){var l=o.oldScroll<a.triggerPoint,h=o.newScroll>=a.triggerPoint,p=l&&h,u=!l&&!h;(p||u)&&(a.queueTrigger(r),t[a.group.id]=a.group)}}}for(var c in t)t[c].flushTriggers();this.oldScroll={x:e.horizontal.newScroll,y:e.vertical.newScroll}},e.prototype.innerHeight=function(){return this.element==this.element.window?n.viewportHeight():this.adapter.innerHeight()},e.prototype.remove=function(t){delete this.waypoints[t.axis][t.key],this.checkEmpty()},e.prototype.innerWidth=function(){return this.element==this.element.window?n.viewportWidth():this.adapter.innerWidth()},e.prototype.destroy=function(){var t=[];for(var e in this.waypoints)for(var i in this.waypoints[e])t.push(this.waypoints[e][i]);for(var o=0,n=t.length;n>o;o++)t[o].destroy()},e.prototype.refresh=function(){var t,e=this.element==this.element.window,i=e?void 0:this.adapter.offset(),o={};this.handleScroll(),t={horizontal:{contextOffset:e?0:i.left,contextScroll:e?0:this.oldScroll.x,contextDimension:this.innerWidth(),oldScroll:this.oldScroll.x,forward:"right",backward:"left",offsetProp:"left"},vertical:{contextOffset:e?0:i.top,contextScroll:e?0:this.oldScroll.y,contextDimension:this.innerHeight(),oldScroll:this.oldScroll.y,forward:"down",backward:"up",offsetProp:"top"}};for(var r in t){var s=t[r];for(var a in this.waypoints[r]){var l,h,p,u,c,d=this.waypoints[r][a],f=d.options.offset,w=d.triggerPoint,y=0,g=null==w;d.element!==d.element.window&&(y=d.adapter.offset()[s.offsetProp]),"function"==typeof f?f=f.apply(d):"string"==typeof f&&(f=parseFloat(f),d.options.offset.indexOf("%")>-1&&(f=Math.ceil(s.contextDimension*f/100))),l=s.contextScroll-s.contextOffset,d.triggerPoint=Math.floor(y+l-f),h=w<s.oldScroll,p=d.triggerPoint>=s.oldScroll,u=h&&p,c=!h&&!p,!g&&u?(d.queueTrigger(s.backward),o[d.group.id]=d.group):!g&&c?(d.queueTrigger(s.forward),o[d.group.id]=d.group):g&&s.oldScroll>=d.triggerPoint&&(d.queueTrigger(s.forward),o[d.group.id]=d.group)}}return n.requestAnimationFrame(function(){for(var t in o)o[t].flushTriggers()}),this},e.findOrCreateByElement=function(t){return e.findByElement(t)||new e(t)},e.refreshAll=function(){for(var t in o)o[t].refresh()},e.findByElement=function(t){return o[t.waypointContextKey]},window.onload=function(){r&&r(),e.refreshAll()},n.requestAnimationFrame=function(e){var i=window.requestAnimationFrame||window.mozRequestAnimationFrame||window.webkitRequestAnimationFrame||t;i.call(window,e)},n.Context=e}(),function(){"use strict";function t(t,e){return t.triggerPoint-e.triggerPoint}function e(t,e){return e.triggerPoint-t.triggerPoint}function i(t){this.name=t.name,this.axis=t.axis,this.id=this.name+"-"+this.axis,this.waypoints=[],this.clearTriggerQueues(),o[this.axis][this.name]=this}var o={vertical:{},horizontal:{}},n=window.Waypoint;i.prototype.add=function(t){this.waypoints.push(t)},i.prototype.clearTriggerQueues=function(){this.triggerQueues={up:[],down:[],left:[],right:[]}},i.prototype.flushTriggers=function(){for(var i in this.triggerQueues){var o=this.triggerQueues[i],n="up"===i||"left"===i;o.sort(n?e:t);for(var r=0,s=o.length;s>r;r+=1){var a=o[r];(a.options.continuous||r===o.length-1)&&a.trigger([i])}}this.clearTriggerQueues()},i.prototype.next=function(e){this.waypoints.sort(t);var i=n.Adapter.inArray(e,this.waypoints),o=i===this.waypoints.length-1;return o?null:this.waypoints[i+1]},i.prototype.previous=function(e){this.waypoints.sort(t);var i=n.Adapter.inArray(e,this.waypoints);return i?this.waypoints[i-1]:null},i.prototype.queueTrigger=function(t,e){this.triggerQueues[e].push(t)},i.prototype.remove=function(t){var e=n.Adapter.inArray(t,this.waypoints);e>-1&&this.waypoints.splice(e,1)},i.prototype.first=function(){return this.waypoints[0]},i.prototype.last=function(){return this.waypoints[this.waypoints.length-1]},i.findOrCreate=function(t){return o[t.axis][t.name]||new i(t)},n.Group=i}(),function(){"use strict";function t(t){this.$element=e(t)}var e=window.jQuery,i=window.Waypoint;e.each(["innerHeight","innerWidth","off","offset","on","outerHeight","outerWidth","scrollLeft","scrollTop"],function(e,i){t.prototype[i]=function(){var t=Array.prototype.slice.call(arguments);return this.$element[i].apply(this.$element,t)}}),e.each(["extend","inArray","isEmptyObject"],function(i,o){t[o]=e[o]}),i.adapters.push({name:"jquery",Adapter:t}),i.Adapter=t}(),function(){"use strict";function t(t){return function(){var i=[],o=arguments[0];return t.isFunction(arguments[0])&&(o=t.extend({},arguments[1]),o.handler=arguments[0]),this.each(function(){var n=t.extend({},o,{element:this});"string"==typeof n.context&&(n.context=t(this).closest(n.context)[0]),i.push(new e(n))}),i}}var e=window.Waypoint;window.jQuery&&(window.jQuery.fn.waypoint=t(window.jQuery)),window.Zepto&&(window.Zepto.fn.waypoint=t(window.Zepto))}();
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.