Team:Team:NCTU Formosa/js/imagesloaded

From 2013.igem.org

/*!

* imagesLoaded v3.0.2
* JavaScript is all like "You images are done yet or what?"
*/

( function( window ) {

'use strict';

var $ = window.jQuery; var console = window.console; var hasConsole = typeof console !== 'undefined';

// -------------------------- helpers -------------------------- //

// extend objects function extend( a, b ) {

 for ( var prop in b ) {
   a[ prop ] = b[ prop ];
 }
 return a;

}

var objToString = Object.prototype.toString; function isArray( obj ) {

 return objToString.call( obj ) === '[object Array]';

}

// turn element or nodeList into an array function makeArray( obj ) {

 var ary = [];
 if ( isArray( obj ) ) {
   // use object if already an array
   ary = obj;
 } else if ( typeof obj.length === 'number' ) {
   // convert nodeList to array
   for ( var i=0, len = obj.length; i < len; i++ ) {
     ary.push( obj[i] );
   }
 } else {
   // array of single index
   ary.push( obj );
 }
 return ary;

}

// -------------------------- -------------------------- //

function defineImagesLoaded( EventEmitter, eventie ) {

 /**
  * @param {Array, Element, NodeList, String} elem
  * @param {Object or Function} options - if function, use as callback
  * @param {Function} onAlways - callback function
  */
 function ImagesLoaded( elem, options, onAlways ) {
   // coerce ImagesLoaded() without new, to be new ImagesLoaded()
   if ( !( this instanceof ImagesLoaded ) ) {
     return new ImagesLoaded( elem, options );
   }
   // use elem as selector string
   if ( typeof elem === 'string' ) {
     elem = document.querySelectorAll( elem );
   }
   this.elements = makeArray( elem );
   this.options = extend( {}, this.options );
   if ( typeof options === 'function' ) {
     onAlways = options;
   } else {
     extend( this.options, options );
   }
   if ( onAlways ) {
     this.on( 'always', onAlways );
   }
   this.getImages();
   if ( $ ) {
     // add jQuery Deferred object
     this.jqDeferred = new $.Deferred();
   }
   // HACK check async to allow time to bind listeners
   var _this = this;
   setTimeout( function() {
     _this.check();
   });
 }
 ImagesLoaded.prototype = new EventEmitter();
 ImagesLoaded.prototype.options = {};
 ImagesLoaded.prototype.getImages = function() {
   this.images = [];
   // filter & find items if we have an item selector
   for ( var i=0, len = this.elements.length; i < len; i++ ) {
     var elem = this.elements[i];
     // filter siblings
     if ( elem.nodeName === 'IMG' ) {
       this.addImage( elem );
     }
     // find children
     var childElems = elem.querySelectorAll('img');
     // concat childElems to filterFound array
     for ( var j=0, jLen = childElems.length; j < jLen; j++ ) {
       var img = childElems[j];
       this.addImage( img );
     }
   }
 };
 /**
  * @param {Image} img
  */
 ImagesLoaded.prototype.addImage = function( img ) {
   var loadingImage = new LoadingImage( img );
   this.images.push( loadingImage );
 };
 ImagesLoaded.prototype.check = function() {
   var _this = this;
   var checkedCount = 0;
   var length = this.images.length;
   this.hasAnyBroken = false;
   // complete if no images
   if ( !length ) {
     this.complete();
     return;
   }
   function onConfirm( image, message ) {
     if ( _this.options.debug && hasConsole ) {
       console.log( 'confirm', image, message );
     }
     _this.progress( image );
     checkedCount++;
     if ( checkedCount === length ) {
       _this.complete();
     }
     return true; // bind once
   }
   for ( var i=0; i < length; i++ ) {
     var loadingImage = this.images[i];
     loadingImage.on( 'confirm', onConfirm );
     loadingImage.check();
   }
 };
 ImagesLoaded.prototype.progress = function( image ) {
   this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
   this.emit( 'progress', this, image );
   if ( this.jqDeferred ) {
     this.jqDeferred.notify( this, image );
   }
 };
 ImagesLoaded.prototype.complete = function() {
   var eventName = this.hasAnyBroken ? 'fail' : 'done';
   this.isComplete = true;
   this.emit( eventName, this );
   this.emit( 'always', this );
   if ( this.jqDeferred ) {
     var jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';
     this.jqDeferred[ jqMethod ]( this );
   }
 };
 // -------------------------- jquery -------------------------- //
 if ( $ ) {
   $.fn.imagesLoaded = function( options, callback ) {
     var instance = new ImagesLoaded( this, options, callback );
     return instance.jqDeferred.promise( $(this) );
   };
 }


 // --------------------------  -------------------------- //
 var cache = {};
 function LoadingImage( img ) {
   this.img = img;
 }
 LoadingImage.prototype = new EventEmitter();
 LoadingImage.prototype.check = function() {
   // first check cached any previous images that have same src
   var cached = cache[ this.img.src ];
   if ( cached ) {
     this.useCached( cached );
     return;
   }
   // add this to cache
   cache[ this.img.src ] = this;
   // If complete is true and browser supports natural sizes,
   // try to check for image status manually.
   if ( this.img.complete && this.img.naturalWidth !== undefined ) {
     // report based on naturalWidth
     this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
     return;
   }
   // If none of the checks above matched, simulate loading on detached element.
   var proxyImage = this.proxyImage = new Image();
   eventie.bind( proxyImage, 'load', this );
   eventie.bind( proxyImage, 'error', this );
   proxyImage.src = this.img.src;
 };
 LoadingImage.prototype.useCached = function( cached ) {
   if ( cached.isConfirmed ) {
     this.confirm( cached.isLoaded, 'cached was confirmed' );
   } else {
     var _this = this;
     cached.on( 'confirm', function( image ) {
       _this.confirm( image.isLoaded, 'cache emitted confirmed' );
       return true; // bind once
     });
   }
 };
 LoadingImage.prototype.confirm = function( isLoaded, message ) {
   this.isConfirmed = true;
   this.isLoaded = isLoaded;
   this.emit( 'confirm', this, message );
 };
 // trigger specified handler for event type
 LoadingImage.prototype.handleEvent = function( event ) {
   var method = 'on' + event.type;
   if ( this[ method ] ) {
     this[ method ]( event );
   }
 };
 LoadingImage.prototype.onload = function() {
   this.confirm( true, 'onload' );
   this.unbindProxyEvents();
 };
 LoadingImage.prototype.onerror = function() {
   this.confirm( false, 'onerror' );
   this.unbindProxyEvents();
 };
 LoadingImage.prototype.unbindProxyEvents = function() {
   eventie.unbind( this.proxyImage, 'load', this );
   eventie.unbind( this.proxyImage, 'error', this );
 };
 // -----  ----- //
 return ImagesLoaded;

}

// -------------------------- transport -------------------------- //

if ( typeof define === 'function' && define.amd ) {

 // AMD
 define( [
     'eventEmitter',
     'eventie'
   ],
   defineImagesLoaded );

} else {

 // browser global
 window.imagesLoaded = defineImagesLoaded(
   window.EventEmitter,
   window.eventie
 );

}

})( window );