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 );