[
  {
    "path": ".eslintrc.js",
    "content": "/* eslint-env node */\n\nmodule.exports = {\n  plugins: [ 'metafizzy' ],\n  extends: 'plugin:metafizzy/browser',\n  env: {\n    browser: true,\n    commonjs: true,\n  },\n  parserOptions: {\n    ecmaVersion: 2018,\n  },\n  globals: {\n    imagesLoaded: 'readonly',\n    QUnit: 'readonly',\n  },\n  rules: {\n    eqeqeq: [ 'error', 'smart' ],\n    'id-length': [ 'error', {\n      min: 2,\n      max: 30,\n      exceptions: [ 'x', 'y', 'z', 'i', 'j', 'a', 'b', 't', '$' ],\n    } ],\n    'new-cap': 'off',\n  },\n  ignorePatterns: [ '*pkgd*.js' ],\n};\n"
  },
  {
    "path": ".gitignore",
    "content": "bower_components/\nnode_modules/\nbuild/index.html\nbuild/*.woff*\nbuild/imagesloaded*.js\n.netlify\n"
  },
  {
    "path": ".nvmrc",
    "content": "16"
  },
  {
    "path": "LICENSE.md",
    "content": "Copyright (c) 2011-2022 [David DeSandro](https://desandro.com) and [contributors](https://github.com/desandro/imagesloaded/graphs/contributors)\n\nPermission 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:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE 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.\n"
  },
  {
    "path": "README.md",
    "content": "# imagesLoaded\n\n<p class=\"tagline\">JavaScript is all like \"You images done yet or what?\"</p>\n\n[imagesloaded.desandro.com](https://imagesloaded.desandro.com)\n\nDetect when images have been loaded.\n\n## Install\n\n### Download\n\n+ [imagesloaded.pkgd.min.js](https://unpkg.com/imagesloaded@5/imagesloaded.pkgd.min.js) minified\n+ [imagesloaded.pkgd.js](https://unpkg.com/imagesloaded@5/imagesloaded.pkgd.js) un-minified\n\n### CDN\n\n``` html\n<script src=\"https://unpkg.com/imagesloaded@5/imagesloaded.pkgd.min.js\"></script>\n<!-- or -->\n<script src=\"https://unpkg.com/imagesloaded@5/imagesloaded.pkgd.js\"></script>\n```\n\n### Package managers\n\nInstall via npm: `npm install imagesloaded`\n\nInstall via Yarn: `yarn add imagesloaded`\n\n## jQuery\n\nYou can use imagesLoaded as a jQuery Plugin.\n\n``` js\n$('#container').imagesLoaded( function() {\n  // images have loaded\n});\n\n// options\n$('#container').imagesLoaded( {\n  // options...\n  },\n  function() {\n    // images have loaded\n  }\n);\n```\n\n`.imagesLoaded()` returns a [jQuery Deferred object](https://api.jquery.com/category/deferred-object/). This allows you to use `.always()`, `.done()`, `.fail()` and `.progress()`.\n\n``` js\n$('#container').imagesLoaded()\n  .always( function( instance ) {\n    console.log('all images loaded');\n  })\n  .done( function( instance ) {\n    console.log('all images successfully loaded');\n  })\n  .fail( function() {\n    console.log('all images loaded, at least one is broken');\n  })\n  .progress( function( instance, image ) {\n    var result = image.isLoaded ? 'loaded' : 'broken';\n    console.log( 'image is ' + result + ' for ' + image.img.src );\n  });\n```\n\n## Vanilla JavaScript\n\nYou can use imagesLoaded with vanilla JS.\n\n``` js\nimagesLoaded( elem, callback )\n// options\nimagesLoaded( elem, options, callback )\n// you can use `new` if you like\nnew imagesLoaded( elem, callback )\n```\n\n+ `elem` _Element, NodeList, Array, or Selector String_\n+ `options` _Object_\n+ `callback` _Function_ - function triggered after all images have been loaded\n\nUsing a callback function is the same as binding it to the `always` event (see below).\n\n``` js\n// element\nimagesLoaded( document.querySelector('#container'), function( instance ) {\n  console.log('all images are loaded');\n});\n// selector string\nimagesLoaded( '#container', function() {...});\n// multiple elements\nvar posts = document.querySelectorAll('.post');\nimagesLoaded( posts, function() {...});\n```\n\nBind events with vanilla JS with .on(), .off(), and .once() methods.\n\n``` js\nvar imgLoad = imagesLoaded( elem );\nfunction onAlways( instance ) {\n  console.log('all images are loaded');\n}\n// bind with .on()\nimgLoad.on( 'always', onAlways );\n// unbind with .off()\nimgLoad.off( 'always', onAlways );\n```\n\n## Background\n\nDetect when background images have loaded, in addition to `<img>`s.\n\nSet `{ background: true }` to detect when the element's background image has loaded.\n\n``` js\n// jQuery\n$('#container').imagesLoaded( { background: true }, function() {\n  console.log('#container background image loaded');\n});\n\n// vanilla JS\nimagesLoaded( '#container', { background: true }, function() {\n  console.log('#container background image loaded');\n});\n```\n\n[See jQuery demo](https://codepen.io/desandro/pen/pjVMPB) or [vanilla JS demo](https://codepen.io/desandro/pen/avKooW) on CodePen.\n\nSet to a selector string like `{ background: '.item' }` to detect when the background images of child elements have loaded.\n\n``` js\n// jQuery\n$('#container').imagesLoaded( { background: '.item' }, function() {\n  console.log('all .item background images loaded');\n});\n\n// vanilla JS\nimagesLoaded( '#container', { background: '.item' }, function() {\n  console.log('all .item background images loaded');\n});\n```\n\n[See jQuery demo](https://codepen.io/desandro/pen/avKoZL) or [vanilla JS demo](https://codepen.io/desandro/pen/vNrBGz) on CodePen.\n\n## Events\n\n### always\n\n``` js\n// jQuery\n$('#container').imagesLoaded().always( function( instance ) {\n  console.log('ALWAYS - all images have been loaded');\n});\n\n// vanilla JS\nimgLoad.on( 'always', function( instance ) {\n  console.log('ALWAYS - all images have been loaded');\n});\n```\n\nTriggered after all images have been either loaded or confirmed broken.\n\n+ `instance` _imagesLoaded_ - the imagesLoaded instance\n\n### done\n\n``` js\n// jQuery\n$('#container').imagesLoaded().done( function( instance ) {\n  console.log('DONE  - all images have been successfully loaded');\n});\n\n// vanilla JS\nimgLoad.on( 'done', function( instance ) {\n  console.log('DONE  - all images have been successfully loaded');\n});\n```\n\nTriggered after all images have successfully loaded without any broken images.\n\n### fail\n\n``` js\n$('#container').imagesLoaded().fail( function( instance ) {\n  console.log('FAIL - all images loaded, at least one is broken');\n});\n\n// vanilla JS\nimgLoad.on( 'fail', function( instance ) {\n  console.log('FAIL - all images loaded, at least one is broken');\n});\n```\n\nTriggered after all images have been loaded with at least one broken image.\n\n### progress\n\n``` js\nimgLoad.on( 'progress', function( instance, image ) {\n  var result = image.isLoaded ? 'loaded' : 'broken';\n  console.log( 'image is ' + result + ' for ' + image.img.src );\n});\n```\n\nTriggered after each image has been loaded.\n\n+ `instance` _imagesLoaded_ - the imagesLoaded instance\n+ `image` _LoadingImage_ - the LoadingImage instance of the loaded image\n\n<!-- sponsored -->\n\n## Properties\n\n### LoadingImage.img\n\n_Image_ - The `img` element\n\n### LoadingImage.isLoaded\n\n_Boolean_ - `true` when the image has successfully loaded\n\n### imagesLoaded.images\n\nArray of _LoadingImage_ instances for each image detected\n\n``` js\nvar imgLoad = imagesLoaded('#container');\nimgLoad.on( 'always', function() {\n  console.log( imgLoad.images.length + ' images loaded' );\n  // detect which image is broken\n  for ( var i = 0, len = imgLoad.images.length; i < len; i++ ) {\n    var image = imgLoad.images[i];\n    var result = image.isLoaded ? 'loaded' : 'broken';\n    console.log( 'image is ' + result + ' for ' + image.img.src );\n  }\n});\n```\n\n## Webpack\n\nInstall imagesLoaded with npm.\n\n``` bash\nnpm install imagesloaded\n```\n\nYou can then `require('imagesloaded')`.\n\n``` js\n// main.js\nvar imagesLoaded = require('imagesloaded');\n\nimagesLoaded( '#container', function() {\n  // images have loaded\n});\n```\n\nUse `.makeJQueryPlugin` to make `.imagesLoaded()` jQuery plugin.\n\n``` js\n// main.js\nvar imagesLoaded = require('imagesloaded');\nvar $ = require('jquery');\n\n// provide jQuery argument\nimagesLoaded.makeJQueryPlugin( $ );\n// now use .imagesLoaded() jQuery plugin\n$('#container').imagesLoaded( function() {...});\n```\n\nRun webpack.\n\n``` bash\nwebpack main.js bundle.js\n```\n\n## Browserify\n\nimagesLoaded works with [Browserify](https://browserify.org/).\n\n``` bash\nnpm install imagesloaded --save\n```\n\n``` js\nvar imagesLoaded = require('imagesloaded');\n\nimagesLoaded( elem, function() {...} );\n```\n\nUse `.makeJQueryPlugin` to make to use `.imagesLoaded()` jQuery plugin.\n\n``` js\nvar $ = require('jquery');\nvar imagesLoaded = require('imagesloaded');\n\n// provide jQuery argument\nimagesLoaded.makeJQueryPlugin( $ );\n// now use .imagesLoaded() jQuery plugin\n$('#container').imagesLoaded( function() {...});\n```\n\n\n## Browser support\n\n+ Chrome 49+\n+ Firefox 41+\n+ Edge 14+\n+ iOS Safari 8+\n\nUse [imagesLoaded v4](https://github.com/desandro/imagesloaded/tree/v4.1.4) for Internet Explorer and other older browser support.\n\n## Development\n\nDevelopment uses Node.js v16 with npm v8\n\n``` bash\nnvm use\n```\n\n## MIT License\n\nimagesLoaded is released under the [MIT License](https://desandro.mit-license.org/). Have at it.\n"
  },
  {
    "path": "bower.json",
    "content": "{\n  \"name\": \"imagesloaded\",\n  \"description\": \"JavaScript is all like _You images done yet or what?_\",\n  \"main\": \"imagesloaded.js\",\n  \"dependencies\": {\n    \"ev-emitter\": \"^2.1.2\"\n  },\n  \"devDependencies\": {\n  },\n  \"ignore\": [\n    \"**/.*\",\n    \"test\",\n    \"package.json\",\n    \"composer.json\",\n    \"node_modules\",\n    \"bower_components\",\n    \"tests\",\n    \"sandbox/\",\n    \"gulpfile.js\",\n    \"contributing.md\"\n  ],\n  \"homepage\": \"https://imagesloaded.desandro.com\",\n  \"authors\": [\n    \"David DeSandro\"\n  ],\n  \"moduleType\": [\n    \"amd\",\n    \"globals\",\n    \"node\"\n  ],\n  \"keywords\": [\n    \"images\"\n  ],\n  \"license\": \"MIT\"\n}\n"
  },
  {
    "path": "contributing.md",
    "content": "## Submitting issues\n\n### Reduced test case required\n\nAll bug reports and problem issues require a [**reduced test case**](https://css-tricks.com/reduced-test-cases/).\n\n+ A reduced test case clearly demonstrates the bug or issue.\n+ It contains the bare minimum HTML, CSS, and JavaScript required to demonstrate the bug.\n+ A link to your production site is **not** a reduced test case.\n\nCreate a test case by forking a [CodePen demos](https://codepen.io/collection/xKRgYx).\n\n+ [progress with jQuery](https://codepen.io/desandro/pen/podVjYW)\n+ [progress with vanilla JS](https://codepen.io/desandro/pen/XWzqXrP)\n+ [`{ background: true }` with jQuery](https://codepen.io/desandro/pen/QWOrNNY)\n+ [`{ background: true }` with vanilla JS](https://codepen.io/desandro/pen/oNodxYW)\n+ [`{ background: '.selector' }` with jQuery](https://codepen.io/desandro/pen/YzELWdo)\n+ [`{ background: '.selector' }` with vanilla JS](https://codepen.io/desandro/pen/KKyRMEv)\n\nProviding 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.\n"
  },
  {
    "path": "imagesloaded.js",
    "content": "/*!\n * imagesLoaded v5.0.0\n * JavaScript is all like \"You images are done yet or what?\"\n * MIT License\n */\n\n( function( window, factory ) {\n  // universal module definition\n  if ( typeof module == 'object' && module.exports ) {\n    // CommonJS\n    module.exports = factory( window, require('ev-emitter') );\n  } else {\n    // browser global\n    window.imagesLoaded = factory( window, window.EvEmitter );\n  }\n\n} )( typeof window !== 'undefined' ? window : this,\n    function factory( window, EvEmitter ) {\n\nlet $ = window.jQuery;\nlet console = window.console;\n\n// -------------------------- helpers -------------------------- //\n\n// turn element or nodeList into an array\nfunction makeArray( obj ) {\n  // use object if already an array\n  if ( Array.isArray( obj ) ) return obj;\n\n  let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';\n  // convert nodeList to array\n  if ( isArrayLike ) return [ ...obj ];\n\n  // array of single index\n  return [ obj ];\n}\n\n// -------------------------- imagesLoaded -------------------------- //\n\n/**\n * @param {[Array, Element, NodeList, String]} elem\n * @param {[Object, Function]} options - if function, use as callback\n * @param {Function} onAlways - callback function\n * @returns {ImagesLoaded}\n */\nfunction ImagesLoaded( elem, options, onAlways ) {\n  // coerce ImagesLoaded() without new, to be new ImagesLoaded()\n  if ( !( this instanceof ImagesLoaded ) ) {\n    return new ImagesLoaded( elem, options, onAlways );\n  }\n  // use elem as selector string\n  let queryElem = elem;\n  if ( typeof elem == 'string' ) {\n    queryElem = document.querySelectorAll( elem );\n  }\n  // bail if bad element\n  if ( !queryElem ) {\n    console.error(`Bad element for imagesLoaded ${queryElem || elem}`);\n    return;\n  }\n\n  this.elements = makeArray( queryElem );\n  this.options = {};\n  // shift arguments if no options set\n  if ( typeof options == 'function' ) {\n    onAlways = options;\n  } else {\n    Object.assign( this.options, options );\n  }\n\n  if ( onAlways ) this.on( 'always', onAlways );\n\n  this.getImages();\n  // add jQuery Deferred object\n  if ( $ ) this.jqDeferred = new $.Deferred();\n\n  // HACK check async to allow time to bind listeners\n  setTimeout( this.check.bind( this ) );\n}\n\nImagesLoaded.prototype = Object.create( EvEmitter.prototype );\n\nImagesLoaded.prototype.getImages = function() {\n  this.images = [];\n\n  // filter & find items if we have an item selector\n  this.elements.forEach( this.addElementImages, this );\n};\n\nconst elementNodeTypes = [ 1, 9, 11 ];\n\n/**\n * @param {Node} elem\n */\nImagesLoaded.prototype.addElementImages = function( elem ) {\n  // filter siblings\n  if ( elem.nodeName === 'IMG' ) {\n    this.addImage( elem );\n  }\n  // get background image on element\n  if ( this.options.background === true ) {\n    this.addElementBackgroundImages( elem );\n  }\n\n  // find children\n  // no non-element nodes, #143\n  let { nodeType } = elem;\n  if ( !nodeType || !elementNodeTypes.includes( nodeType ) ) return;\n\n  let childImgs = elem.querySelectorAll('img');\n  // concat childElems to filterFound array\n  for ( let img of childImgs ) {\n    this.addImage( img );\n  }\n\n  // get child background images\n  if ( typeof this.options.background == 'string' ) {\n    let children = elem.querySelectorAll( this.options.background );\n    for ( let child of children ) {\n      this.addElementBackgroundImages( child );\n    }\n  }\n};\n\nconst reURL = /url\\((['\"])?(.*?)\\1\\)/gi;\n\nImagesLoaded.prototype.addElementBackgroundImages = function( elem ) {\n  let style = getComputedStyle( elem );\n  // Firefox returns null if in a hidden iframe https://bugzil.la/548397\n  if ( !style ) return;\n\n  // get url inside url(\"...\")\n  let matches = reURL.exec( style.backgroundImage );\n  while ( matches !== null ) {\n    let url = matches && matches[2];\n    if ( url ) {\n      this.addBackground( url, elem );\n    }\n    matches = reURL.exec( style.backgroundImage );\n  }\n};\n\n/**\n * @param {Image} img\n */\nImagesLoaded.prototype.addImage = function( img ) {\n  let loadingImage = new LoadingImage( img );\n  this.images.push( loadingImage );\n};\n\nImagesLoaded.prototype.addBackground = function( url, elem ) {\n  let background = new Background( url, elem );\n  this.images.push( background );\n};\n\nImagesLoaded.prototype.check = function() {\n  this.progressedCount = 0;\n  this.hasAnyBroken = false;\n  // complete if no images\n  if ( !this.images.length ) {\n    this.complete();\n    return;\n  }\n\n  /* eslint-disable-next-line func-style */\n  let onProgress = ( image, elem, message ) => {\n    // HACK - Chrome triggers event before object properties have changed. #83\n    setTimeout( () => {\n      this.progress( image, elem, message );\n    } );\n  };\n\n  this.images.forEach( function( loadingImage ) {\n    loadingImage.once( 'progress', onProgress );\n    loadingImage.check();\n  } );\n};\n\nImagesLoaded.prototype.progress = function( image, elem, message ) {\n  this.progressedCount++;\n  this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;\n  // progress event\n  this.emitEvent( 'progress', [ this, image, elem ] );\n  if ( this.jqDeferred && this.jqDeferred.notify ) {\n    this.jqDeferred.notify( this, image );\n  }\n  // check if completed\n  if ( this.progressedCount === this.images.length ) {\n    this.complete();\n  }\n\n  if ( this.options.debug && console ) {\n    console.log( `progress: ${message}`, image, elem );\n  }\n};\n\nImagesLoaded.prototype.complete = function() {\n  let eventName = this.hasAnyBroken ? 'fail' : 'done';\n  this.isComplete = true;\n  this.emitEvent( eventName, [ this ] );\n  this.emitEvent( 'always', [ this ] );\n  if ( this.jqDeferred ) {\n    let jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';\n    this.jqDeferred[ jqMethod ]( this );\n  }\n};\n\n// --------------------------  -------------------------- //\n\nfunction LoadingImage( img ) {\n  this.img = img;\n}\n\nLoadingImage.prototype = Object.create( EvEmitter.prototype );\n\nLoadingImage.prototype.check = function() {\n  // If complete is true and browser supports natural sizes,\n  // try to check for image status manually.\n  let isComplete = this.getIsImageComplete();\n  if ( isComplete ) {\n    // report based on naturalWidth\n    this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );\n    return;\n  }\n\n  // If none of the checks above matched, simulate loading on detached element.\n  this.proxyImage = new Image();\n  // add crossOrigin attribute. #204\n  if ( this.img.crossOrigin ) {\n    this.proxyImage.crossOrigin = this.img.crossOrigin;\n  }\n  this.proxyImage.addEventListener( 'load', this );\n  this.proxyImage.addEventListener( 'error', this );\n  // bind to image as well for Firefox. #191\n  this.img.addEventListener( 'load', this );\n  this.img.addEventListener( 'error', this );\n  this.proxyImage.src = this.img.currentSrc || this.img.src;\n};\n\nLoadingImage.prototype.getIsImageComplete = function() {\n  // check for non-zero, non-undefined naturalWidth\n  // fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671\n  return this.img.complete && this.img.naturalWidth;\n};\n\nLoadingImage.prototype.confirm = function( isLoaded, message ) {\n  this.isLoaded = isLoaded;\n  let { parentNode } = this.img;\n  // emit progress with parent <picture> or self <img>\n  let elem = parentNode.nodeName === 'PICTURE' ? parentNode : this.img;\n  this.emitEvent( 'progress', [ this, elem, message ] );\n};\n\n// ----- events ----- //\n\n// trigger specified handler for event type\nLoadingImage.prototype.handleEvent = function( event ) {\n  let method = 'on' + event.type;\n  if ( this[ method ] ) {\n    this[ method ]( event );\n  }\n};\n\nLoadingImage.prototype.onload = function() {\n  this.confirm( true, 'onload' );\n  this.unbindEvents();\n};\n\nLoadingImage.prototype.onerror = function() {\n  this.confirm( false, 'onerror' );\n  this.unbindEvents();\n};\n\nLoadingImage.prototype.unbindEvents = function() {\n  this.proxyImage.removeEventListener( 'load', this );\n  this.proxyImage.removeEventListener( 'error', this );\n  this.img.removeEventListener( 'load', this );\n  this.img.removeEventListener( 'error', this );\n};\n\n// -------------------------- Background -------------------------- //\n\nfunction Background( url, element ) {\n  this.url = url;\n  this.element = element;\n  this.img = new Image();\n}\n\n// inherit LoadingImage prototype\nBackground.prototype = Object.create( LoadingImage.prototype );\n\nBackground.prototype.check = function() {\n  this.img.addEventListener( 'load', this );\n  this.img.addEventListener( 'error', this );\n  this.img.src = this.url;\n  // check if image is already complete\n  let isComplete = this.getIsImageComplete();\n  if ( isComplete ) {\n    this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );\n    this.unbindEvents();\n  }\n};\n\nBackground.prototype.unbindEvents = function() {\n  this.img.removeEventListener( 'load', this );\n  this.img.removeEventListener( 'error', this );\n};\n\nBackground.prototype.confirm = function( isLoaded, message ) {\n  this.isLoaded = isLoaded;\n  this.emitEvent( 'progress', [ this, this.element, message ] );\n};\n\n// -------------------------- jQuery -------------------------- //\n\nImagesLoaded.makeJQueryPlugin = function( jQuery ) {\n  jQuery = jQuery || window.jQuery;\n  if ( !jQuery ) return;\n\n  // set local variable\n  $ = jQuery;\n  // $().imagesLoaded()\n  $.fn.imagesLoaded = function( options, onAlways ) {\n    let instance = new ImagesLoaded( this, options, onAlways );\n    return instance.jqDeferred.promise( $( this ) );\n  };\n};\n// try making plugin\nImagesLoaded.makeJQueryPlugin();\n\n// --------------------------  -------------------------- //\n\nreturn ImagesLoaded;\n\n} );\n"
  },
  {
    "path": "imagesloaded.pkgd.js",
    "content": "/*!\n * imagesLoaded PACKAGED v5.0.0\n * JavaScript is all like \"You images are done yet or what?\"\n * MIT License\n */\n\n/**\n * EvEmitter v2.1.1\n * Lil' event emitter\n * MIT License\n */\n\n( function( global, factory ) {\n  // universal module definition\n  if ( typeof module == 'object' && module.exports ) {\n    // CommonJS - Browserify, Webpack\n    module.exports = factory();\n  } else {\n    // Browser globals\n    global.EvEmitter = factory();\n  }\n\n}( typeof window != 'undefined' ? window : this, function() {\n\nfunction EvEmitter() {}\n\nlet proto = EvEmitter.prototype;\n\nproto.on = function( eventName, listener ) {\n  if ( !eventName || !listener ) return this;\n\n  // set events hash\n  let events = this._events = this._events || {};\n  // set listeners array\n  let listeners = events[ eventName ] = events[ eventName ] || [];\n  // only add once\n  if ( !listeners.includes( listener ) ) {\n    listeners.push( listener );\n  }\n\n  return this;\n};\n\nproto.once = function( eventName, listener ) {\n  if ( !eventName || !listener ) return this;\n\n  // add event\n  this.on( eventName, listener );\n  // set once flag\n  // set onceEvents hash\n  let onceEvents = this._onceEvents = this._onceEvents || {};\n  // set onceListeners object\n  let onceListeners = onceEvents[ eventName ] = onceEvents[ eventName ] || {};\n  // set flag\n  onceListeners[ listener ] = true;\n\n  return this;\n};\n\nproto.off = function( eventName, listener ) {\n  let listeners = this._events && this._events[ eventName ];\n  if ( !listeners || !listeners.length ) return this;\n\n  let index = listeners.indexOf( listener );\n  if ( index != -1 ) {\n    listeners.splice( index, 1 );\n  }\n\n  return this;\n};\n\nproto.emitEvent = function( eventName, args ) {\n  let listeners = this._events && this._events[ eventName ];\n  if ( !listeners || !listeners.length ) return this;\n\n  // copy over to avoid interference if .off() in listener\n  listeners = listeners.slice( 0 );\n  args = args || [];\n  // once stuff\n  let onceListeners = this._onceEvents && this._onceEvents[ eventName ];\n\n  for ( let listener of listeners ) {\n    let isOnce = onceListeners && onceListeners[ listener ];\n    if ( isOnce ) {\n      // remove listener\n      // remove before trigger to prevent recursion\n      this.off( eventName, listener );\n      // unset once flag\n      delete onceListeners[ listener ];\n    }\n    // trigger listener\n    listener.apply( this, args );\n  }\n\n  return this;\n};\n\nproto.allOff = function() {\n  delete this._events;\n  delete this._onceEvents;\n  return this;\n};\n\nreturn EvEmitter;\n\n} ) );\n/*!\n * imagesLoaded v5.0.0\n * JavaScript is all like \"You images are done yet or what?\"\n * MIT License\n */\n\n( function( window, factory ) {\n  // universal module definition\n  if ( typeof module == 'object' && module.exports ) {\n    // CommonJS\n    module.exports = factory( window, require('ev-emitter') );\n  } else {\n    // browser global\n    window.imagesLoaded = factory( window, window.EvEmitter );\n  }\n\n} )( typeof window !== 'undefined' ? window : this,\n    function factory( window, EvEmitter ) {\n\nlet $ = window.jQuery;\nlet console = window.console;\n\n// -------------------------- helpers -------------------------- //\n\n// turn element or nodeList into an array\nfunction makeArray( obj ) {\n  // use object if already an array\n  if ( Array.isArray( obj ) ) return obj;\n\n  let isArrayLike = typeof obj == 'object' && typeof obj.length == 'number';\n  // convert nodeList to array\n  if ( isArrayLike ) return [ ...obj ];\n\n  // array of single index\n  return [ obj ];\n}\n\n// -------------------------- imagesLoaded -------------------------- //\n\n/**\n * @param {[Array, Element, NodeList, String]} elem\n * @param {[Object, Function]} options - if function, use as callback\n * @param {Function} onAlways - callback function\n * @returns {ImagesLoaded}\n */\nfunction ImagesLoaded( elem, options, onAlways ) {\n  // coerce ImagesLoaded() without new, to be new ImagesLoaded()\n  if ( !( this instanceof ImagesLoaded ) ) {\n    return new ImagesLoaded( elem, options, onAlways );\n  }\n  // use elem as selector string\n  let queryElem = elem;\n  if ( typeof elem == 'string' ) {\n    queryElem = document.querySelectorAll( elem );\n  }\n  // bail if bad element\n  if ( !queryElem ) {\n    console.error(`Bad element for imagesLoaded ${queryElem || elem}`);\n    return;\n  }\n\n  this.elements = makeArray( queryElem );\n  this.options = {};\n  // shift arguments if no options set\n  if ( typeof options == 'function' ) {\n    onAlways = options;\n  } else {\n    Object.assign( this.options, options );\n  }\n\n  if ( onAlways ) this.on( 'always', onAlways );\n\n  this.getImages();\n  // add jQuery Deferred object\n  if ( $ ) this.jqDeferred = new $.Deferred();\n\n  // HACK check async to allow time to bind listeners\n  setTimeout( this.check.bind( this ) );\n}\n\nImagesLoaded.prototype = Object.create( EvEmitter.prototype );\n\nImagesLoaded.prototype.getImages = function() {\n  this.images = [];\n\n  // filter & find items if we have an item selector\n  this.elements.forEach( this.addElementImages, this );\n};\n\nconst elementNodeTypes = [ 1, 9, 11 ];\n\n/**\n * @param {Node} elem\n */\nImagesLoaded.prototype.addElementImages = function( elem ) {\n  // filter siblings\n  if ( elem.nodeName === 'IMG' ) {\n    this.addImage( elem );\n  }\n  // get background image on element\n  if ( this.options.background === true ) {\n    this.addElementBackgroundImages( elem );\n  }\n\n  // find children\n  // no non-element nodes, #143\n  let { nodeType } = elem;\n  if ( !nodeType || !elementNodeTypes.includes( nodeType ) ) return;\n\n  let childImgs = elem.querySelectorAll('img');\n  // concat childElems to filterFound array\n  for ( let img of childImgs ) {\n    this.addImage( img );\n  }\n\n  // get child background images\n  if ( typeof this.options.background == 'string' ) {\n    let children = elem.querySelectorAll( this.options.background );\n    for ( let child of children ) {\n      this.addElementBackgroundImages( child );\n    }\n  }\n};\n\nconst reURL = /url\\((['\"])?(.*?)\\1\\)/gi;\n\nImagesLoaded.prototype.addElementBackgroundImages = function( elem ) {\n  let style = getComputedStyle( elem );\n  // Firefox returns null if in a hidden iframe https://bugzil.la/548397\n  if ( !style ) return;\n\n  // get url inside url(\"...\")\n  let matches = reURL.exec( style.backgroundImage );\n  while ( matches !== null ) {\n    let url = matches && matches[2];\n    if ( url ) {\n      this.addBackground( url, elem );\n    }\n    matches = reURL.exec( style.backgroundImage );\n  }\n};\n\n/**\n * @param {Image} img\n */\nImagesLoaded.prototype.addImage = function( img ) {\n  let loadingImage = new LoadingImage( img );\n  this.images.push( loadingImage );\n};\n\nImagesLoaded.prototype.addBackground = function( url, elem ) {\n  let background = new Background( url, elem );\n  this.images.push( background );\n};\n\nImagesLoaded.prototype.check = function() {\n  this.progressedCount = 0;\n  this.hasAnyBroken = false;\n  // complete if no images\n  if ( !this.images.length ) {\n    this.complete();\n    return;\n  }\n\n  /* eslint-disable-next-line func-style */\n  let onProgress = ( image, elem, message ) => {\n    // HACK - Chrome triggers event before object properties have changed. #83\n    setTimeout( () => {\n      this.progress( image, elem, message );\n    } );\n  };\n\n  this.images.forEach( function( loadingImage ) {\n    loadingImage.once( 'progress', onProgress );\n    loadingImage.check();\n  } );\n};\n\nImagesLoaded.prototype.progress = function( image, elem, message ) {\n  this.progressedCount++;\n  this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded;\n  // progress event\n  this.emitEvent( 'progress', [ this, image, elem ] );\n  if ( this.jqDeferred && this.jqDeferred.notify ) {\n    this.jqDeferred.notify( this, image );\n  }\n  // check if completed\n  if ( this.progressedCount === this.images.length ) {\n    this.complete();\n  }\n\n  if ( this.options.debug && console ) {\n    console.log( `progress: ${message}`, image, elem );\n  }\n};\n\nImagesLoaded.prototype.complete = function() {\n  let eventName = this.hasAnyBroken ? 'fail' : 'done';\n  this.isComplete = true;\n  this.emitEvent( eventName, [ this ] );\n  this.emitEvent( 'always', [ this ] );\n  if ( this.jqDeferred ) {\n    let jqMethod = this.hasAnyBroken ? 'reject' : 'resolve';\n    this.jqDeferred[ jqMethod ]( this );\n  }\n};\n\n// --------------------------  -------------------------- //\n\nfunction LoadingImage( img ) {\n  this.img = img;\n}\n\nLoadingImage.prototype = Object.create( EvEmitter.prototype );\n\nLoadingImage.prototype.check = function() {\n  // If complete is true and browser supports natural sizes,\n  // try to check for image status manually.\n  let isComplete = this.getIsImageComplete();\n  if ( isComplete ) {\n    // report based on naturalWidth\n    this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );\n    return;\n  }\n\n  // If none of the checks above matched, simulate loading on detached element.\n  this.proxyImage = new Image();\n  // add crossOrigin attribute. #204\n  if ( this.img.crossOrigin ) {\n    this.proxyImage.crossOrigin = this.img.crossOrigin;\n  }\n  this.proxyImage.addEventListener( 'load', this );\n  this.proxyImage.addEventListener( 'error', this );\n  // bind to image as well for Firefox. #191\n  this.img.addEventListener( 'load', this );\n  this.img.addEventListener( 'error', this );\n  this.proxyImage.src = this.img.currentSrc || this.img.src;\n};\n\nLoadingImage.prototype.getIsImageComplete = function() {\n  // check for non-zero, non-undefined naturalWidth\n  // fixes Safari+InfiniteScroll+Masonry bug infinite-scroll#671\n  return this.img.complete && this.img.naturalWidth;\n};\n\nLoadingImage.prototype.confirm = function( isLoaded, message ) {\n  this.isLoaded = isLoaded;\n  let { parentNode } = this.img;\n  // emit progress with parent <picture> or self <img>\n  let elem = parentNode.nodeName === 'PICTURE' ? parentNode : this.img;\n  this.emitEvent( 'progress', [ this, elem, message ] );\n};\n\n// ----- events ----- //\n\n// trigger specified handler for event type\nLoadingImage.prototype.handleEvent = function( event ) {\n  let method = 'on' + event.type;\n  if ( this[ method ] ) {\n    this[ method ]( event );\n  }\n};\n\nLoadingImage.prototype.onload = function() {\n  this.confirm( true, 'onload' );\n  this.unbindEvents();\n};\n\nLoadingImage.prototype.onerror = function() {\n  this.confirm( false, 'onerror' );\n  this.unbindEvents();\n};\n\nLoadingImage.prototype.unbindEvents = function() {\n  this.proxyImage.removeEventListener( 'load', this );\n  this.proxyImage.removeEventListener( 'error', this );\n  this.img.removeEventListener( 'load', this );\n  this.img.removeEventListener( 'error', this );\n};\n\n// -------------------------- Background -------------------------- //\n\nfunction Background( url, element ) {\n  this.url = url;\n  this.element = element;\n  this.img = new Image();\n}\n\n// inherit LoadingImage prototype\nBackground.prototype = Object.create( LoadingImage.prototype );\n\nBackground.prototype.check = function() {\n  this.img.addEventListener( 'load', this );\n  this.img.addEventListener( 'error', this );\n  this.img.src = this.url;\n  // check if image is already complete\n  let isComplete = this.getIsImageComplete();\n  if ( isComplete ) {\n    this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' );\n    this.unbindEvents();\n  }\n};\n\nBackground.prototype.unbindEvents = function() {\n  this.img.removeEventListener( 'load', this );\n  this.img.removeEventListener( 'error', this );\n};\n\nBackground.prototype.confirm = function( isLoaded, message ) {\n  this.isLoaded = isLoaded;\n  this.emitEvent( 'progress', [ this, this.element, message ] );\n};\n\n// -------------------------- jQuery -------------------------- //\n\nImagesLoaded.makeJQueryPlugin = function( jQuery ) {\n  jQuery = jQuery || window.jQuery;\n  if ( !jQuery ) return;\n\n  // set local variable\n  $ = jQuery;\n  // $().imagesLoaded()\n  $.fn.imagesLoaded = function( options, onAlways ) {\n    let instance = new ImagesLoaded( this, options, onAlways );\n    return instance.jqDeferred.promise( $( this ) );\n  };\n};\n// try making plugin\nImagesLoaded.makeJQueryPlugin();\n\n// --------------------------  -------------------------- //\n\nreturn ImagesLoaded;\n\n} );\n"
  },
  {
    "path": "package.json",
    "content": "{\n  \"name\": \"imagesloaded\",\n  \"version\": \"5.0.0\",\n  \"description\": \"JavaScript is all like _You images done yet or what?_\",\n  \"main\": \"imagesloaded.js\",\n  \"files\": [\n    \"imagesloaded*.js\"\n  ],\n  \"dependencies\": {\n    \"ev-emitter\": \"^2.1.2\"\n  },\n  \"devDependencies\": {\n    \"eslint\": \"^7.32.0\",\n    \"eslint-plugin-metafizzy\": \"^1.2.1\",\n    \"jquery\": \"^3.6.0\",\n    \"qunit\": \"^2.17.2\",\n    \"terser\": \"^5.10.0\"\n  },\n  \"scripts\": {\n    \"test\": \"npm run lint\",\n    \"lint\": \"npx eslint .\",\n    \"dist\": \"node tasks/dist.js\",\n    \"version\": \"node tasks/version.js && npm run dist && git add -A .\"\n  },\n  \"repository\": {\n    \"type\": \"git\",\n    \"url\": \"git://github.com/desandro/imagesloaded.git\"\n  },\n  \"keywords\": [\n    \"images\",\n    \"loaded\",\n    \"ui\",\n    \"dom\",\n    \"jquery-plugin\"\n  ],\n  \"license\": \"MIT\",\n  \"bugs\": {\n    \"url\": \"https://github.com/desandro/imagesloaded/issues\"\n  },\n  \"homepage\": \"https://github.com/desandro/imagesloaded\",\n  \"directories\": {\n    \"test\": \"test\"\n  },\n  \"author\": \"David DeSandro\"\n}\n"
  },
  {
    "path": "sandbox/background/css/background.css",
    "content": ".box {\n  width: 300px;\n  height: 300px;\n  margin: 0 20px 20px 0;\n  border: 1px solid;\n  display: inline-block;\n}\n\n.orange-tree {\n  background: url('https://i.imgur.com/bwy74ok.jpg');\n  background-size: cover;\n}\n\n.thunder-cloud {\n  background: url('../../../test/img/thunder-cloud.jpg');\n  background-size: contain;\n}\n\n.multi1 {\n  background:\n    url(\"https://i.imgur.com/ZAVN3.png\"),\n    url('https://i.imgur.com/6UdOxeB.png') bottom right,\n    url(https://i.imgur.com/LkmcILl.jpg);\n  background-size: cover;\n}\n\n.blue {\n  background: #09F;\n}"
  },
  {
    "path": "sandbox/background/index.html",
    "content": "<!doctype html>\n<html>\n<head>\n  <meta charset=\"utf-8\" />\n  <meta name=\"viewport\" content=\"width=device-width\" />\n\n  <title>background</title>\n\n  <!-- put in separate folder so JS path is different from CSS path -->\n  <link rel=\"stylesheet\" href=\"css/background.css\" >\n\n</head>\n<body>\n\n  <h1>background</h1>\n\n<div class=\"box orange-tree\"></div>\n\n<div class=\"box thunder-cloud\"></div>\n\n<div class=\"box multi1\"></div>\n\n<div class=\"box blue\"></div>\n\n<script src=\"../../node_modules/ev-emitter/ev-emitter.js\"></script>\n<script src=\"../../imagesloaded.js\"></script>\n<script>\n\nvar imgLoad0 = imagesLoaded( '.orange-tree', { background: true }, function() {\n  console.log('orange tree bg images loaded', imgLoad0.images.length );\n});\n\nvar imgLoad1 = imagesLoaded( '.thunder-cloud', { background: true }, function() {\n  console.log('thunder cloud bg images loaded', imgLoad1.images.length);\n});\n\nvar imgLoad2 = imagesLoaded( '.multi1', { background: true }, function() {\n  console.log('multi1 bg images loaded', imgLoad2.images.length);\n});\n\nvar imgLoad3 = imagesLoaded( '.box', { background: true }, function() {\n  console.log('.box bg images loaded', imgLoad3.images.length);\n});\nimgLoad3.on('progress', function( instance, image, element ) {\n  console.log( 'progress on .box', image.img.src, element.className );\n});\n\n</script>\n\n</body>\n</html>\n"
  },
  {
    "path": "sandbox/picture.html",
    "content": "<!DOCTYPE html>\n<html lang=\"en\">\n<head>\n  <meta charset=\"utf-8\">\n  <meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\n\n  <title>picture</title>\n\n</head>\n<body>\n\n    <picture>\n      <source srcset=\"https://picsum.photos/id/103/1200/900\" media=\"(min-width: 1200px)\">\n      <source srcset=\"https://picsum.photos/id/103/800/600\" media=\"(min-width: 800px)\">\n      <img src=\"https://picsum.photos/id/103/400/300\">\n    </picture>\n  \n</body>\n</html>\n"
  },
  {
    "path": "sandbox/progress/index.html",
    "content": "<!doctype html>\n<html>\n<head>\n  <meta charset=\"utf-8\" />\n  <meta name=\"viewport\" content=\"width=device-width\" />\n\n  <title>progress</title>\n\n  <style>\n  #image-container img {\n    max-height: 140px;\n  }\n\n  li {\n    height: 140px;\n    min-width: 100px;\n    display: block;\n    float: left;\n    list-style: none;\n    margin: 0 5px 5px 0;\n    background-color: black;\n    background-position: center center;\n    background-repeat: no-repeat;\n  }\n\n  li img,\n  #status {\n    -webkit-transition: opacity 0.4s;\n       -moz-transition: opacity 0.4s;\n        -ms-transition: opacity 0.4s;\n            transition: opacity 0.4s;\n  }\n\n  li.is-loading {\n    background-color: black;\n    background-image: url('https://desandro.github.io/imagesloaded/assets/loading.gif');\n  }\n\n  li.is-broken {\n    background-image: url('https://desandro.github.io/imagesloaded/assets/broken.png');\n    background-color: #be3730;\n    width: 120px;\n  }\n\n  li.is-loading img,\n  li.is-broken img {\n    opacity: 0;\n  }\n\n  .buttons { margin-bottom: 1.0em; }\n\n  button {\n    font-size: 18px;\n    padding: 0.4em 0.8em;\n    font-family: sans-serif;\n  }\n\n  #status {\n    opacity: 0;\n    position: fixed;\n    right: 20px;\n    top: 20px;\n    background: hsla( 0, 0%, 0%, 0.8);\n    padding: 20px;\n    border-radius: 10px;\n    z-index: 2; /* over other stuff */\n  }\n  </style>\n  \n</head>\n<body>\n\n  <h1>progress</h1>\n\n  <div class=\"buttons\">\n    <button id=\"add\">Add images</button>\n    <button id=\"reset\">Reset</button>\n  </div>\n  <div id=\"status\">\n    <progress max=\"7\" value=\"0\"></progress>\n  </div>\n  <div id=\"image-container\"></div>\n\n<script src=\"../../node_modules/ev-emitter/ev-emitter.js\"></script>\n<script src=\"../../imagesloaded.js\"></script>\n<script src=\"progress.js\"></script>\n\n</body>\n</html>\n"
  },
  {
    "path": "sandbox/progress/progress.js",
    "content": "let progressElem, statusElem,\n        supportsProgress,\n        loadedImageCount, imageCount;\n\nlet container = document.querySelector('#image-container');\nstatusElem = document.querySelector('#status');\nprogressElem = document.querySelector('progress');\n\nsupportsProgress = progressElem &&\n  // IE does not support progress\n  progressElem.toString().indexOf('Unknown') === -1;\n\ndocument.querySelector('#add').onclick = function() {\n  // add new images\n  let fragment = getItemsFragment();\n  container.insertBefore( fragment, container.firstChild );\n  // use ImagesLoaded\n  let imgLoad = imagesLoaded( container );\n  imgLoad.on( 'progress', onProgress );\n  imgLoad.on( 'always', onAlways );\n  // reset progress counter\n  imageCount = imgLoad.images.length;\n  resetProgress();\n  updateProgress( 0 );\n};\n\n// reset container\ndocument.querySelector('#reset').onclick = function() {\n  empty( container );\n};\n\n// ----- set text helper ----- //\n\nlet docElem = document.documentElement;\nlet textSetter = docElem.textContent !== undefined ? 'textContent' : 'innerText';\n\nfunction setText( elem, value ) {\n  elem[ textSetter ] = value;\n}\n\nfunction empty( elem ) {\n  while ( elem.firstChild ) {\n    elem.removeChild( elem.firstChild );\n  }\n}\n\n// -----  ----- //\n\n// return doc fragment with\nfunction getItemsFragment() {\n  let fragment = document.createDocumentFragment();\n  for ( let i = 0; i < 7; i++ ) {\n    let item = getImageItem();\n    fragment.appendChild( item );\n  }\n  return fragment;\n}\n\n// return an <li> with a <img> in it\nfunction getImageItem() {\n  let item = document.createElement('li');\n  item.className = 'is-loading';\n  let img = document.createElement('img');\n  let size = Math.random() * 3 + 1;\n  let width = Math.random() * 110 + 100;\n  width = Math.round( width * size );\n  let height = Math.round( 140 * size );\n  let rando = Math.ceil( Math.random() * 1000 );\n  // 10% chance of broken image src\n  // random parameter to prevent cached images\n  img.src = rando < 100 ? `//foo/broken-${rando}.jpg` :\n    // use picsum for great random images\n    `https://picsum.photos/${width}/${height}/?random`;\n  item.appendChild( img );\n  return item;\n}\n\n// -----  ----- //\n\nfunction resetProgress() {\n  statusElem.style.opacity = 1;\n  loadedImageCount = 0;\n  if ( supportsProgress ) {\n    progressElem.setAttribute( 'max', imageCount );\n  }\n}\n\nfunction updateProgress( value ) {\n  if ( supportsProgress ) {\n    progressElem.setAttribute( 'value', value );\n  } else {\n    // if you don't support progress elem\n    setText( statusElem, value + ' / ' + imageCount );\n  }\n}\n\n// triggered after each item is loaded\nfunction onProgress( imgLoad, image ) {\n  // change class if the image is loaded or broken\n  image.img.parentNode.className = image.isLoaded ? '' : 'is-broken';\n  // update progress element\n  loadedImageCount++;\n  updateProgress( loadedImageCount );\n}\n\n// hide status when done\nfunction onAlways() {\n  statusElem.style.opacity = 0;\n}\n"
  },
  {
    "path": "tasks/dist.js",
    "content": "const fs = require('fs');\nconst { execSync } = require('child_process');\nconst { minify } = require('terser');\n\nconst indexPath = 'imagesloaded.js';\nconst distPath = 'imagesloaded.pkgd.js';\nconst distMinPath = 'imagesloaded.pkgd.min.js';\n\nlet indexContent = fs.readFileSync( `./${indexPath}`, 'utf8' );\n\nlet paths = [\n  'node_modules/ev-emitter/ev-emitter.js',\n  'imagesloaded.js',\n];\n\n// concatenate files\nexecSync(`cat ${paths.join(' ')} > ${distPath}`);\n\n// add banner\nlet banner = indexContent.split(' */')[0] + ' */\\n\\n';\nbanner = banner.replace( 'imagesLoaded', 'imagesLoaded PACKAGED' );\nlet distJsContent = fs.readFileSync( distPath, 'utf8' );\ndistJsContent = banner + distJsContent;\nfs.writeFileSync( distPath, distJsContent );\n\n// minify\n( async function() {\n  let { code } = await minify( distJsContent, { mangle: true } );\n  fs.writeFileSync( distMinPath, code );\n} )();\n"
  },
  {
    "path": "tasks/version.js",
    "content": "const fs = require('fs');\nconst version = require('../package.json').version;\n\nconst file = 'imagesloaded.js';\n\nlet src = fs.readFileSync( file, 'utf8' );\nsrc = src.replace( /imagesLoaded v\\d+\\.\\d+\\.\\d+/, `imagesLoaded v${version}` );\nfs.writeFileSync( file, src, 'utf8' );\n"
  },
  {
    "path": "test/css/tests.css",
    "content": "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  right: 0;\n  left: auto;\n}\n\n/* ---- backgrounds ---- */\n\n.bg-box {\n  width: 240px;\n  height: 240px;\n  margin: 0 20px 20px 0;\n  border: 1px solid;\n  display: inline-block;\n}\n\n.bg-box.tulip {\n  background: url('https://i.imgur.com/9xYjgCk.jpg');\n  background-size: cover;\n}\n\n.bg-box.thunder-cloud {\n  background: url('../img/thunder-cloud.jpg');\n  background-size: contain;\n}\n\n.bg-box.multi {\n  background:\n    url(\"https://i.imgur.com/ZAVN3.png\"),\n    url('https://i.imgur.com/6UdOxeB.png') bottom right,\n    url(https://picsum.photos/601/401/?random);\n  background-size: cover;\n}\n\n.bg-box.blue {\n  background: #09F;\n}\n\n.bg-box.gulls {\n  background-image: url('https://i.imgur.com/qKhkOKC.jpg');\n  background-size: cover;\n}\n"
  },
  {
    "path": "test/index.html",
    "content": "<!doctype html>\n<html>\n<head>\n  <meta charset=\"utf-8\">\n\n  <title>imagesLoaded tests</title>\n\n  <link rel=\"stylesheet\" href=\"../node_modules/qunit/qunit/qunit.css\" />\n  <link rel=\"stylesheet\" href=\"css/tests.css\" />\n\n  <script src=\"../node_modules/ev-emitter/ev-emitter.js\"></script>\n  <script src=\"../node_modules/qunit/qunit/qunit.js\"></script>\n  <script src=\"../node_modules/jquery/dist/jquery.js\"></script>\n\n  <script src=\"../imagesloaded.js\"></script>\n\n  <script src=\"unit/basics.js\"></script>\n  <script src=\"unit/selector-string.js\"></script>\n  <script src=\"unit/single-element.js\"></script>\n  <script src=\"unit/local-files.js\"></script>\n  <script src=\"unit/data-uri.js\"></script>\n  <script src=\"unit/append.js\"></script>\n  <script src=\"unit/no-images.js\"></script>\n  <script src=\"unit/jquery-success.js\"></script>\n  <script src=\"unit/jquery-fail.js\"></script>\n  <script src=\"unit/non-element.js\"></script>\n  <script src=\"unit/background.js\"></script>\n  <script src=\"unit/picture.js\"></script>\n  <script src=\"unit/srcset.js\"></script>\n\n</head>\n<body>\n\n  <h1>imagesLoaded tests</h1>\n\n  <div id=\"qunit\"></div>\n\n  <h2>Basics</h2>\n\n  <div id=\"basics\">\n    <img src=\"https://i.imgur.com/xrQHn.jpg\" />\n    <img src=\"https://i.imgur.com/b3fBJ.jpg\" />\n    <img src=\"https://i.imgur.com/xmSh2.jpg\" />\n    <img src=\"https://i.imgur.com/iIpJm.jpg\" />\n    <img src=\"https://i.imgur.com/cvZZl10.gif\" />\n  </div>\n\n  <img id=\"mario-with-shell\" src=\"https://i.imgur.com/ZAVN3.png\" >\n\n  <h2>Locals</h2>\n\n  <div id=\"locals\">\n    <img src=\"img/blue-shell.jpg\" />\n    <img src=\"img/bowser-jr.jpg\" />\n    <!-- thunder cloud has bad permissions, should 403 -->\n    <img src=\"img/not-there.jpg\" />\n  </div>\n\n  <h2>Data URI</h2>\n\n  <div id=\"data-uri\">\n    <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=\" />\n    <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==\" />\n  </div>\n\n  <h2>append</h2>\n\n  <div id=\"append\"></div>\n\n  <h2>no images</h2>\n\n  <div id=\"no-images\"></div>\n\n  <h2>jQuery success</h2>\n\n  <div id=\"jquery-success\">\n    <img src=\"https://i.imgur.com/YbYCPFF.png\" />\n    <img src=\"https://i.imgur.com/6UdOxeB.png\" />\n    <img src=\"https://i.imgur.com/qd8G15D.png\" />\n  </div>\n\n  <h2>jQuery fail</h2>\n\n  <div id=\"jquery-fail\">\n    <img src=\"https://i.imgur.com/xmSh2.jpg\" />\n    <img src=\"img/bowser-jr.jpg\" />\n    <img src=\"https://i.imgur.com/ZAVN3.png\">\n    <img src=\"img/not-there.jpg\" />\n    <img src=\"foobar.jpg\" />\n  </div>\n\n  <h2>background</h2>\n\n  <div id=\"background\">\n    <div class=\"bg-box tulip\"></div>\n    <div class=\"bg-box thunder-cloud\"></div>\n    <div class=\"bg-box multi\"></div>\n    <div class=\"bg-box blue\"></div>\n    <div class=\"bg-box gulls\">\n      <img src=\"https://picsum.photos/400/300/?random\" />\n      <img src=\"https://picsum.photos/800/600/?random\" />\n    </div>\n  </div>\n\n  <h2>picture</h2>\n\n  <div id=\"picture-list\">\n    <picture>\n      <source srcset=\"https://picsum.photos/id/1036/1200/900\" media=\"(min-width: 1200px)\">\n      <source srcset=\"https://picsum.photos/id/1036/800/600\" media=\"(min-width: 800px)\">\n      <img src=\"https://picsum.photos/id/1036/400/300\">\n    </picture>\n    <picture>\n      <source srcset=\"https://picsum.photos/id/103/1200/900\" media=\"(min-width: 1200px)\">\n      <source srcset=\"https://picsum.photos/id/103/800/600\" media=\"(min-width: 800px)\">\n      <img src=\"https://picsum.photos/id/103/400/300\">\n    </picture>\n    <picture>\n      <source srcset=\"https://picsum.photos/id/1080/900/1200\" media=\"(min-width: 1200px)\">\n      <source srcset=\"https://picsum.photos/id/1080/600/800\" media=\"(min-width: 800px)\">\n      <img src=\"https://picsum.photos/id/1080/300/400\">\n    </picture>\n  </div>\n\n  <h2>srcset</h2>\n\n  <div id=\"srcset\">\n    <img\n      srcset=\"\n        https://picsum.photos/id/1074/1200/900 1200w,\n        https://picsum.photos/id/1074/800/600 800w,\n        https://picsum.photos/id/1074/400/300 400w\n      \"\n      sizes=\"\n        (min-width: 1200px) 240px,\n        (min-width: 800px) 240px,\n        240px,\n      \"\n    >\n    <img\n      srcset=\"\n        https://picsum.photos/id/159/900/1200 900w,\n        https://picsum.photos/id/159/600/800 600w,\n        https://picsum.photos/id/159/300/400 300w\n      \"\n      sizes=\"\n        (min-width: 1200px) 240px,\n        (min-width: 800px) 240px,\n        240px,\n      \"\n    >\n    <img\n      srcset=\"\n        https://picsum.photos/id/133/1200/900 1200w,\n        https://picsum.photos/id/133/800/600 800w,\n        https://picsum.photos/id/133/400/300 400w\n      \"\n      sizes=\"\n        (min-width: 1200px) 240px,\n        (min-width: 800px) 240px,\n        240px,\n      \"\n    >\n  </div>\n\n\n</body>\n</html>\n"
  },
  {
    "path": "test/unit/append.js",
    "content": "QUnit.test( 'append', function( assert ) {\n  let imgUrls = [\n    'https://i.imgur.com/bwy74ok.jpg',\n    'https://i.imgur.com/bAZWoqx.jpg',\n    'https://i.imgur.com/PgmEBSB.jpg',\n    'https://i.imgur.com/aboaFoB.jpg',\n    'https://i.imgur.com/LkmcILl.jpg',\n    'https://i.imgur.com/q9zO6tw.jpg',\n  ];\n\n  // create images\n  let fragment = document.createDocumentFragment();\n  for ( let i = 0, len = imgUrls.length; i < len; i++ ) {\n    let img = document.createElement('img');\n    img.src = imgUrls[i];\n    fragment.appendChild( img );\n  }\n\n  let elem = document.querySelector('#append');\n  elem.appendChild( fragment );\n  let done = assert.async();\n\n  imagesLoaded( elem, { debug: false } ).on( 'always', function() {\n    assert.ok('appended images loaded');\n    done();\n  } );\n\n} );\n"
  },
  {
    "path": "test/unit/background.js",
    "content": "QUnit.test( 'background', function( assert ) {\n  // from Modernizr\n  let supportsMultiBGs = ( function() {\n    let style = document.createElement('a').style;\n    style.cssText = 'background:url(https://),url(https://),red url(https://)';\n    return ( /(url\\s*\\(.*?){3}/ ).test( style.background );\n  } )();\n\n  let multiBGCount = supportsMultiBGs ? 3 : 0;\n  let done = assert.async( 14 + multiBGCount );\n\n  let imgLoad0 = imagesLoaded( '#background .tulip', { background: true }, function() {\n    assert.ok( true, 'callback triggered on .orange-tree' );\n    done();\n  } );\n  assert.equal( imgLoad0.images.length, 1, '1 image on .images' );\n\n  imgLoad0.on( 'progress', function( instance, image, element ) {\n    assert.ok( element.nodeName === 'DIV', 'progress; element is div' );\n    assert.ok( image.isLoaded, 'progress; image.isLoaded' );\n    done();\n  } );\n\n  let imgLoad1 = imagesLoaded( '#background .thunder-cloud', { background: true },\n      function() {\n      assert.ok( true, 'callback triggered on .thunder-cloud' );\n      done();\n    } );\n  assert.equal( imgLoad1.images.length, 1, '1 image on .images' );\n\n  // multiple backgrounds\n  let imgLoad2 = imagesLoaded( '#background .multi', { background: true }, function() {\n    assert.ok( true, 'callback triggered on .multi' );\n    done();\n  } );\n  assert.equal( imgLoad2.images.length, multiBGCount,\n      'correct multiple BG count on .images' );\n\n  // multiple elements\n  let imgLoad3 = imagesLoaded( '#background .bg-box', { background: true }, function() {\n    assert.ok( true, 'callback triggered on .bg-box' );\n    let count = 5 + multiBGCount;\n    assert.equal( imgLoad3.images.length, count, count + ' images on .bg-box' );\n    done();\n  } );\n\n  imgLoad3.on( 'progress', function( instance, image /* , element */) {\n    assert.ok( true, 'progress on .bg-box; ' + image.img.src );\n    assert.equal( image.isLoaded, true, 'image.isLoaded == true' );\n    done();\n  } );\n\n  // background and <img> children\n  let imgLoad4 = imagesLoaded( '#background .gulls', { background: true } );\n  assert.equal( imgLoad4.images.length, 3, '3 images: 1 background and 2 <img>' );\n\n  imgLoad4.on( 'progress', function( instance, image ) {\n    assert.equal( image.isLoaded, true, 'image is loaded' );\n    done();\n  } );\n\n  // child background selector\n  let imgLoad5 = imagesLoaded( '#background', { background: '.bg-box' }, function() {\n    let count = 5 + multiBGCount;\n    assert.equal( imgLoad5.images.length, count,\n        count + ' images on .bg-box, with {background: .bg-box}' );\n    done();\n  } );\n\n} );\n"
  },
  {
    "path": "test/unit/basics.js",
    "content": "QUnit.test( 'basics', function( assert ) {\n  let elem = document.querySelector('#basics');\n  let images = elem.querySelectorAll('img');\n  let done = assert.async( 3 + images.length );\n\n  let imgLoader = new imagesLoaded( elem, function( obj ) {\n    assert.ok( true, 'callback function triggered' );\n    assert.equal( imgLoader, obj, 'callback argument and instance match' );\n    done();\n  } );\n  imgLoader.on( 'done', function() {\n    assert.ok( true, 'done event triggered' );\n    done();\n  } );\n  imgLoader.on( 'always', function() {\n    assert.ok( true, 'always event triggered' );\n    done();\n  } );\n\n  imgLoader.on( 'progress', function( loader, image ) {\n    assert.ok( image.isLoaded, 'image is loaded' );\n    done();\n  } );\n\n} );\n"
  },
  {
    "path": "test/unit/data-uri.js",
    "content": "QUnit.test( 'data-uri', function( assert ) {\n  let done = assert.async();\n  imagesLoaded( '#data-uri', { debug: false } ).on( 'done', function( obj ) {\n    assert.ok( true, 'data-uri images loaded' );\n    assert.equal( obj.images.length, 2, 'instance has 2 images' );\n    done();\n  } );\n} );\n"
  },
  {
    "path": "test/unit/jquery-fail.js",
    "content": "QUnit.test( 'jquery fail', function( assert ) {\n  let $ = window.jQuery;\n  let $images = $('#jquery-fail img');\n  let done = assert.async( 3 + $images.length );\n\n  $('#jquery-fail').imagesLoaded( function( instance ) {\n      assert.ok( true, 'callback triggered' );\n      assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' );\n      done();\n    } )\n    .fail( function( instance ) {\n      assert.ok( true, 'fail triggered' );\n      assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' );\n      done();\n    } )\n    .always( function( instance ) {\n      assert.ok( true, 'always triggered' );\n      assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' );\n      done();\n    } )\n    .progress( function( /* instance, image */) {\n      assert.ok( true, 'progress trigged' );\n      done();\n    } );\n\n  } );\n"
  },
  {
    "path": "test/unit/jquery-success.js",
    "content": "QUnit.test( 'jquery success', function( assert ) {\n  let $ = window.jQuery;\n  let done = assert.async( 6 );\n\n  $('#jquery-success').imagesLoaded( function( instance ) {\n      assert.ok( true, 'callback triggered' );\n      assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' );\n      done();\n    } )\n    .done( function( instance ) {\n      assert.ok( true, 'done triggered' );\n      assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' );\n      done();\n    } )\n    .always( function( instance ) {\n      assert.ok( true, 'always triggered' );\n      assert.ok( instance instanceof imagesLoaded, 'instance instanceof imagesLoaded' );\n      done();\n    } )\n    .progress( function( instance, image ) {\n      assert.ok( image.isLoaded, 'progress trigged, image is loaded' );\n      done();\n    } );\n\n} );\n"
  },
  {
    "path": "test/unit/local-files.js",
    "content": "QUnit.test( 'local files', function( assert ) {\n  let elem = document.querySelector('#locals');\n  let done = assert.async( 6 );\n\n  let imgLoader = new imagesLoaded( elem, function( obj ) {\n    assert.ok( true, 'callback function triggered' );\n    assert.equal( imgLoader, obj, 'callback argument and instance match' );\n    done();\n  } );\n  imgLoader.on( 'fail', function() {\n    assert.ok( true, 'fail event triggered' );\n    done();\n  } );\n  imgLoader.on( 'always', function() {\n    assert.ok( true, 'always event triggered' );\n    done();\n  } );\n\n  imgLoader.on( 'progress', function( loader, image ) {\n    assert.ok( true, 'image progressed' );\n    if ( image.img.src.indexOf('img/not-there.jpg') !== -1 ) {\n      assert.ok( !image.isLoaded, 'thunder cloud is not loaded' );\n    } else {\n      assert.ok( image.isLoaded, 'image is loaded' );\n    }\n    done();\n  } );\n\n} );\n"
  },
  {
    "path": "test/unit/no-images.js",
    "content": "QUnit.test( 'no images', function( assert ) {\n  let elem = document.querySelector('#no-images');\n  let done = assert.async();\n  imagesLoaded( elem, function() {\n    assert.ok( true, 'triggered with no images' );\n    done();\n  } );\n\n} );\n"
  },
  {
    "path": "test/unit/non-element.js",
    "content": "QUnit.test( 'dismiss non-element nodes', function( assert ) {\n  let $ = window.jQuery;\n  let done = assert.async( 2 );\n\n  $( '<img src=\"https://picsum.photos/401/301/?random\" />' +\n  '<img src=\"https://picsum.photos/402/302/?random\" /> ' )\n    .imagesLoaded( function() {\n      assert.ok( true, 'elements from jQuery string ok' );\n      done();\n    } );\n\n  // test fragment\n  let frag = document.createDocumentFragment();\n  let img = new Image();\n  img.src = 'https://picsum.photos/403/303/?random';\n  frag.appendChild( img );\n  let imgLoad = imagesLoaded( frag, function() {\n    assert.ok( true, 'document fragment ok' );\n    assert.equal( imgLoad.images.length, 1, '1 image found' );\n    done();\n  } );\n\n} );\n"
  },
  {
    "path": "test/unit/picture.js",
    "content": "QUnit.test( 'picture', function( assert ) {\n\n  let done = assert.async( 4 );\n\n  let imgLoad0 = imagesLoaded( '#picture-list', function() {\n    assert.ok( true, 'callback triggered on #picture-list' );\n    done();\n  } );\n  assert.equal( imgLoad0.images.length, 3, '3 images on #picture-list' );\n\n  imgLoad0.on( 'progress', function( instance, image, element ) {\n    assert.ok( element.nodeName === 'PICTURE', 'progress; element is picture' );\n    assert.ok( image.isLoaded, 'progress; image.isLoaded' );\n    done();\n  } );\n\n} );\n"
  },
  {
    "path": "test/unit/selector-string.js",
    "content": "QUnit.test( 'selector string', function( assert ) {\n  let images = document.querySelectorAll('#basics img');\n  let done = assert.async();\n  let imgLoad = imagesLoaded( '#basics', { debug: true } )\n    .on( 'done', function( obj ) {\n      assert.ok( true, 'selector string worked' );\n      assert.ok( obj.images, 'argument has images' );\n      assert.equal( obj.images.length, images.length, 'images.length matches' );\n      done();\n    } );\n  assert.ok( imgLoad.options.debug, 'debug option set' );\n} );\n"
  },
  {
    "path": "test/unit/single-element.js",
    "content": "QUnit.test( 'single element', function( assert ) {\n  let elem = document.querySelector('#mario-with-shell');\n  let done = assert.async();\n  imagesLoaded( elem ).on( 'done', function( obj ) {\n    assert.ok( true, 'single element worked' );\n    assert.ok( obj.images, 'argument has images' );\n    assert.equal( obj.images.length, 1, 'images.length = 1' );\n    done();\n  } );\n} );\n"
  },
  {
    "path": "test/unit/srcset.js",
    "content": "QUnit.test( 'srcset', function( assert ) {\n\n  let done = assert.async( 4 );\n\n  let imgLoad0 = imagesLoaded( '#srcset', function() {\n    assert.ok( true, 'callback triggered on #srcset' );\n    done();\n  } );\n  assert.equal( imgLoad0.images.length, 3, '3 images on #srcset' );\n\n  imgLoad0.on( 'progress', function( instance, image, element ) {\n    assert.ok( element.nodeName === 'IMG', 'progress; element is img' );\n    assert.ok( image.isLoaded, 'progress; image.isLoaded' );\n    done();\n  } );\n\n} );\n"
  }
]