Repository: desandro/imagesloaded
Branch: master
Commit: 92de29b5a9a4
Files: 32
Total size: 60.0 KB
Directory structure:
gitextract_8bkypk_n/
├── .eslintrc.js
├── .gitignore
├── .nvmrc
├── LICENSE.md
├── README.md
├── bower.json
├── contributing.md
├── imagesloaded.js
├── imagesloaded.pkgd.js
├── package.json
├── sandbox/
│ ├── background/
│ │ ├── css/
│ │ │ └── background.css
│ │ └── index.html
│ ├── picture.html
│ └── progress/
│ ├── index.html
│ └── progress.js
├── tasks/
│ ├── dist.js
│ └── version.js
└── test/
├── css/
│ └── tests.css
├── index.html
└── unit/
├── append.js
├── background.js
├── basics.js
├── data-uri.js
├── jquery-fail.js
├── jquery-success.js
├── local-files.js
├── no-images.js
├── non-element.js
├── picture.js
├── selector-string.js
├── single-element.js
└── srcset.js
================================================
FILE CONTENTS
================================================
================================================
FILE: .eslintrc.js
================================================
/* eslint-env node */
module.exports = {
plugins: [ 'metafizzy' ],
extends: 'plugin:metafizzy/browser',
env: {
browser: true,
commonjs: true,
},
parserOptions: {
ecmaVersion: 2018,
},
globals: {
imagesLoaded: 'readonly',
QUnit: 'readonly',
},
rules: {
eqeqeq: [ 'error', 'smart' ],
'id-length': [ 'error', {
min: 2,
max: 30,
exceptions: [ 'x', 'y', 'z', 'i', 'j', 'a', 'b', 't', '$' ],
} ],
'new-cap': 'off',
},
ignorePatterns: [ '*pkgd*.js' ],
};
================================================
FILE: .gitignore
================================================
bower_components/
node_modules/
build/index.html
build/*.woff*
build/imagesloaded*.js
.netlify
================================================
FILE: .nvmrc
================================================
16
================================================
FILE: LICENSE.md
================================================
Copyright (c) 2011-2022 [David DeSandro](https://desandro.com) and [contributors](https://github.com/desandro/imagesloaded/graphs/contributors)
Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
================================================
FILE: README.md
================================================
# imagesLoaded
<p class="tagline">JavaScript is all like "You images done yet or what?"</p>
[imagesloaded.desandro.com](https://imagesloaded.desandro.com)
Detect when images have been loaded.
## Install
### Download
+ [imagesloaded.pkgd.min.js](https://unpkg.com/imagesloaded@5/imagesloaded.pkgd.min.js) minified
+ [imagesloaded.pkgd.js](https://unpkg.com/imagesloaded@5/imagesloaded.pkgd.js) un-minified
### CDN
``` html
<script src="https://unpkg.com/imagesloaded@5/imagesloaded.pkgd.min.js"></script>
<!-- or -->
<script src="https://unpkg.com/imagesloaded@5/imagesloaded.pkgd.js"></script>
```
### Package managers
Install via npm: `npm install imagesloaded`
Install via Yarn: `yarn add imagesloaded`
## jQuery
You can use imagesLoaded as a jQuery Plugin.
``` js
$('#container').imagesLoaded( function() {
// images have loaded
});
// options
$('#container').imagesLoaded( {
// options...
},
function() {
// images have loaded
}
);
```
`.imagesLoaded()` returns a [jQuery Deferred object](https://api.jquery.com/category/deferred-object/). This allows you to use `.always()`, `.done()`, `.fail()` and `.progress()`.
``` js
$('#container').imagesLoaded()
.always( function( instance ) {
console.log('all images loaded');
})
.done( function( instance ) {
console.log('all images successfully loaded');
})
.fail( function() {
console.log('all images loaded, at least one is broken');
})
.progress( function( instance, image ) {
var result = image.isLoaded ? 'loaded' : 'broken';
console.log( 'image is ' + result + ' for ' + image.img.src );
});
```
## Vanilla JavaScript
You can use imagesLoaded with vanilla JS.
``` js
imagesLoaded( elem, callback )
// options
imagesLoaded( elem, options, callback )
// you can use `new` if you like
new imagesLoaded( elem, callback )
```
+ `elem` _Element, NodeList, Array, or Selector String_
+ `options` _Object_
+ `callback` _Function_ - function triggered after all images have been loaded
Using a callback function is the same as binding it to the `always` event (see below).
``` js
// element
imagesLoaded( document.querySelector('#container'), function( instance ) {
console.log('all images are loaded');
});
// selector string
imagesLoaded( '#container', function() {...});
// multiple elements
var posts = document.querySelectorAll('.post');
imagesLoaded( posts, function() {...});
```
Bind events with vanilla JS with .on(), .off(), and .once() methods.
``` js
var imgLoad = imagesLoaded( elem );
function onAlways( instance ) {
console.log('all images are loaded');
}
// bind with .on()
imgLoad.on( 'always', onAlways );
// unbind with .off()
imgLoad.off( 'always', onAlways );
```
## Background
Detect when background images have loaded, in addition to `<img>`s.
Set `{ background: true }` to detect when the element's background image has loaded.
``` js
// jQuery
$('#container').imagesLoaded( { background: true }, function() {
console.log('#container background image loaded');
});
// vanilla JS
imagesLoaded( '#container', { background: true }, function() {
console.log('#container background image loaded');
});
```
[See jQuery demo](https://codepen.io/desandro/pen/pjVMPB) or [vanilla JS demo](https://codepen.io/desandro/pen/avKooW) on CodePen.
Set to a selector string like `{ background: '.item' }` to detect when the background images of child elements have loaded.
``` js
// jQuery
$('#container').imagesLoaded( { background: '.item' }, function() {
console.log('all .item background images loaded');
});
// vanilla JS
imagesLoaded( '#container', { background: '.item' }, function() {
console.log('all .item background images loaded');
});
```
[See jQuery demo](https://codepen.io/desandro/pen/avKoZL) or [vanilla JS demo](https://codepen.io/desandro/pen/vNrBGz) on CodePen.
## Events
### always
``` js
// jQuery
$('#container').imagesLoaded().always( function( instance ) {
console.log('ALWAYS - all images have been loaded');
});
// vanilla JS
imgLoad.on( 'always', function( instance ) {
console.log('ALWAYS - all images have been loaded');
});
```
Triggered after all images have been either loaded or confirmed broken.
+ `instance` _imagesLoaded_ - the imagesLoaded instance
### done
``` js
// jQuery
$('#container').imagesLoaded().done( function( instance ) {
console.log('DONE - all images have been successfully loaded');
});
// vanilla JS
imgLoad.on( 'done', function( instance ) {
console.log('DONE - all images have been successfully loaded');
});
```
Triggered after all images have successfully loaded without any broken images.
### fail
``` js
$('#container').imagesLoaded().fail( function( instance ) {
console.log('FAIL - all images loaded, at least one is broken');
});
// vanilla JS
imgLoad.on( 'fail', function( instance ) {
console.log('FAIL - all images loaded, at least one is broken');
});
```
Triggered after all images have been loaded with at least one broken image.
### progress
``` js
imgLoad.on( 'progress', function( instance, image ) {
var result = image.isLoaded ? 'loaded' : 'broken';
console.log( 'image is ' + result + ' for ' + image.img.src );
});
```
Triggered after each image has been loaded.
+ `instance` _imagesLoaded_ - the imagesLoaded instance
+ `image` _LoadingImage_ - the LoadingImage instance of the loaded image
<!-- sponsored -->
## Properties
### LoadingImage.img
_Image_ - The `img` element
### LoadingImage.isLoaded
_Boolean_ - `true` when the image has successfully loaded
### imagesLoaded.images
Array of _LoadingImage_ instances for each image detected
``` js
var imgLoad = imagesLoaded('#container');
imgLoad.on( 'always', function() {
console.log( imgLoad.images.length + ' images loaded' );
// detect which image is broken
for ( var i = 0, len = imgLoad.images.length; i < len; i++ ) {
var image = imgLoad.images[i];
var result = image.isLoaded ? 'loaded' : 'broken';
console.log( 'image is ' + result + ' for ' + image.img.src );
}
});
```
## Webpack
Install imagesLoaded with npm.
``` bash
npm install imagesloaded
```
You can then `require('imagesloaded')`.
``` js
// main.js
var imagesLoaded = require('imagesloaded');
imagesLoaded( '#container', function() {
// images have loaded
});
```
Use `.makeJQueryPlugin` to make `.imagesLoaded()` jQuery plugin.
``` js
// main.js
var imagesLoaded = require('imagesloaded');
var $ = require('jquery');
// provide jQuery argument
imagesLoaded.makeJQueryPlugin( $ );
// now use .imagesLoaded() jQuery plugin
$('#container').imagesLoaded( function() {...});
```
Run webpack.
``` bash
webpack main.js bundle.js
```
## Browserify
imagesLoaded works with [Browserify](https://browserify.org/).
``` bash
npm install imagesloaded --save
```
``` js
var imagesLoaded = require('imagesloaded');
imagesLoaded( elem, function() {...} );
```
Use `.makeJQueryPlugin` to make to use `.imagesLoaded()` jQuery plugin.
``` js
var $ = require('jquery');
var imagesLoaded = require('imagesloaded');
// provide jQuery argument
imagesLoaded.makeJQueryPlugin( $ );
// now use .imagesLoaded() jQuery plugin
$('#container').imagesLoaded( function() {...});
```
## Browser support
+ Chrome 49+
+ Firefox 41+
+ Edge 14+
+ iOS Safari 8+
Use [imagesLoaded v4](https://github.com/desandro/imagesloaded/tree/v4.1.4) for Internet Explorer and other older browser support.
## Development
Development uses Node.js v16 with npm v8
``` bash
nvm use
```
## MIT License
imagesLoaded is released under the [MIT License](https://desandro.mit-license.org/). Have at it.
================================================
FILE: bower.json
================================================
{
"name": "imagesloaded",
"description": "JavaScript is all like _You images done yet or what?_",
"main": "imagesloaded.js",
"dependencies": {
"ev-emitter": "^2.1.2"
},
"devDependencies": {
},
"ignore": [
"**/.*",
"test",
"package.json",
"composer.json",
"node_modules",
"bower_components",
"tests",
"sandbox/",
"gulpfile.js",
"contributing.md"
],
"homepage": "https://imagesloaded.desandro.com",
"authors": [
"David DeSandro"
],
"moduleType": [
"amd",
"globals",
"node"
],
"keywords": [
"images"
],
"license": "MIT"
}
================================================
FILE: contributing.md
================================================
## Submitting issues
### Reduced test case required
All bug reports and problem issues require a [**reduced test case**](https://css-tricks.com/reduced-test-cases/).
+ A reduced test case clearly demonstrates the bug or issue.
+ It contains the bare minimum HTML, CSS, and JavaScript required to demonstrate the bug.
+ A link to your production site is **not** a reduced test case.
Create a test case by forking a [CodePen demos](https://codepen.io/collection/xKRgYx).
+ [progress with jQuery](https://codepen.io/desandro/pen/podVjYW)
+ [progress with vanilla JS](https://codepen.io/desandro/pen/XWzqXrP)
+ [`{ background: true }` with jQuery](https://codepen.io/desandro/pen/QWOrNNY)
+ [`{ background: true }` with vanilla JS](https://codepen.io/desandro/pen/oNodxYW)
+ [`{ background: '.selector' }` with jQuery](https://codepen.io/desandro/pen/YzELWdo)
+ [`{ background: '.selector' }` with vanilla JS](https://codepen.io/desandro/pen/KKyRMEv)
Providing a reduced test case is the best way to get your issue addressed. They help you point out the problem. They help me verify and debug the problem. They help others understand the problem. Without a reduced test case, your issue may be closed.
================================================
FILE: imagesloaded.js
================================================
/*!
* imagesLoaded v5.0.0
* JavaScript is all like "You images are done yet or what?"
* MIT License
*/
( function( window, factory ) {
// universal module definition
if ( typeof module == 'object' && module.exports ) {
// CommonJS
module.exports = factory( window, require('ev-emitter') );
} else {
// browser global
window.imagesLoaded = factory( window, window.EvEmitter );
}
} )( typeof window !== 'undefined' ? window : this,
function factory( window, EvEmitter ) {
let $ = window.jQuery;
let console = window.console;
// -------------------------- helpers -------------------------- //
// turn element or nodeList into an array
function makeArray( obj ) {
// use object if already an array
if ( Array.isArray( obj ) ) return obj;
let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
// convert nodeList to array
if ( isArrayLike ) return [ ...obj ];
// array of single index
return [ obj ];
}
// -------------------------- imagesLoaded -------------------------- //
/**
* @param {[Array, Element, NodeList, String]} elem
* @param {[Object, Function]} options - if function, use as callback
* @param {Function} onAlways - callback function
* @returns {ImagesLoaded}
*/
function ImagesLoaded( elem, options, onAlways ) {
// coerce ImagesLoaded() without new, to be new ImagesLoaded()
if ( !( this instanceof ImagesLoaded ) ) {
return new ImagesLoaded( elem, options, onAlways );
}
// use elem as selector string
let queryElem = elem;
if ( typeof elem == 'string' ) {
queryElem = document.querySelectorAll( elem );
}
// bail if bad element
if ( !queryElem ) {
console.error(`Bad element for imagesLoaded ${queryElem || elem}`);
return;
}
this.elements = makeArray( queryElem );
this.options = {};
// shift arguments if no options set
if ( typeof options == 'function' ) {
onAlways = options;
} else {
Object.assign( this.options, options );
}
if ( onAlways ) this.on( 'always', onAlways );
this.getImages();
// add jQuery Deferred object
if ( $ ) this.jqDeferred = new $.Deferred();
// HACK check async to allow time to bind listeners
setTimeout( this.check.bind( this ) );
}
ImagesLoaded.prototype = Object.create( EvEmitter.prototype );
ImagesLoaded.prototype.getImages = function() {
this.images = [];
// filter & find items if we have an item selector
this.elements.forEach( this.addElementImages, this );
};
const elementNodeTypes = [ 1, 9, 11 ];
/**
* @param {Node} elem
*/
ImagesLoaded.prototype.addElementImages = function( elem ) {
// filter siblings
if ( elem.nodeName === 'IMG' ) {
this.addImage( elem );
}
// get background image on element
if ( this.options.background === true ) {
this.addElementBackgroundImages( elem );
}
// find children
// no non-element nodes, #143
let { nodeType } = elem;
if ( !nodeType || !elementNodeTypes.includes( nodeType ) ) return;
let childImgs = elem.querySelectorAll('img');
// concat childElems to filterFound array
for ( let img of childImgs ) {
this.addImage( img );
}
// get child background images
if ( typeof this.options.background == 'string' ) {
let children = elem.querySelectorAll( this.options.background );
for ( let child of children ) {
this.addElementBackgroundImages( child );
}
}
};
const reURL = /url\((['"])?(.*?)\1\)/gi;
ImagesLoaded.prototype.addElementBackgroundImages = function( elem ) {
let style = getComputedStyle( elem );
// Firefox returns null if in a hidden iframe https://bugzil.la/548397
if ( !style ) return;
// get url inside url("...")
let matches = reURL.exec( style.backgroundImage );
while ( matches !== null ) {
let url = matches && matches[2];
if ( url ) {
this.addBackground( url, elem );
}
matches = reURL.exec( style.backgroundImage );
}
};
/**
* @param {Image} img
*/
ImagesLoaded.prototype.addImage = function( img ) {
let loadingImage = new LoadingImage( img );
this.images.push( loadingImage );
};
ImagesLoaded.prototype.addBackground = function( url, elem ) {
let background = new Background( url, elem );
this.images.push( background );
};
ImagesLoaded.prototype.check = function() {
this.progressedCount = 0;
this.hasAnyBroken = false;
// complete if no images
if ( !this.images.length ) {
this.complete();
return;
}
/* eslint-disable-next-line func-style */
let onProgress = ( image, elem, message ) => {
// HACK - Chrome triggers event before object properties have changed. #83
setTimeout( () => {
this.progress( image, elem, message );
} );
};
this.images.forEach( function( loadingImage ) {
loadingImage.once( 'progress', onProgress );
loadingImage.check();
} );
};
ImagesLoaded.prototype.progress = function( image, elem, message ) {
this.progressedCount++;
this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
// progress event
this.emitEvent( '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() {
let eventName = this.hasAnyBroken ? 'fail' : 'done';
this.isComplete = true;
this.emitEvent( eventName, [ this ] );
this.emitEvent( 'always', [ this ] );
if ( this.jqDeferred ) {
let jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';
this.jqDeferred[ jqMethod ]( this );
}
};
// -------------------------- -------------------------- //
function LoadingImage( img ) {
this.img = img;
}
LoadingImage.prototype = Object.create( EvEmitter.prototype );
LoadingImage.prototype.check = function() {
// If complete is true and browser supports natural sizes,
// try to check for image status manually.
let isComplete = this.getIsImageComplete();
if ( isComplete ) {
// report based on naturalWidth
this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
return;
}
// If none of the checks above matched, simulate loading on detached element.
this.proxyImage = new Image();
// add crossOrigin attribute. #204
if ( this.img.crossOrigin ) {
this.proxyImage.crossOrigin = this.img.crossOrigin;
}
this.proxyImage.addEventListener( 'load', this );
this.proxyImage.addEventListener( 'error', this );
// bind to image as well for Firefox. #191
this.img.addEventListener( 'load', this );
this.img.addEventListener( 'error', this );
this.proxyImage.src = this.img.currentSrc || this.img.src;
};
LoadingImage.prototype.getIsImageComplete = function() {
// check for non-zero, non-undefined naturalWidth
// fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671
return this.img.complete && this.img.naturalWidth;
};
LoadingImage.prototype.confirm = function( isLoaded, message ) {
this.isLoaded = isLoaded;
let { parentNode } = this.img;
// emit progress with parent <picture> or self <img>
let elem = parentNode.nodeName === 'PICTURE' ? parentNode : this.img;
this.emitEvent( 'progress', [ this, elem, message ] );
};
// ----- events ----- //
// trigger specified handler for event type
LoadingImage.prototype.handleEvent = function( event ) {
let method = 'on' + event.type;
if ( this[ method ] ) {
this[ method ]( event );
}
};
LoadingImage.prototype.onload = function() {
this.confirm( true, 'onload' );
this.unbindEvents();
};
LoadingImage.prototype.onerror = function() {
this.confirm( false, 'onerror' );
this.unbindEvents();
};
LoadingImage.prototype.unbindEvents = function() {
this.proxyImage.removeEventListener( 'load', this );
this.proxyImage.removeEventListener( 'error', this );
this.img.removeEventListener( 'load', this );
this.img.removeEventListener( 'error', this );
};
// -------------------------- Background -------------------------- //
function Background( url, element ) {
this.url = url;
this.element = element;
this.img = new Image();
}
// inherit LoadingImage prototype
Background.prototype = Object.create( LoadingImage.prototype );
Background.prototype.check = function() {
this.img.addEventListener( 'load', this );
this.img.addEventListener( 'error', this );
this.img.src = this.url;
// check if image is already complete
let isComplete = this.getIsImageComplete();
if ( isComplete ) {
this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
this.unbindEvents();
}
};
Background.prototype.unbindEvents = function() {
this.img.removeEventListener( 'load', this );
this.img.removeEventListener( 'error', this );
};
Background.prototype.confirm = function( isLoaded, message ) {
this.isLoaded = isLoaded;
this.emitEvent( 'progress', [ this, this.element, message ] );
};
// -------------------------- jQuery -------------------------- //
ImagesLoaded.makeJQueryPlugin = function( jQuery ) {
jQuery = jQuery || window.jQuery;
if ( !jQuery ) return;
// set local variable
$ = jQuery;
// $().imagesLoaded()
$.fn.imagesLoaded = function( options, onAlways ) {
let instance = new ImagesLoaded( this, options, onAlways );
return instance.jqDeferred.promise( $( this ) );
};
};
// try making plugin
ImagesLoaded.makeJQueryPlugin();
// -------------------------- -------------------------- //
return ImagesLoaded;
} );
================================================
FILE: imagesloaded.pkgd.js
================================================
/*!
* imagesLoaded PACKAGED v5.0.0
* JavaScript is all like "You images are done yet or what?"
* MIT License
*/
/**
* EvEmitter v2.1.1
* Lil' event emitter
* MIT License
*/
( function( global, factory ) {
// universal module definition
if ( typeof module == 'object' && module.exports ) {
// CommonJS - Browserify, Webpack
module.exports = factory();
} else {
// Browser globals
global.EvEmitter = factory();
}
}( typeof window != 'undefined' ? window : this, function() {
function EvEmitter() {}
let proto = EvEmitter.prototype;
proto.on = function( eventName, listener ) {
if ( !eventName || !listener ) return this;
// set events hash
let events = this._events = this._events || {};
// set listeners array
let listeners = events[ eventName ] = events[ eventName ] || [];
// only add once
if ( !listeners.includes( listener ) ) {
listeners.push( listener );
}
return this;
};
proto.once = function( eventName, listener ) {
if ( !eventName || !listener ) return this;
// add event
this.on( eventName, listener );
// set once flag
// set onceEvents hash
let onceEvents = this._onceEvents = this._onceEvents || {};
// set onceListeners object
let onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};
// set flag
onceListeners[ listener ] = true;
return this;
};
proto.off = function( eventName, listener ) {
let listeners = this._events && this._events[ eventName ];
if ( !listeners || !listeners.length ) return this;
let index = listeners.indexOf( listener );
if ( index != -1 ) {
listeners.splice( index, 1 );
}
return this;
};
proto.emitEvent = function( eventName, args ) {
let listeners = this._events && this._events[ eventName ];
if ( !listeners || !listeners.length ) return this;
// copy over to avoid interference if .off() in listener
listeners = listeners.slice( 0 );
args = args || [];
// once stuff
let onceListeners = this._onceEvents && this._onceEvents[ eventName ];
for ( let listener of listeners ) {
let isOnce = onceListeners && onceListeners[ listener ];
if ( isOnce ) {
// remove listener
// remove before trigger to prevent recursion
this.off( eventName, listener );
// unset once flag
delete onceListeners[ listener ];
}
// trigger listener
listener.apply( this, args );
}
return this;
};
proto.allOff = function() {
delete this._events;
delete this._onceEvents;
return this;
};
return EvEmitter;
} ) );
/*!
* imagesLoaded v5.0.0
* JavaScript is all like "You images are done yet or what?"
* MIT License
*/
( function( window, factory ) {
// universal module definition
if ( typeof module == 'object' && module.exports ) {
// CommonJS
module.exports = factory( window, require('ev-emitter') );
} else {
// browser global
window.imagesLoaded = factory( window, window.EvEmitter );
}
} )( typeof window !== 'undefined' ? window : this,
function factory( window, EvEmitter ) {
let $ = window.jQuery;
let console = window.console;
// -------------------------- helpers -------------------------- //
// turn element or nodeList into an array
function makeArray( obj ) {
// use object if already an array
if ( Array.isArray( obj ) ) return obj;
let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';
// convert nodeList to array
if ( isArrayLike ) return [ ...obj ];
// array of single index
return [ obj ];
}
// -------------------------- imagesLoaded -------------------------- //
/**
* @param {[Array, Element, NodeList, String]} elem
* @param {[Object, Function]} options - if function, use as callback
* @param {Function} onAlways - callback function
* @returns {ImagesLoaded}
*/
function ImagesLoaded( elem, options, onAlways ) {
// coerce ImagesLoaded() without new, to be new ImagesLoaded()
if ( !( this instanceof ImagesLoaded ) ) {
return new ImagesLoaded( elem, options, onAlways );
}
// use elem as selector string
let queryElem = elem;
if ( typeof elem == 'string' ) {
queryElem = document.querySelectorAll( elem );
}
// bail if bad element
if ( !queryElem ) {
console.error(`Bad element for imagesLoaded ${queryElem || elem}`);
return;
}
this.elements = makeArray( queryElem );
this.options = {};
// shift arguments if no options set
if ( typeof options == 'function' ) {
onAlways = options;
} else {
Object.assign( this.options, options );
}
if ( onAlways ) this.on( 'always', onAlways );
this.getImages();
// add jQuery Deferred object
if ( $ ) this.jqDeferred = new $.Deferred();
// HACK check async to allow time to bind listeners
setTimeout( this.check.bind( this ) );
}
ImagesLoaded.prototype = Object.create( EvEmitter.prototype );
ImagesLoaded.prototype.getImages = function() {
this.images = [];
// filter & find items if we have an item selector
this.elements.forEach( this.addElementImages, this );
};
const elementNodeTypes = [ 1, 9, 11 ];
/**
* @param {Node} elem
*/
ImagesLoaded.prototype.addElementImages = function( elem ) {
// filter siblings
if ( elem.nodeName === 'IMG' ) {
this.addImage( elem );
}
// get background image on element
if ( this.options.background === true ) {
this.addElementBackgroundImages( elem );
}
// find children
// no non-element nodes, #143
let { nodeType } = elem;
if ( !nodeType || !elementNodeTypes.includes( nodeType ) ) return;
let childImgs = elem.querySelectorAll('img');
// concat childElems to filterFound array
for ( let img of childImgs ) {
this.addImage( img );
}
// get child background images
if ( typeof this.options.background == 'string' ) {
let children = elem.querySelectorAll( this.options.background );
for ( let child of children ) {
this.addElementBackgroundImages( child );
}
}
};
const reURL = /url\((['"])?(.*?)\1\)/gi;
ImagesLoaded.prototype.addElementBackgroundImages = function( elem ) {
let style = getComputedStyle( elem );
// Firefox returns null if in a hidden iframe https://bugzil.la/548397
if ( !style ) return;
// get url inside url("...")
let matches = reURL.exec( style.backgroundImage );
while ( matches !== null ) {
let url = matches && matches[2];
if ( url ) {
this.addBackground( url, elem );
}
matches = reURL.exec( style.backgroundImage );
}
};
/**
* @param {Image} img
*/
ImagesLoaded.prototype.addImage = function( img ) {
let loadingImage = new LoadingImage( img );
this.images.push( loadingImage );
};
ImagesLoaded.prototype.addBackground = function( url, elem ) {
let background = new Background( url, elem );
this.images.push( background );
};
ImagesLoaded.prototype.check = function() {
this.progressedCount = 0;
this.hasAnyBroken = false;
// complete if no images
if ( !this.images.length ) {
this.complete();
return;
}
/* eslint-disable-next-line func-style */
let onProgress = ( image, elem, message ) => {
// HACK - Chrome triggers event before object properties have changed. #83
setTimeout( () => {
this.progress( image, elem, message );
} );
};
this.images.forEach( function( loadingImage ) {
loadingImage.once( 'progress', onProgress );
loadingImage.check();
} );
};
ImagesLoaded.prototype.progress = function( image, elem, message ) {
this.progressedCount++;
this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;
// progress event
this.emitEvent( '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() {
let eventName = this.hasAnyBroken ? 'fail' : 'done';
this.isComplete = true;
this.emitEvent( eventName, [ this ] );
this.emitEvent( 'always', [ this ] );
if ( this.jqDeferred ) {
let jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';
this.jqDeferred[ jqMethod ]( this );
}
};
// -------------------------- -------------------------- //
function LoadingImage( img ) {
this.img = img;
}
LoadingImage.prototype = Object.create( EvEmitter.prototype );
LoadingImage.prototype.check = function() {
// If complete is true and browser supports natural sizes,
// try to check for image status manually.
let isComplete = this.getIsImageComplete();
if ( isComplete ) {
// report based on naturalWidth
this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
return;
}
// If none of the checks above matched, simulate loading on detached element.
this.proxyImage = new Image();
// add crossOrigin attribute. #204
if ( this.img.crossOrigin ) {
this.proxyImage.crossOrigin = this.img.crossOrigin;
}
this.proxyImage.addEventListener( 'load', this );
this.proxyImage.addEventListener( 'error', this );
// bind to image as well for Firefox. #191
this.img.addEventListener( 'load', this );
this.img.addEventListener( 'error', this );
this.proxyImage.src = this.img.currentSrc || this.img.src;
};
LoadingImage.prototype.getIsImageComplete = function() {
// check for non-zero, non-undefined naturalWidth
// fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671
return this.img.complete && this.img.naturalWidth;
};
LoadingImage.prototype.confirm = function( isLoaded, message ) {
this.isLoaded = isLoaded;
let { parentNode } = this.img;
// emit progress with parent <picture> or self <img>
let elem = parentNode.nodeName === 'PICTURE' ? parentNode : this.img;
this.emitEvent( 'progress', [ this, elem, message ] );
};
// ----- events ----- //
// trigger specified handler for event type
LoadingImage.prototype.handleEvent = function( event ) {
let method = 'on' + event.type;
if ( this[ method ] ) {
this[ method ]( event );
}
};
LoadingImage.prototype.onload = function() {
this.confirm( true, 'onload' );
this.unbindEvents();
};
LoadingImage.prototype.onerror = function() {
this.confirm( false, 'onerror' );
this.unbindEvents();
};
LoadingImage.prototype.unbindEvents = function() {
this.proxyImage.removeEventListener( 'load', this );
this.proxyImage.removeEventListener( 'error', this );
this.img.removeEventListener( 'load', this );
this.img.removeEventListener( 'error', this );
};
// -------------------------- Background -------------------------- //
function Background( url, element ) {
this.url = url;
this.element = element;
this.img = new Image();
}
// inherit LoadingImage prototype
Background.prototype = Object.create( LoadingImage.prototype );
Background.prototype.check = function() {
this.img.addEventListener( 'load', this );
this.img.addEventListener( 'error', this );
this.img.src = this.url;
// check if image is already complete
let isComplete = this.getIsImageComplete();
if ( isComplete ) {
this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );
this.unbindEvents();
}
};
Background.prototype.unbindEvents = function() {
this.img.removeEventListener( 'load', this );
this.img.removeEventListener( 'error', this );
};
Background.prototype.confirm = function( isLoaded, message ) {
this.isLoaded = isLoaded;
this.emitEvent( 'progress', [ this, this.element, message ] );
};
// -------------------------- jQuery -------------------------- //
ImagesLoaded.makeJQueryPlugin = function( jQuery ) {
jQuery = jQuery || window.jQuery;
if ( !jQuery ) return;
// set local variable
$ = jQuery;
// $().imagesLoaded()
$.fn.imagesLoaded = function( options, onAlways ) {
let instance = new ImagesLoaded( this, options, onAlways );
return instance.jqDeferred.promise( $( this ) );
};
};
// try making plugin
ImagesLoaded.makeJQueryPlugin();
// -------------------------- -------------------------- //
return ImagesLoaded;
} );
================================================
FILE: package.json
================================================
{
"name": "imagesloaded",
"version": "5.0.0",
"description": "JavaScript is all like _You images done yet or what?_",
"main": "imagesloaded.js",
"files": [
"imagesloaded*.js"
],
"dependencies": {
"ev-emitter": "^2.1.2"
},
"devDependencies": {
"eslint": "^7.32.0",
"eslint-plugin-metafizzy": "^1.2.1",
"jquery": "^3.6.0",
"qunit": "^2.17.2",
"terser": "^5.10.0"
},
"scripts": {
"test": "npm run lint",
"lint": "npx eslint .",
"dist": "node tasks/dist.js",
"version": "node tasks/version.js && npm run dist && git add -A ."
},
"repository": {
"type": "git",
"url": "git://github.com/desandro/imagesloaded.git"
},
"keywords": [
"images",
"loaded",
"ui",
"dom",
"jquery-plugin"
],
"license": "MIT",
"bugs": {
"url": "https://github.com/desandro/imagesloaded/issues"
},
"homepage": "https://github.com/desandro/imagesloaded",
"directories": {
"test": "test"
},
"author": "David DeSandro"
}
================================================
FILE: sandbox/background/css/background.css
================================================
.box {
width: 300px;
height: 300px;
margin: 0 20px 20px 0;
border: 1px solid;
display: inline-block;
}
.orange-tree {
background: url('https://i.imgur.com/bwy74ok.jpg');
background-size: cover;
}
.thunder-cloud {
background: url('../../../test/img/thunder-cloud.jpg');
background-size: contain;
}
.multi1 {
background:
url("https://i.imgur.com/ZAVN3.png"),
url('https://i.imgur.com/6UdOxeB.png') bottom right,
url(https://i.imgur.com/LkmcILl.jpg);
background-size: cover;
}
.blue {
background: #09F;
}
================================================
FILE: sandbox/background/index.html
================================================
<!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="../../node_modules/ev-emitter/ev-emitter.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>
================================================
FILE: sandbox/picture.html
================================================
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>picture</title>
</head>
<body>
<picture>
<source srcset="https://picsum.photos/id/103/1200/900" media="(min-width: 1200px)">
<source srcset="https://picsum.photos/id/103/800/600" media="(min-width: 800px)">
<img src="https://picsum.photos/id/103/400/300">
</picture>
</body>
</html>
================================================
FILE: sandbox/progress/index.html
================================================
<!doctype html>
<html>
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width" />
<title>progress</title>
<style>
#image-container img {
max-height: 140px;
}
li {
height: 140px;
min-width: 100px;
display: block;
float: left;
list-style: none;
margin: 0 5px 5px 0;
background-color: black;
background-position: center center;
background-repeat: no-repeat;
}
li img,
#status {
-webkit-transition: opacity 0.4s;
-moz-transition: opacity 0.4s;
-ms-transition: opacity 0.4s;
transition: opacity 0.4s;
}
li.is-loading {
background-color: black;
background-image: url('https://desandro.github.io/imagesloaded/assets/loading.gif');
}
li.is-broken {
background-image: url('https://desandro.github.io/imagesloaded/assets/broken.png');
background-color: #be3730;
width: 120px;
}
li.is-loading img,
li.is-broken img {
opacity: 0;
}
.buttons { margin-bottom: 1.0em; }
button {
font-size: 18px;
padding: 0.4em 0.8em;
font-family: sans-serif;
}
#status {
opacity: 0;
position: fixed;
right: 20px;
top: 20px;
background: hsla( 0, 0%, 0%, 0.8);
padding: 20px;
border-radius: 10px;
z-index: 2; /* over other stuff */
}
</style>
</head>
<body>
<h1>progress</h1>
<div class="buttons">
<button id="add">Add images</button>
<button id="reset">Reset</button>
</div>
<div id="status">
<progress max="7" value="0"></progress>
</div>
<div id="image-container"></div>
<script src="../../node_modules/ev-emitter/ev-emitter.js"></script>
<script src="../../imagesloaded.js"></script>
<script src="progress.js"></script>
</body>
</html>
================================================
FILE: sandbox/progress/progress.js
================================================
let progressElem, statusElem,
supportsProgress,
loadedImageCount, imageCount;
let container = document.querySelector('#image-container');
statusElem = document.querySelector('#status');
progressElem = document.querySelector('progress');
supportsProgress = progressElem &&
// IE does not support progress
progressElem.toString().indexOf('Unknown') === -1;
document.querySelector('#add').onclick = function() {
// add new images
let fragment = getItemsFragment();
container.insertBefore( fragment, container.firstChild );
// use ImagesLoaded
let imgLoad = imagesLoaded( container );
imgLoad.on( 'progress', onProgress );
imgLoad.on( 'always', onAlways );
// reset progress counter
imageCount = imgLoad.images.length;
resetProgress();
updateProgress( 0 );
};
// reset container
document.querySelector('#reset').onclick = function() {
empty( container );
};
// ----- set text helper ----- //
let docElem = document.documentElement;
let textSetter = docElem.textContent !== undefined ? 'textContent' : 'innerText';
function setText( elem, value ) {
elem[ textSetter ] = value;
}
function empty( elem ) {
while ( elem.firstChild ) {
elem.removeChild( elem.firstChild );
}
}
// ----- ----- //
// return doc fragment with
function getItemsFragment() {
let fragment = document.createDocumentFragment();
for ( let i = 0; i < 7; i++ ) {
let item = getImageItem();
fragment.appendChild( item );
}
return fragment;
}
// return an <li> with a <img> in it
function getImageItem() {
let item = document.createElement('li');
item.className = 'is-loading';
let img = document.createElement('img');
let size = Math.random() * 3 + 1;
let width = Math.random() * 110 + 100;
width = Math.round( width * size );
let height = Math.round( 140 * size );
let rando = Math.ceil( Math.random() * 1000 );
// 10% chance of broken image src
// random parameter to prevent cached images
img.src = rando < 100 ? `//foo/broken-${rando}.jpg` :
// use picsum for great random images
`https://picsum.photos/${width}/${height}/?random`;
item.appendChild( img );
return item;
}
// ----- ----- //
function resetProgress() {
statusElem.style.opacity = 1;
loadedImageCount = 0;
if ( supportsProgress ) {
progressElem.setAttribute( 'max', imageCount );
}
}
function updateProgress( value ) {
if ( supportsProgress ) {
progressElem.setAttribute( 'value', value );
} else {
// if you don't support progress elem
setText( statusElem, value + ' / ' + imageCount );
}
}
// triggered after each item is loaded
function onProgress( imgLoad, image ) {
// change class if the image is loaded or broken
image.img.parentNode.className = image.isLoaded ? '' : 'is-broken';
// update progress element
loadedImageCount++;
updateProgress( loadedImageCount );
}
// hide status when done
function onAlways() {
statusElem.style.opacity = 0;
}
================================================
FILE: tasks/dist.js
================================================
const fs = require('fs');
const { execSync } = require('child_process');
const { minify } = require('terser');
const indexPath = 'imagesloaded.js';
const distPath = 'imagesloaded.pkgd.js';
const distMinPath = 'imagesloaded.pkgd.min.js';
let indexContent = fs.readFileSync( `./${indexPath}`, 'utf8' );
let paths = [
'node_modules/ev-emitter/ev-emitter.js',
'imagesloaded.js',
];
// concatenate files
execSync(`cat ${paths.join(' ')} > ${distPath}`);
// add banner
let banner = indexContent.split(' */')[0] + ' */\n\n';
banner = banner.replace( 'imagesLoaded', 'imagesLoaded PACKAGED' );
let distJsContent = fs.readFileSync( distPath, 'utf8' );
distJsContent = banner + distJsContent;
fs.writeFileSync( distPath, distJsContent );
// minify
( async function() {
let { code } = await minify( distJsContent, { mangle: true } );
fs.writeFileSync( distMinPath, code );
} )();
================================================
FILE: tasks/version.js
================================================
const fs = require('fs');
const version = require('../package.json').version;
const file = 'imagesloaded.js';
let src = fs.readFileSync( file, 'utf8' );
src = src.replace( /imagesLoaded v\d+\.\d+\.\d+/, `imagesLoaded v${version}` );
fs.writeFileSync( file, src, 'utf8' );
================================================
FILE: test/css/tests.css
================================================
body {
font-family: sans-serif;
}
img {
display: inline-block;
max-width: 240px;
}
#qunit {
max-width: 600px;
right: 0;
left: auto;
}
/* ---- backgrounds ---- */
.bg-box {
width: 240px;
height: 240px;
margin: 0 20px 20px 0;
border: 1px solid;
display: inline-block;
}
.bg-box.tulip {
background: url('https://i.imgur.com/9xYjgCk.jpg');
background-size: cover;
}
.bg-box.thunder-cloud {
background: url('../img/thunder-cloud.jpg');
background-size: contain;
}
.bg-box.multi {
background:
url("https://i.imgur.com/ZAVN3.png"),
url('https://i.imgur.com/6UdOxeB.png') bottom right,
url(https://picsum.photos/601/401/?random);
background-size: cover;
}
.bg-box.blue {
background: #09F;
}
.bg-box.gulls {
background-image: url('https://i.imgur.com/qKhkOKC.jpg');
background-size: cover;
}
================================================
FILE: test/index.html
================================================
<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>imagesLoaded tests</title>
<link rel="stylesheet" href="../node_modules/qunit/qunit/qunit.css" />
<link rel="stylesheet" href="css/tests.css" />
<script src="../node_modules/ev-emitter/ev-emitter.js"></script>
<script src="../node_modules/qunit/qunit/qunit.js"></script>
<script src="../node_modules/jquery/dist/jquery.js"></script>
<script src="../imagesloaded.js"></script>
<script src="unit/basics.js"></script>
<script src="unit/selector-string.js"></script>
<script src="unit/single-element.js"></script>
<script src="unit/local-files.js"></script>
<script src="unit/data-uri.js"></script>
<script src="unit/append.js"></script>
<script src="unit/no-images.js"></script>
<script src="unit/jquery-success.js"></script>
<script src="unit/jquery-fail.js"></script>
<script src="unit/non-element.js"></script>
<script src="unit/background.js"></script>
<script src="unit/picture.js"></script>
<script src="unit/srcset.js"></script>
</head>
<body>
<h1>imagesLoaded tests</h1>
<div id="qunit"></div>
<h2>Basics</h2>
<div id="basics">
<img src="https://i.imgur.com/xrQHn.jpg" />
<img src="https://i.imgur.com/b3fBJ.jpg" />
<img src="https://i.imgur.com/xmSh2.jpg" />
<img src="https://i.imgur.com/iIpJm.jpg" />
<img src="https://i.imgur.com/cvZZl10.gif" />
</div>
<img id="mario-with-shell" src="https://i.imgur.com/ZAVN3.png" >
<h2>Locals</h2>
<div id="locals">
<img src="img/blue-shell.jpg" />
<img src="img/bowser-jr.jpg" />
<!-- thunder cloud has bad permissions, should 403 -->
<img src="img/not-there.jpg" />
</div>
<h2>Data URI</h2>
<div id="data-uri">
<img src="data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAARgAA/+4ADkFkb2JlAGTAAAAAAf/bAIQABAMDAwMDBAMDBAYEAwQGBwUEBAUHCAYGBwYGCAoICQkJCQgKCgwMDAwMCgwMDQ0MDBERERERFBQUFBQUFBQUFAEEBQUIBwgPCgoPFA4ODhQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQUFBQU/8AAEQgAMAAwAwERAAIRAQMRAf/EAJMAAAEFAQEBAAAAAAAAAAAAAAYAAwQHCAUBAgEAAgIDAQEAAAAAAAAAAAAAAAUEBgECAwcIEAABAwMDAgQFAwUAAAAAAAACAQMEEQUGACESMQdBUSIyYUJiExRSIwihgiQVFhEAAQMCBQEFBgcAAAAAAAAAAQARAgMEITFBEgVRYYGRIgZxocHRchPw4TJCIxQH/9oADAMBAAIRAxEAPwDf2hCWhC42R5JBxuF+RJq7JcqMWIC/uOmngnkKfMXh/TSTmOZt+MoGrVP0x1kez4nTwCl21rOvPbHvPRRMHuFzutmcuF2NClPyn1ERSjYNiXEQD4DTx389RvTl/VvrKNxUzqGRA6B2AHgt72lGlVMI/tbxRJqyKCloQloQm31eRlxY4iT6CqtCaqIqVNkVURaJXWk9207W3Ng+T9qyGfFUtPutrbyFIuazTtWRyy+1FbuIKyw9v6QiO7tODVdhEuXmldfM/qbi+arXMql2A2hDmAHQM7D29+Kt9tc04w20Rh7+9FkKZIx1VFhf8bkv3I5biqqu6p5Kvw0u9N+sL3iav9eX8tJ22dPoOnsy7FwrW8bnzZS6/NHkZ4pEdt42yZIxQlaP3DXwXX1LQqmrTjMxMNwfbLMdh7VWJBiQ7p3Xdapt99mMy5JkOC1HZEnHXTVBEQBKkSqvRERN9CFSFx7q5PkqOz8TfZs2ON8lizJDIvyZLadHlFxeLYF1BOKlTdadNWy34emIg1XMjoNElr35EmgEORO4uaXWUNnya2QMpxZ50FemSWBhuxXBJFB9tKGDn219ftAtvStdJvUnEQHHXEqQJIpTaP6jI7SwGrk5KVZ3z1IieDkfgqDkOf8AcEsmQ7FGbs+LspRm7SowzJkh2u7iNGvFhpE9iqJGXVeOvPfQX+Yw4+Iu+Q89zIOIPhSfqdanXSOQxxU6+5oSBhROA9/5Isgd08vxltq5ZQ+zfccNUKZIYZFiUwz4ugjXocEfcQ8UKnRa7a9cuOHpyiftOJDQ6pPR5AmTTCvONJYmR2ZcVwXosgBdYeBeQG2aIQkKp1RUWqaqZDJ0qL7p5U9nz1w7cY887FtMSQLGR3JteKyVb9TkJrxQK0F4/HcE8V1ZONsAwrVMtB8Uru7v7flGaGZlqdt8AGnXUOMwQqTYogjTolUTy1Z4yEkid1DwPIrzLzLKbNdba7GsFo+wlruDraCxL/IqQ/jkgopIAJ+9Ui9dKcemlUjWlUkCPKGbwXWpCAhEjMu697gZHfYmW4pabRbnZVjuzjwXa4NAJsRRZ4kX5JKKqCE2pfaUVH1pvXprANaE4iIwLv4IpxgYSJzGSnwLQ7cbe4DLyNx3iJRbVEIadFoi+emkpiJXEll2O1uXu9u5cLt1fnXZVinS1ZsFwMuSwjfWoRHK7q0p1RkvkqgL6aKlc5Pj3BrQ7x8fmn1pd7/Kc1W9zukjtr3AvuMX0VjPSpsm5WqQ5sEyFMeJ4XGyXYlFSVtxE3Eh36ppnYV4VKMRqAyj3luTJwuxIvzV6bKG2+ipJFRJQXdBXqqeVNMwAEs2mKYKZc7MItPG3NbH2PI4jLnH6gL01+IrocrIAllgkk26XgSaYJuG2XueJxHnOPjxAdq+XJaaHKCBHPFSYeQt2JoYDj9Ejigipruop4rrBiDmsGBlih+DOkdzc8s2K2BFkPtTI1wukltOTcOFDeB43XFTZFLigNoq1Ii26Lpdf3EKdEjUhgmdpbyEnK1plWF4pm8BLZltoi3eEKqTYSm0MmyXqTZ7EBbdQVF1R4VJQLxLJ2Q6zdlX8asvxO5O3TtPLbulofLktiukhWpbH0syTRRcBPAXaEn6i0+teV24T8VFq24mEMOdve/F3f8Awf8AjljPJRClS5sQIqeFeYOGS0+kFXTGXLUgMCosbJl9tdu+/FoeWEuHpKc3QZUSdFKMXxQnHGyT+4E0R5aiRiidk6IsX/jVmOW3Jq5d15bdqsrBcksdrfV2Y/T5XZIIgttr8yNciX9Q6X3XK7g0PFSqVuILSmLYbiuE2/8A1eJ2iLaIKrycbitoCuElfU4XuMt+pqq6QTqSmXkXUoBl/9k=" />
<img src="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACsAAAAwCAMAAAC/knOqAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAMBQTFRFkF0QF27/Bgsp/fQF+fr6jqvpDEG2zp4CCx9Ys4IFo5JU8MqQXJH2Ulxj89QDC0bIsrKxIHn//fxztcv2iYqG5ebmCjCHzNjxAzTYRmih2drcCzijMof+OB8U/Pg59PHXE2D9xMK9eUMDAVf8kXNP/fvr2eP0p6WgOUtnAkX7Eljwa3WB5er2UXjVC0jZAh9/EFHa8PHyl5mZJVKt6NM34dzNz87NASGpsbzZDlDytq4tLWfs4bQFyLNp////+/v7DjziEwAAAEB0Uk5T////////////////////////////////////////////////////////////////////////////////////AMJ7sUQAAAPaSURBVHjadNWLdqo6EAZgQKGRA0YUYzRQY1ELqFykiojV93+rM0FQbLt/VlcvfpmVhGQq3V6TjgyjLOWyNIzR9sdn0stvE0MuQrmOZxmjf9pRybln+sJZspWZiSU7o7+twTmXtcU3BmhZ4f6/zLJk2ej+ttsyDIXVN4klsGzqmQP1ZXn9044TQbmcuS5Yx3Ic380cy2rj2qZJktzrui7MFqiDKlutcv1ip0mNseuGFbaedeVd235qGOMkAo4VJYB4AVcUbHG5erjxtN1ME8kwpgHybV0/63vbRF5QrUFk+7ADwpgGD82nva9+p4m+CQKYWFjwUH3YKYNkjPrnCr6/D4fz93f46WsKuIDqu8amPmGE5bnZr2u+fw2Hwwr3N4FYRZKsazshBLCggPv9S79K56saV+NRbU8McO6+ifSavL1dLtVQk2LYT7VtY/hcgnw8HgkGAL9Q2E78tDGJfWBV3CbiFwnqmzlsfmPXUDd2pTtUFAVVj6IIDtVNqmGtmW+aEYJQDZ9puM/gPTX7cNtBYeS7r+z+hVyfAp0+3gUsDsXKP5IXGLPne7uVUJf8TRFPEi1Ln1YVq/sbazzBbN8+v2LGjCguzNBtllVRwovoPtvnvcgYihlpLaueQeFRjY1f79vWhxfCGKpz54gVRYTZ7Nedn8JeiPNG7lhBGS2KIKdZ99edT6cKQjEiBGMf+UhhZRFQSnG02/60J9i0qmCMcsbimPGABkXIRYdQX+2EaaEcinOc57GWlWXpeR7cYqsUPWj0YksKN73QNEpLdZJer9d0rToeVC2LEG5+2rIqLjjXKKPJ6PrMxPJkK6DcsdSn3dIo5DnK8113de22tOHJWhyUDp88rBFFPEJxvruu0jYVOEE0tCyjsSMchQVBOZ3Px+MfeOehmHJLbs76LioKpuT5QND0hV4nnqZoGPrb3Z6iKNIUJc6Os5nA3ZfKTgCvGtq3Kuw2BIpMP5/O/8JGQEzC4N/BGuyuwAyZKYvtw/GOYc7A4RHf1ICNbUIi2blJqocJWt5Skm8OiyPo8aGufX/UQJvd9sSPZFUqKfGPcHRYPF0MBovT8VhXh3TT1cqgFM7kzESslEbqUezdyszJ4HvwKfhi8eCra0incwFm+1N9Hub9ztnffOqf+0/IY8BhpWbnTmfePjurs2iJZ922dXsPqQcMFouqWfbnLfst+ii05t7Stjd2lb0Y1Lt0hkA73y3bexNddzjs93S7yd5e9i4XaPFQ5tLqD5LohxfouG+S5G/u8T8+7l34Al25+7SHpVRlKS312fo4OA0Ws7Fe/1FaLg+V+l+AAQAurhhy+upm/wAAAABJRU5ErkJggg==" />
</div>
<h2>append</h2>
<div id="append"></div>
<h2>no images</h2>
<div id="no-images"></div>
<h2>jQuery success</h2>
<div id="jquery-success">
<img src="https://i.imgur.com/YbYCPFF.png" />
<img src="https://i.imgur.com/6UdOxeB.png" />
<img src="https://i.imgur.com/qd8G15D.png" />
</div>
<h2>jQuery fail</h2>
<div id="jquery-fail">
<img src="https://i.imgur.com/xmSh2.jpg" />
<img src="img/bowser-jr.jpg" />
<img src="https://i.imgur.com/ZAVN3.png">
<img src="img/not-there.jpg" />
<img src="foobar.jpg" />
</div>
<h2>background</h2>
<div id="background">
<div class="bg-box tulip"></div>
<div class="bg-box thunder-cloud"></div>
<div class="bg-box multi"></div>
<div class="bg-box blue"></div>
<div class="bg-box gulls">
<img src="https://picsum.photos/400/300/?random" />
<img src="https://picsum.photos/800/600/?random" />
</div>
</div>
<h2>picture</h2>
<div id="picture-list">
<picture>
<source srcset="https://picsum.photos/id/1036/1200/900" media="(min-width: 1200px)">
<source srcset="https://picsum.photos/id/1036/800/600" media="(min-width: 800px)">
<img src="https://picsum.photos/id/1036/400/300">
</picture>
<picture>
<source srcset="https://picsum.photos/id/103/1200/900" media="(min-width: 1200px)">
<source srcset="https://picsum.photos/id/103/800/600" media="(min-width: 800px)">
<img src="https://picsum.photos/id/103/400/300">
</picture>
<picture>
<source srcset="https://picsum.photos/id/1080/900/1200" media="(min-width: 1200px)">
<source srcset="https://picsum.photos/id/1080/600/800" media="(min-width: 800px)">
<img src="https://picsum.photos/id/1080/300/400">
</picture>
</div>
<h2>srcset</h2>
<div id="srcset">
<img
srcset="
https://picsum.photos/id/1074/1200/900 1200w,
https://picsum.photos/id/1074/800/600 800w,
https://picsum.photos/id/1074/400/300 400w
"
sizes="
(min-width: 1200px) 240px,
(min-width: 800px) 240px,
240px,
"
>
<img
srcset="
https://picsum.photos/id/159/900/1200 900w,
https://picsum.photos/id/159/600/800 600w,
https://picsum.photos/id/159/300/400 300w
"
sizes="
(min-width: 1200px) 240px,
(min-width: 800px) 240px,
240px,
"
>
<img
srcset="
https://picsum.photos/id/133/1200/900 1200w,
https://picsum.photos/id/133/800/600 800w,
https://picsum.photos/id/133/400/300 400w
"
sizes="
(min-width: 1200px) 240px,
(min-width: 800px) 240px,
240px,
"
>
</div>
</body>
</html>
================================================
FILE: test/unit/append.js
================================================
QUnit.test( 'append', function( assert ) {
let imgUrls = [
'https://i.imgur.com/bwy74ok.jpg',
'https://i.imgur.com/bAZWoqx.jpg',
'https://i.imgur.com/PgmEBSB.jpg',
'https://i.imgur.com/aboaFoB.jpg',
'https://i.imgur.com/LkmcILl.jpg',
'https://i.imgur.com/q9zO6tw.jpg',
];
// create images
let fragment = document.createDocumentFragment();
for ( let i = 0, len = imgUrls.length; i < len; i++ ) {
let img = document.createElement('img');
img.src = imgUrls[i];
fragment.appendChild( img );
}
let elem = document.querySelector('#append');
elem.appendChild( fragment );
let done = assert.async();
imagesLoaded( elem, { debug: false } ).on( 'always', function() {
assert.ok('appended images loaded');
done();
} );
} );
================================================
FILE: test/unit/background.js
================================================
QUnit.test( 'background', function( assert ) {
// from Modernizr
let supportsMultiBGs = ( function() {
let style = document.createElement('a').style;
style.cssText = 'background:url(https://),url(https://),red url(https://)';
return ( /(url\s*\(.*?){3}/ ).test( style.background );
} )();
let multiBGCount = supportsMultiBGs ? 3 : 0;
let done = assert.async( 14 + multiBGCount );
let imgLoad0 = imagesLoaded( '#background .tulip', { background: true }, function() {
assert.ok( true, 'callback triggered on .orange-tree' );
done();
} );
assert.equal( imgLoad0.images.length, 1, '1 image on .images' );
imgLoad0.on( 'progress', function( instance, image, element ) {
assert.ok( element.nodeName === 'DIV', 'progress; element is div' );
assert.ok( image.isLoaded, 'progress; image.isLoaded' );
done();
} );
let imgLoad1 = imagesLoaded( '#background .thunder-cloud', { background: true },
function() {
assert.ok( true, 'callback triggered on .thunder-cloud' );
done();
} );
assert.equal( imgLoad1.images.length, 1, '1 image on .images' );
// multiple backgrounds
let imgLoad2 = imagesLoaded( '#background .multi', { background: true }, function() {
assert.ok( true, 'callback triggered on .multi' );
done();
} );
assert.equal( imgLoad2.images.length, multiBGCount,
'correct multiple BG count on .images' );
// multiple elements
let imgLoad3 = imagesLoaded( '#background .bg-box', { background: true }, function() {
assert.ok( true, 'callback triggered on .bg-box' );
let count = 5 + multiBGCount;
assert.equal( imgLoad3.images.length, count, count + ' images on .bg-box' );
done();
} );
imgLoad3.on( 'progress', function( instance, image /* , element */) {
assert.ok( true, 'progress on .bg-box; ' + image.img.src );
assert.equal( image.isLoaded, true, 'image.isLoaded == true' );
done();
} );
// background and <img> children
let imgLoad4 = imagesLoaded( '#background .gulls', { background: true } );
assert.equal( imgLoad4.images.length, 3, '3 images: 1 background and 2 <img>' );
imgLoad4.on( 'progress', function( instance, image ) {
assert.equal( image.isLoaded, true, 'image is loaded' );
done();
} );
// child background selector
let imgLoad5 = imagesLoaded( '#background', { background: '.bg-box' }, function() {
let count = 5 + multiBGCount;
assert.equal( imgLoad5.images.length, count,
count + ' images on .bg-box, with {background: .bg-box}' );
done();
} );
} );
================================================
FILE: test/unit/basics.js
================================================
QUnit.test( 'basics', function( assert ) {
let elem = document.querySelector('#basics');
let images = elem.querySelectorAll('img');
let done = assert.async( 3 + images.length );
let imgLoader = new imagesLoaded( elem, function( obj ) {
assert.ok( true, 'callback function triggered' );
assert.equal( imgLoader, obj, 'callback argument and instance match' );
done();
} );
imgLoader.on( 'done', function() {
assert.ok( true, 'done event triggered' );
done();
} );
imgLoader.on( 'always', function() {
assert.ok( true, 'always event triggered' );
done();
} );
imgLoader.on( 'progress', function( loader, image ) {
assert.ok( image.isLoaded, 'image is loaded' );
done();
} );
} );
================================================
FILE: test/unit/data-uri.js
================================================
QUnit.test( 'data-uri', function( assert ) {
let done = assert.async();
imagesLoaded( '#data-uri', { debug: false } ).on( 'done', function( obj ) {
assert.ok( true, 'data-uri images loaded' );
assert.equal( obj.images.length, 2, 'instance has 2 images' );
done();
} );
} );
================================================
FILE: test/unit/jquery-fail.js
================================================
QUnit.test( 'jquery fail', function( assert ) {
let $ = window.jQuery;
let $images = $('#jquery-fail img');
let done = assert.async( 3 + $images.length );
$('#jquery-fail').imagesLoaded( function( instance ) {
assert.ok( true, 'callback triggered' );
assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' );
done();
} )
.fail( function( instance ) {
assert.ok( true, 'fail triggered' );
assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' );
done();
} )
.always( function( instance ) {
assert.ok( true, 'always triggered' );
assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' );
done();
} )
.progress( function( /* instance, image */) {
assert.ok( true, 'progress trigged' );
done();
} );
} );
================================================
FILE: test/unit/jquery-success.js
================================================
QUnit.test( 'jquery success', function( assert ) {
let $ = window.jQuery;
let done = assert.async( 6 );
$('#jquery-success').imagesLoaded( function( instance ) {
assert.ok( true, 'callback triggered' );
assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' );
done();
} )
.done( function( instance ) {
assert.ok( true, 'done triggered' );
assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' );
done();
} )
.always( function( instance ) {
assert.ok( true, 'always triggered' );
assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' );
done();
} )
.progress( function( instance, image ) {
assert.ok( image.isLoaded, 'progress trigged, image is loaded' );
done();
} );
} );
================================================
FILE: test/unit/local-files.js
================================================
QUnit.test( 'local files', function( assert ) {
let elem = document.querySelector('#locals');
let done = assert.async( 6 );
let imgLoader = new imagesLoaded( elem, function( obj ) {
assert.ok( true, 'callback function triggered' );
assert.equal( imgLoader, obj, 'callback argument and instance match' );
done();
} );
imgLoader.on( 'fail', function() {
assert.ok( true, 'fail event triggered' );
done();
} );
imgLoader.on( 'always', function() {
assert.ok( true, 'always event triggered' );
done();
} );
imgLoader.on( 'progress', function( loader, image ) {
assert.ok( true, 'image progressed' );
if ( image.img.src.indexOf('img/not-there.jpg') !== -1 ) {
assert.ok( !image.isLoaded, 'thunder cloud is not loaded' );
} else {
assert.ok( image.isLoaded, 'image is loaded' );
}
done();
} );
} );
================================================
FILE: test/unit/no-images.js
================================================
QUnit.test( 'no images', function( assert ) {
let elem = document.querySelector('#no-images');
let done = assert.async();
imagesLoaded( elem, function() {
assert.ok( true, 'triggered with no images' );
done();
} );
} );
================================================
FILE: test/unit/non-element.js
================================================
QUnit.test( 'dismiss non-element nodes', function( assert ) {
let $ = window.jQuery;
let done = assert.async( 2 );
$( '<img src="https://picsum.photos/401/301/?random" />' +
'<img src="https://picsum.photos/402/302/?random" /> ' )
.imagesLoaded( function() {
assert.ok( true, 'elements from jQuery string ok' );
done();
} );
// test fragment
let frag = document.createDocumentFragment();
let img = new Image();
img.src = 'https://picsum.photos/403/303/?random';
frag.appendChild( img );
let imgLoad = imagesLoaded( frag, function() {
assert.ok( true, 'document fragment ok' );
assert.equal( imgLoad.images.length, 1, '1 image found' );
done();
} );
} );
================================================
FILE: test/unit/picture.js
================================================
QUnit.test( 'picture', function( assert ) {
let done = assert.async( 4 );
let imgLoad0 = imagesLoaded( '#picture-list', function() {
assert.ok( true, 'callback triggered on #picture-list' );
done();
} );
assert.equal( imgLoad0.images.length, 3, '3 images on #picture-list' );
imgLoad0.on( 'progress', function( instance, image, element ) {
assert.ok( element.nodeName === 'PICTURE', 'progress; element is picture' );
assert.ok( image.isLoaded, 'progress; image.isLoaded' );
done();
} );
} );
================================================
FILE: test/unit/selector-string.js
================================================
QUnit.test( 'selector string', function( assert ) {
let images = document.querySelectorAll('#basics img');
let done = assert.async();
let imgLoad = imagesLoaded( '#basics', { debug: true } )
.on( 'done', function( obj ) {
assert.ok( true, 'selector string worked' );
assert.ok( obj.images, 'argument has images' );
assert.equal( obj.images.length, images.length, 'images.length matches' );
done();
} );
assert.ok( imgLoad.options.debug, 'debug option set' );
} );
================================================
FILE: test/unit/single-element.js
================================================
QUnit.test( 'single element', function( assert ) {
let elem = document.querySelector('#mario-with-shell');
let done = assert.async();
imagesLoaded( elem ).on( 'done', function( obj ) {
assert.ok( true, 'single element worked' );
assert.ok( obj.images, 'argument has images' );
assert.equal( obj.images.length, 1, 'images.length = 1' );
done();
} );
} );
================================================
FILE: test/unit/srcset.js
================================================
QUnit.test( 'srcset', function( assert ) {
let done = assert.async( 4 );
let imgLoad0 = imagesLoaded( '#srcset', function() {
assert.ok( true, 'callback triggered on #srcset' );
done();
} );
assert.equal( imgLoad0.images.length, 3, '3 images on #srcset' );
imgLoad0.on( 'progress', function( instance, image, element ) {
assert.ok( element.nodeName === 'IMG', 'progress; element is img' );
assert.ok( image.isLoaded, 'progress; image.isLoaded' );
done();
} );
} );
gitextract_8bkypk_n/
├── .eslintrc.js
├── .gitignore
├── .nvmrc
├── LICENSE.md
├── README.md
├── bower.json
├── contributing.md
├── imagesloaded.js
├── imagesloaded.pkgd.js
├── package.json
├── sandbox/
│ ├── background/
│ │ ├── css/
│ │ │ └── background.css
│ │ └── index.html
│ ├── picture.html
│ └── progress/
│ ├── index.html
│ └── progress.js
├── tasks/
│ ├── dist.js
│ └── version.js
└── test/
├── css/
│ └── tests.css
├── index.html
└── unit/
├── append.js
├── background.js
├── basics.js
├── data-uri.js
├── jquery-fail.js
├── jquery-success.js
├── local-files.js
├── no-images.js
├── non-element.js
├── picture.js
├── selector-string.js
├── single-element.js
└── srcset.js
SYMBOL INDEX (17 symbols across 3 files)
FILE: imagesloaded.js
function makeArray (line 26) | function makeArray( obj ) {
function ImagesLoaded (line 46) | function ImagesLoaded( elem, options, onAlways ) {
function LoadingImage (line 210) | function LoadingImage( img ) {
function Background (line 283) | function Background( url, element ) {
FILE: imagesloaded.pkgd.js
function EvEmitter (line 25) | function EvEmitter() {}
function makeArray (line 132) | function makeArray( obj ) {
function ImagesLoaded (line 152) | function ImagesLoaded( elem, options, onAlways ) {
function LoadingImage (line 316) | function LoadingImage( img ) {
function Background (line 389) | function Background( url, element ) {
FILE: sandbox/progress/progress.js
function setText (line 37) | function setText( elem, value ) {
function empty (line 41) | function empty( elem ) {
function getItemsFragment (line 50) | function getItemsFragment() {
function getImageItem (line 60) | function getImageItem() {
function resetProgress (line 80) | function resetProgress() {
function updateProgress (line 88) | function updateProgress( value ) {
function onProgress (line 98) | function onProgress( imgLoad, image ) {
function onAlways (line 107) | function onAlways() {
Condensed preview — 32 files, each showing path, character count, and a content snippet. Download the .json file or copy for the full structured content (66K chars).
[
{
"path": ".eslintrc.js",
"chars": 525,
"preview": "/* eslint-env node */\n\nmodule.exports = {\n plugins: [ 'metafizzy' ],\n extends: 'plugin:metafizzy/browser',\n env: {\n "
},
{
"path": ".gitignore",
"chars": 95,
"preview": "bower_components/\nnode_modules/\nbuild/index.html\nbuild/*.woff*\nbuild/imagesloaded*.js\n.netlify\n"
},
{
"path": ".nvmrc",
"chars": 2,
"preview": "16"
},
{
"path": "LICENSE.md",
"chars": 1168,
"preview": "Copyright (c) 2011-2022 [David DeSandro](https://desandro.com) and [contributors](https://github.com/desandro/imagesload"
},
{
"path": "README.md",
"chars": 7587,
"preview": "# imagesLoaded\n\n<p class=\"tagline\">JavaScript is all like \"You images done yet or what?\"</p>\n\n[imagesloaded.desandro.com"
},
{
"path": "bower.json",
"chars": 617,
"preview": "{\n \"name\": \"imagesloaded\",\n \"description\": \"JavaScript is all like _You images done yet or what?_\",\n \"main\": \"imagesl"
},
{
"path": "contributing.md",
"chars": 1204,
"preview": "## Submitting issues\n\n### Reduced test case required\n\nAll bug reports and problem issues require a [**reduced test case*"
},
{
"path": "imagesloaded.js",
"chars": 9537,
"preview": "/*!\n * imagesLoaded v5.0.0\n * JavaScript is all like \"You images are done yet or what?\"\n * MIT License\n */\n\n( function( "
},
{
"path": "imagesloaded.pkgd.js",
"chars": 12075,
"preview": "/*!\n * imagesLoaded PACKAGED v5.0.0\n * JavaScript is all like \"You images are done yet or what?\"\n * MIT License\n */\n\n/**"
},
{
"path": "package.json",
"chars": 1011,
"preview": "{\n \"name\": \"imagesloaded\",\n \"version\": \"5.0.0\",\n \"description\": \"JavaScript is all like _You images done yet or what?"
},
{
"path": "sandbox/background/css/background.css",
"chars": 541,
"preview": ".box {\n width: 300px;\n height: 300px;\n margin: 0 20px 20px 0;\n border: 1px solid;\n display: inline-block;\n}\n\n.orang"
},
{
"path": "sandbox/background/index.html",
"chars": 1339,
"preview": "<!doctype html>\n<html>\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width\" />\n\n <tit"
},
{
"path": "sandbox/picture.html",
"chars": 460,
"preview": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n <meta charset=\"utf-8\">\n <meta name=\"viewport\" content=\"width=device-width, in"
},
{
"path": "sandbox/progress/index.html",
"chars": 1762,
"preview": "<!doctype html>\n<html>\n<head>\n <meta charset=\"utf-8\" />\n <meta name=\"viewport\" content=\"width=device-width\" />\n\n <tit"
},
{
"path": "sandbox/progress/progress.js",
"chars": 2945,
"preview": "let progressElem, statusElem,\n supportsProgress,\n loadedImageCount, imageCount;\n\nlet container = document."
},
{
"path": "tasks/dist.js",
"chars": 883,
"preview": "const fs = require('fs');\nconst { execSync } = require('child_process');\nconst { minify } = require('terser');\n\nconst in"
},
{
"path": "tasks/version.js",
"chars": 274,
"preview": "const fs = require('fs');\nconst version = require('../package.json').version;\n\nconst file = 'imagesloaded.js';\n\nlet src "
},
{
"path": "test/css/tests.css",
"chars": 844,
"preview": "body {\n font-family: sans-serif;\n}\n\nimg {\n display: inline-block;\n max-width: 240px;\n}\n\n#qunit {\n max-width: 600px;\n"
},
{
"path": "test/index.html",
"chars": 8745,
"preview": "<!doctype html>\n<html>\n<head>\n <meta charset=\"utf-8\">\n\n <title>imagesLoaded tests</title>\n\n <link rel=\"stylesheet\" hr"
},
{
"path": "test/unit/append.js",
"chars": 783,
"preview": "QUnit.test( 'append', function( assert ) {\n let imgUrls = [\n 'https://i.imgur.com/bwy74ok.jpg',\n 'https://i.imgur"
},
{
"path": "test/unit/background.js",
"chars": 2563,
"preview": "QUnit.test( 'background', function( assert ) {\n // from Modernizr\n let supportsMultiBGs = ( function() {\n let style"
},
{
"path": "test/unit/basics.js",
"chars": 738,
"preview": "QUnit.test( 'basics', function( assert ) {\n let elem = document.querySelector('#basics');\n let images = elem.querySele"
},
{
"path": "test/unit/data-uri.js",
"chars": 292,
"preview": "QUnit.test( 'data-uri', function( assert ) {\n let done = assert.async();\n imagesLoaded( '#data-uri', { debug: false } "
},
{
"path": "test/unit/jquery-fail.js",
"chars": 883,
"preview": "QUnit.test( 'jquery fail', function( assert ) {\n let $ = window.jQuery;\n let $images = $('#jquery-fail img');\n let do"
},
{
"path": "test/unit/jquery-success.js",
"chars": 853,
"preview": "QUnit.test( 'jquery success', function( assert ) {\n let $ = window.jQuery;\n let done = assert.async( 6 );\n\n $('#jquer"
},
{
"path": "test/unit/local-files.js",
"chars": 876,
"preview": "QUnit.test( 'local files', function( assert ) {\n let elem = document.querySelector('#locals');\n let done = assert.asyn"
},
{
"path": "test/unit/no-images.js",
"chars": 237,
"preview": "QUnit.test( 'no images', function( assert ) {\n let elem = document.querySelector('#no-images');\n let done = assert.asy"
},
{
"path": "test/unit/non-element.js",
"chars": 711,
"preview": "QUnit.test( 'dismiss non-element nodes', function( assert ) {\n let $ = window.jQuery;\n let done = assert.async( 2 );\n\n"
},
{
"path": "test/unit/picture.js",
"chars": 528,
"preview": "QUnit.test( 'picture', function( assert ) {\n\n let done = assert.async( 4 );\n\n let imgLoad0 = imagesLoaded( '#picture-l"
},
{
"path": "test/unit/selector-string.js",
"chars": 504,
"preview": "QUnit.test( 'selector string', function( assert ) {\n let images = document.querySelectorAll('#basics img');\n let done "
},
{
"path": "test/unit/single-element.js",
"chars": 378,
"preview": "QUnit.test( 'single element', function( assert ) {\n let elem = document.querySelector('#mario-with-shell');\n let done "
},
{
"path": "test/unit/srcset.js",
"chars": 501,
"preview": "QUnit.test( 'srcset', function( assert ) {\n\n let done = assert.async( 4 );\n\n let imgLoad0 = imagesLoaded( '#srcset', f"
}
]
About this extraction
This page contains the full source code of the desandro/imagesloaded GitHub repository, extracted and formatted as plain text for AI agents and large language models (LLMs). The extraction includes 32 files (60.0 KB), approximately 18.5k tokens, and a symbol index with 17 extracted functions, classes, methods, constants, and types. Use this with OpenClaw, Claude, ChatGPT, Cursor, Windsurf, or any other AI tool that accepts text input. You can copy the full output to your clipboard or download it as a .txt file.
Extracted by GitExtract — free GitHub repo to text converter for AI. Built by Nikandr Surkov.