Skip to content

Commit

Permalink
first pass at background image support. Ref #29
Browse files Browse the repository at this point in the history
  • Loading branch information
desandro committed Oct 28, 2015
1 parent 08596e9 commit e20c078
Show file tree
Hide file tree
Showing 3 changed files with 179 additions and 28 deletions.
126 changes: 98 additions & 28 deletions imagesloaded.js
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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
*/
Expand All @@ -171,62 +200,65 @@ 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() {
var eventName = this.hasAnyBroken ? 'fail' : 'done';
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 );
}
};

// -------------------------- -------------------------- //
Expand All @@ -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;
Expand All @@ -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 ----- //
Expand Down Expand Up @@ -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 ) {
Expand Down
29 changes: 29 additions & 0 deletions sandbox/background/css/background.css
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
.box {
width: 300px;
height: 300px;
margin: 0 20px 20px 0;
border: 1px solid;
display: inline-block;
}

.orange-tree {
background: url('http://i.imgur.com/bwy74ok.jpg');
background-size: cover;
}

.thunder-cloud {
background: url('../../../test/img/thunder-cloud.jpg');
background-size: contain;
}

.multi1 {
background:
url("http://i.imgur.com/ZAVN3.png"),
url('http://i.imgur.com/6UdOxeB.png') bottom right,
url(http://i.imgur.com/LkmcILl.jpg);
background-size: cover;
}

.blue {
background: #09F;
}
52 changes: 52 additions & 0 deletions sandbox/background/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />

<title>background</title>

<!-- put in separate folder so JS path is different from CSS path -->
<link rel="stylesheet" href="css/background.css" >

</head>
<body>

<h1>background</h1>

<div class="box orange-tree"></div>

<div class="box thunder-cloud"></div>

<div class="box multi1"></div>

<div class="box blue"></div>

<script src="../../bower_components/eventEmitter/EventEmitter.js"></script>
<script src="../../bower_components/eventie/eventie.js"></script>
<script src="../../imagesloaded.js"></script>
<script>

var imgLoad0 = imagesLoaded( '.orange-tree', { background: true }, function() {
console.log('orange tree bg images loaded', imgLoad0.images.length );
});

var imgLoad1 = imagesLoaded( '.thunder-cloud', { background: true }, function() {
console.log('thunder cloud bg images loaded', imgLoad1.images.length);
});

var imgLoad2 = imagesLoaded( '.multi1', { background: true }, function() {
console.log('multi1 bg images loaded', imgLoad2.images.length);
});

var imgLoad3 = imagesLoaded( '.box', { background: true }, function() {
console.log('.box bg images loaded', imgLoad3.images.length);
});
imgLoad3.on('progress', function( instance, image, element ) {
console.log( 'progress on .box', image.img.src, element.className );
})

</script>

</body>
</html>

0 comments on commit e20c078

Please sign in to comment.