diff options
Diffstat (limited to 'imagesloaded.js')
-rw-r--r-- | imagesloaded.js | 126 |
1 files changed, 98 insertions, 28 deletions
diff --git a/imagesloaded.js b/imagesloaded.js index 58bf2bf..0fb802a 100644 --- a/imagesloaded.js +++ b/imagesloaded.js @@ -143,6 +143,11 @@ function makeArray( obj ) { if ( elem.nodeName == 'IMG' ) { this.addImage( elem ); } + // + if ( this.options.background === true ) { + this.addElementBackgroundImages( elem ); + } + // find children // no non-element nodes, #143 var nodeType = elem.nodeType; @@ -163,6 +168,30 @@ function makeArray( obj ) { 11: true }; + ImagesLoaded.prototype.addElementBackgroundImages = function( elem ) { + var style = getStyle( elem ); + // get `url("http://example.com/foo.jpg")`, possible multiples + var multiMatches = style.backgroundImage.match( /url\(['"]*[^'"\)]+['"]*\)/gi ); + if ( !multiMatches || !multiMatches.length ) { + return; + } + var urls = []; + for ( var i=0; i < multiMatches.length; i++ ) { + var multiMatch = multiMatches[i]; + // get `http://example.com/foo.jpg` + var urlMatches = multiMatch.match( /url\(['"]*([^'"\)]+)['"]*\)/i ); + var url = urlMatches && urlMatches[1]; + if ( url ) { + this.addBackground( url, elem ); + } + } + }; + + // IE8 + var getStyle = window.getComputedStyle || function( elem ) { + return elem.currentStyle; + }; + /** * @param {Image} img */ @@ -171,47 +200,52 @@ function makeArray( obj ) { this.images.push( loadingImage ); }; + ImagesLoaded.prototype.addBackground = function( url, elem ) { + var background = new Background( url, elem ); + this.images.push( background ); + }; + ImagesLoaded.prototype.check = function() { var _this = this; - var checkedCount = 0; - var length = this.images.length; + this.progressedCount = 0; this.hasAnyBroken = false; // complete if no images - if ( !length ) { + if ( !this.images.length ) { this.complete(); return; } - function onConfirm( image, message ) { - if ( _this.options.debug && console ) { - console.log( 'confirm', image, message ); - } - - _this.progress( image ); - checkedCount++; - if ( checkedCount == length ) { - _this.complete(); - } - return true; // bind once + function onProgress( image, elem, message ) { + _this.progress( image, elem, message ); } - for ( var i=0; i < length; i++ ) { + for ( var i=0; i < this.images.length; i++ ) { var loadingImage = this.images[i]; - loadingImage.on( 'confirm', onConfirm ); + loadingImage.once( 'progress', onProgress ); loadingImage.check(); } }; - ImagesLoaded.prototype.progress = function( image ) { + ImagesLoaded.prototype.progress = function( image, elem, message ) { + this.progressedCount++; + this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded; // HACK - Chrome triggers event before object properties have changed. #83 var _this = this; setTimeout( function() { - _this.emit( 'progress', _this, image ); + _this.emit( 'progress', _this, image, elem ); if ( _this.jqDeferred && _this.jqDeferred.notify ) { _this.jqDeferred.notify( _this, image ); } + // check if completed + if ( _this.progressedCount == _this.images.length ) { + _this.complete(); + } }); + + if ( this.options.debug && console ) { + console.log( 'progress: ' + message, image, elem ); + } }; ImagesLoaded.prototype.complete = function() { @@ -219,14 +253,12 @@ function makeArray( obj ) { this.isComplete = true; var _this = this; // HACK - another setTimeout so that confirm happens after progress - setTimeout( function() { - _this.emit( eventName, _this ); - _this.emit( 'always', _this ); - if ( _this.jqDeferred ) { - var jqMethod = _this.hasAnyBroken ? 'reject' : 'resolve'; - _this.jqDeferred[ jqMethod ]( _this ); - } - }); + _this.emit( eventName, _this ); + _this.emit( 'always', _this ); + if ( _this.jqDeferred ) { + var jqMethod = _this.hasAnyBroken ? 'reject' : 'resolve'; + _this.jqDeferred[ jqMethod ]( _this ); + } }; // -------------------------- -------------------------- // @@ -240,7 +272,8 @@ function makeArray( obj ) { LoadingImage.prototype.check = function() { // If complete is true and browser supports natural sizes, // try to check for image status manually. - if ( this.img.complete && this.img.naturalWidth !== undefined ) { + var isComplete = this.getIsImageComplete(); + if ( isComplete ) { // report based on naturalWidth this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); return; @@ -256,9 +289,13 @@ function makeArray( obj ) { this.proxyImage.src = this.img.src; }; + LoadingImage.prototype.getIsImageComplete = function() { + return this.img.complete && this.img.naturalWidth !== undefined; + }; + LoadingImage.prototype.confirm = function( isLoaded, message ) { this.isLoaded = isLoaded; - this.emit( 'confirm', this, message ); + this.emit( 'progress', this, this.img, message ); }; // ----- events ----- // @@ -288,6 +325,39 @@ function makeArray( obj ) { eventie.unbind( this.img, 'error', this ); }; + // -------------------------- Background -------------------------- // + + function Background( url, element ) { + this.url = url; + this.element = element; + this.img = new Image(); + } + + // inherit LoadingImage prototype + Background.prototype = new LoadingImage(); + + Background.prototype.check = function() { + eventie.bind( this.img, 'load', this ); + eventie.bind( this.img, 'error', this ); + this.img.src = this.url; + // check if image is already complete + var isComplete = this.getIsImageComplete(); + if ( isComplete ) { + this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); + this.unbindEvents(); + } + }; + + Background.prototype.unbindEvents = function() { + eventie.unbind( this.img, 'load', this ); + eventie.unbind( this.img, 'error', this ); + }; + + Background.prototype.confirm = function( isLoaded, message ) { + this.isLoaded = isLoaded; + this.emit( 'progress', this, this.element, message ); + }; + // -------------------------- jQuery -------------------------- // ImagesLoaded.makeJQueryPlugin = function( jQuery ) { |