vendor: 4,355 bytes, lines 1-179
1/*! 2 * imagesLoaded v4.1.3 3 * JavaScript is all like "You images are done yet or what?" 4 * MIT License 5 */ 6 7( function( window, factory ) { 'use strict'; 8 // universal module definition 9 10 /*global define: false, module: false, require: false */ 11 12 if ( typeof define == 'function' && define.amd ) { 13 // AMD 14 define( [ 15 'ev-emitter/ev-emitter' 16 ], function( EvEmitter ) { 17 return factory( window, EvEmitter ); 18 }); 19 } else if ( typeof module == 'object' && module.exports ) { 20 // CommonJS 21 module.exports = factory( 22 window, 23 require('ev-emitter') 24 ); 25 } else { 26 // browser global 27 window.imagesLoaded = factory( 28 window, 29 window.EvEmitter 30 ); 31 } 32 33})( typeof window !== 'undefined' ? window : this, 34 35// -------------------------- factory -------------------------- // 36 37function factory( window, EvEmitter ) { 38 39'use strict'; 40 41var $ = window.jQuery; 42var console = window.console; 43 44// -------------------------- helpers -------------------------- // 45 46// extend objects 47function extend( a, b ) { 48 for ( var prop in b ) { 49 a[ prop ] = b[ prop ]; 50 } 51 return a; 52} 53 54// turn element or nodeList into an array 55function makeArray( obj ) { 56 var ary = []; 57 if ( Array.isArray( obj ) ) { 58 // use object if already an array 59 ary = obj; 60 } else if ( typeof obj.length == 'number' ) { 61 // convert nodeList to array 62 for ( var i=0; i < obj.length; i++ ) { 63 ary.push( obj[i] ); 64 } 65 } else { 66 // array of single index 67 ary.push( obj ); 68 } 69 return ary; 70} 71 72// -------------------------- imagesLoaded -------------------------- // 73 74/** 75 * @param {Array, Element, NodeList, String} elem 76 * @param {Object or Function} options - if function, use as callback 77 * @param {Function} onAlways - callback function 78 */ 79function ImagesLoaded( elem, options, onAlways ) { 80 // coerce ImagesLoaded() without new, to be new ImagesLoaded() 81 if ( !( this instanceof ImagesLoaded ) ) { 82 return new ImagesLoaded( elem, options, onAlways ); 83 } 84 // use elem as selector string 85 if ( typeof elem == 'string' ) { 86 elem = document.querySelectorAll( elem ); 87 } 88 89 this.elements = makeArray( elem ); 90 this.options = extend( {}, this.options ); 91 92 if ( typeof options == 'function' ) { 93 onAlways = options; 94 } else { 95 extend( this.options, options ); 96 } 97 98 if ( onAlways ) { 99 this.on( 'always', onAlways ); 100 } 101 102 this.getImages(); 103 104 if ( $ ) { 105 // add jQuery Deferred object 106 this.jqDeferred = new $.Deferred(); 107 } 108 109 // HACK check async to allow time to bind listeners 110 setTimeout( function() { 111 this.check(); 112 }.bind( this )); 113} 114 115ImagesLoaded.prototype = Object.create( EvEmitter.prototype ); 116 117ImagesLoaded.prototype.options = {}; 118 119ImagesLoaded.prototype.getImages = function() { 120 this.images = []; 121 122 // filter & find items if we have an item selector 123 this.elements.forEach( this.addElementImages, this ); 124}; 125 126/** 127 * @param {Node} element 128 */ 129ImagesLoaded.prototype.addElementImages = function( elem ) { 130 // filter siblings 131 if ( elem.nodeName == 'IMG' ) { 132 this.addImage( elem ); 133 } 134 // get background image on element 135 if ( this.options.background === true ) { 136 this.addElementBackgroundImages( elem ); 137 } 138 139 // find children 140 // no non-element nodes, #143 141 var nodeType = elem.nodeType; 142 if ( !nodeType || !elementNodeTypes[ nodeType ] ) { 143 return; 144 } 145 var childImgs = elem.querySelectorAll('img'); 146 // concat childElems to filterFound array 147 for ( var i=0; i < childImgs.length; i++ ) { 148 var img = childImgs[i]; 149 this.addImage( img ); 150 } 151 152 // get child background images 153 if ( typeof this.options.background == 'string' ) { 154 var children = elem.querySelectorAll( this.options.background ); 155 for ( i=0; i < children.length; i++ ) { 156 var child = children[i]; 157 this.addElementBackgroundImages( child ); 158 } 159 } 160}; 161 162var elementNodeTypes = { 163 1: true, 164 9: true, 165 11: true 166}; 167 168ImagesLoaded.prototype.addElementBackgroundImages = function( elem ) { 169 var style = getComputedStyle( elem ); 170 if ( !style ) { 171 // Firefox returns null if in a hidden iframe https://bugzil.la/548397 172 return; 173 } 174 // get url inside url("...") 175 var reURL = /url\((['"])?(.*?)\1\)/gi; 176 var matches = reURL.exec( style.backgroundImage ); 177 while ( matches !== null ) { 178 var url = matches && matches[2]; 179 if ( url ) {
vendor: 2,905 bytes, lines 180-280
180 this.addBackground( url, elem ); 181 } 182 matches = reURL.exec( style.backgroundImage ); 183 } 184}; 185 186/** 187 * @param {Image} img 188 */ 189ImagesLoaded.prototype.addImage = function( img ) { 190 var loadingImage = new LoadingImage( img ); 191 this.images.push( loadingImage ); 192}; 193 194ImagesLoaded.prototype.addBackground = function( url, elem ) { 195 var background = new Background( url, elem ); 196 this.images.push( background ); 197}; 198 199ImagesLoaded.prototype.check = function() { 200 var _this = this; 201 this.progressedCount = 0; 202 this.hasAnyBroken = false; 203 // complete if no images 204 if ( !this.images.length ) { 205 this.complete(); 206 return; 207 } 208 209 function onProgress( image, elem, message ) { 210 // HACK - Chrome triggers event before object properties have changed. #83 211 setTimeout( function() { 212 _this.progress( image, elem, message ); 213 }); 214 } 215 216 this.images.forEach( function( loadingImage ) { 217 loadingImage.once( 'progress', onProgress ); 218 loadingImage.check(); 219 }); 220}; 221 222ImagesLoaded.prototype.progress = function( image, elem, message ) { 223 this.progressedCount++; 224 this.hasAnyBroken = this.hasAnyBroken || !image.isLoaded; 225 // progress event 226 this.emitEvent( 'progress', [ this, image, elem ] ); 227 if ( this.jqDeferred && this.jqDeferred.notify ) { 228 this.jqDeferred.notify( this, image ); 229 } 230 // check if completed 231 if ( this.progressedCount == this.images.length ) { 232 this.complete(); 233 } 234 235 if ( this.options.debug && console ) { 236 console.log( 'progress: ' + message, image, elem ); 237 } 238}; 239 240ImagesLoaded.prototype.complete = function() { 241 var eventName = this.hasAnyBroken ? 'fail' : 'done'; 242 this.isComplete = true; 243 this.emitEvent( eventName, [ this ] ); 244 this.emitEvent( 'always', [ this ] ); 245 if ( this.jqDeferred ) { 246 var jqMethod = this.hasAnyBroken ? 'reject' : 'resolve'; 247 this.jqDeferred[ jqMethod ]( this ); 248 } 249}; 250 251// -------------------------- -------------------------- // 252 253function LoadingImage( img ) { 254 this.img = img; 255} 256 257LoadingImage.prototype = Object.create( EvEmitter.prototype ); 258 259LoadingImage.prototype.check = function() { 260 // If complete is true and browser supports natural sizes, 261 // try to check for image status manually. 262 var isComplete = this.getIsImageComplete(); 263 if ( isComplete ) { 264 // report based on naturalWidth 265 this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); 266 return; 267 } 268 269 // If none of the checks above matched, simulate loading on detached element. 270 this.proxyImage = new Image(); 271 this.proxyImage.addEventListener( 'load', this ); 272 this.proxyImage.addEventListener( 'error', this ); 273 // bind to image as well for Firefox. #191 274 this.img.addEventListener( 'load', this ); 275 this.img.addEventListener( 'error', this ); 276 this.proxyImage.src = this.img.src; 277}; 278 279LoadingImage.prototype.getIsImageComplete = function() { 280 return this.img.complete && this.img.naturalWidth !== undefined
vendor: 2,398 bytes, lines 280-370
280; 281}; 282 283LoadingImage.prototype.confirm = function( isLoaded, message ) { 284 this.isLoaded = isLoaded; 285 this.emitEvent( 'progress', [ this, this.img, message ] ); 286}; 287 288// ----- events ----- // 289 290// trigger specified handler for event type 291LoadingImage.prototype.handleEvent = function( event ) { 292 var method = 'on' + event.type; 293 if ( this[ method ] ) { 294 this[ method ]( event ); 295 } 296}; 297 298LoadingImage.prototype.onload = function() { 299 this.confirm( true, 'onload' ); 300 this.unbindEvents(); 301}; 302 303LoadingImage.prototype.onerror = function() { 304 this.confirm( false, 'onerror' ); 305 this.unbindEvents(); 306}; 307 308LoadingImage.prototype.unbindEvents = function() { 309 this.proxyImage.removeEventListener( 'load', this ); 310 this.proxyImage.removeEventListener( 'error', this ); 311 this.img.removeEventListener( 'load', this ); 312 this.img.removeEventListener( 'error', this ); 313}; 314 315// -------------------------- Background -------------------------- // 316 317function Background( url, element ) { 318 this.url = url; 319 this.element = element; 320 this.img = new Image(); 321} 322 323// inherit LoadingImage prototype 324Background.prototype = Object.create( LoadingImage.prototype ); 325 326Background.prototype.check = function() { 327 this.img.addEventListener( 'load', this ); 328 this.img.addEventListener( 'error', this ); 329 this.img.src = this.url; 330 // check if image is already complete 331 var isComplete = this.getIsImageComplete(); 332 if ( isComplete ) { 333 this.confirm( this.img.naturalWidth !== 0, 'naturalWidth' ); 334 this.unbindEvents(); 335 } 336}; 337 338Background.prototype.unbindEvents = function() { 339 this.img.removeEventListener( 'load', this ); 340 this.img.removeEventListener( 'error', this ); 341}; 342 343Background.prototype.confirm = function( isLoaded, message ) { 344 this.isLoaded = isLoaded; 345 this.emitEvent( 'progress', [ this, this.element, message ] ); 346}; 347 348// -------------------------- jQuery -------------------------- // 349 350ImagesLoaded.makeJQueryPlugin = function( jQuery ) { 351 jQuery = jQuery || window.jQuery; 352 if ( !jQuery ) { 353 return; 354 } 355 // set local variable 356 $ = jQuery; 357 // $().imagesLoaded() 358 $.fn.imagesLoaded = function( options, callback ) { 359 var instance = new ImagesLoaded( this, options, callback ); 360 return instance.jqDeferred.promise( $(this) ); 361 }; 362}; 363// try making plugin 364ImagesLoaded.makeJQueryPlugin(); 365 366// -------------------------- -------------------------- // 367 368return ImagesLoaded; 369 370});
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.