1/* 2 * waitForImages 1.4.2 3 * ------------------- 4 * Provides a callback when all images have loaded in your given selector. 5 * https://github.com/alexanderdickson/waitForImages 6 * 7 * Copyright (c) 2013 Alex Dickson 8 * Licensed under the MIT license. 9 */ 10(function ($) { 11 // Namespace all events. 12 var eventNamespace = 'waitForImages'; 13 14 // CSS properties which contain references to images. 15 $.waitForImages = { 16 hasImageProperties: ['backgroundImage', 'listStyleImage', 'borderImage', 'borderCornerImage'] 17 }; 18 19 // Custom selector to find `img` elements that have a valid `src` attribute and have not already loaded. 20 $.expr[':'].uncached = function (obj) { 21 // Ensure we are dealing with an `img` element with a valid `src` attribute. 22 if (!$(obj).is('img[src!=""]')) { 23 return false; 24 } 25 26 // Firefox's `complete` property will always be `true` even if the image has not been downloaded. 27 // Doing it this way works in Firefox. 28 var img = new Image(); 29 img.src = obj.src; 30 return !img.complete; 31 }; 32 33 $.fn.waitForImages = function (finishedCallback, eachCallback, waitForAll) { 34 35 var allImgsLength = 0; 36 var allImgsLoaded = 0; 37 38 // Handle options object. 39 if ($.isPlainObject(arguments[0])) { 40 waitForAll = arguments[0].waitForAll; 41 eachCallback = arguments[0].each; 42 // This must be last as arguments[0] 43 // is aliased with finishedCallback. 44 finishedCallback = arguments[0].finished; 45 } 46 47 // Handle missing callbacks. 48 finishedCallback = finishedCallback || $.noop; 49 eachCallback = eachCallback || $.noop; 50 51 // Convert waitForAll to Boolean 52 waitForAll = !! waitForAll; 53 54 // Ensure callbacks are functions. 55 if (!$.isFunction(finishedCallback) || !$.isFunction(eachCallback)) { 56 throw new TypeError('An invalid callback was supplied.'); 57 } 58 59 return this.each(function () { 60 // Build a list of all imgs, dependent on what images will be considered. 61 var obj = $(this); 62 var allImgs = []; 63 // CSS properties which may contain an image. 64 var hasImgProperties = $.waitForImages.hasImageProperties || []; 65 // To match `url()` references. 66 // Spec: http://www.w3.org/TR/CSS2/syndata.html#value-def-uri 67 var matchUrl = /url\(\s*(['"]?)(.*?)\1\s*\)/g; 68 69 if (waitForAll) { 70 71 // Get all elements (including the original), as any one of them could have a background image. 72 obj.find('*').andSelf().each(function () { 73 var element = $(this); 74 75 // If an `img` element, add it. But keep iterating in case it has a background image too. 76 if (element.is('img:uncached')) { 77 allImgs.push({ 78 src: element.attr('src'), 79 element: element[0] 80 }); 81 } 82 83 $.each(hasImgProperties, function (i, property) { 84 var propertyValue = element.css(property); 85 var match; 86 87 // If it doesn't contain this property, skip. 88 if (!propertyValue) { 89 return true; 90 } 91 92 // Get all url() of this element. 93 while (match = matchUrl.exec(propertyValue)) { 94 allImgs.push({ 95 src: match[2], 96 element: element[0] 97 }); 98 } 99 }); 100 }); 101 } else { 102 // For images only, the task is simpler. 103 obj.find('img:uncached') 104 .each(function () { 105 allImgs.push({ 106 src: this.src, 107 element: this 108 }); 109 }); 110 } 111 112 allImgsLength = allImgs.length; 113 allImgsLoaded = 0; 114 115 // If no images found, don't bother. 116 if (allImgsLength === 0) { 117 finishedCallback.call(obj[0]); 118 } 119 120 $.each(allImgs, function (i, img) { 121 122 var image = new Image(); 123 124 // Handle the image loading and error with the same callback. 125 $(image).bind('load.' + eventNamespace + ' error.' + eventNamespace, function (event) { 126 allImgsLoaded++; 127 128 // If an error occurred with loading the image, set the third argument accordingly. 129 eachCallback.call(img.element, allImgsLoaded, allImgsLength, event.type == 'load'); 130 131 if (allImgsLoaded == allImgsLength) { 132 finishedCallback.call(obj[0]); 133 return false;
134 } 135 136 }); 137 138 image.src = img.src; 139 }); 140 }); 141 }; 142}(jQuery));
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.