1/*! waitForImages jQuery Plugin - v2.0.2 - 2015-06-02 2* https://github.com/alexanderdickson/waitForImages 3* Copyright (c) 2015 Alex Dickson; Licensed MIT */ 4;(function (factory) { 5 if (typeof define === 'function' && define.amd) { 6 // AMD. Register as an anonymous module. 7 define(['jquery'], factory); 8 } else if (typeof exports === 'object') { 9 // CommonJS / nodejs module 10 module.exports = factory(require('jquery')); 11 } else { 12 // Browser globals 13 factory(jQuery); 14 } 15}(function ($) { 16 // Namespace all events. 17 var eventNamespace = 'waitForImages'; 18 19 // CSS properties which contain references to images. 20 $.waitForImages = { 21 hasImageProperties: [ 22 'backgroundImage', 23 'listStyleImage', 24 'borderImage', 25 'borderCornerImage', 26 'cursor' 27 ], 28 hasImageAttributes: ['srcset'] 29 }; 30 31 // Custom selector to find all `img` elements with a valid `src` attribute. 32 $.expr[':']['has-src'] = function (obj) { 33 // Ensure we are dealing with an `img` element with a valid 34 // `src` attribute. 35 return $(obj).is('img[src][src!=""]'); 36 }; 37 38 // Custom selector to find images which are not already cached by the 39 // browser. 40 $.expr[':'].uncached = function (obj) { 41 // Ensure we are dealing with an `img` element with a valid 42 // `src` attribute. 43 if (!$(obj).is(':has-src')) { 44 return false; 45 } 46 47 return !obj.complete; 48 }; 49 50 $.fn.waitForImages = function () { 51 52 var allImgsLength = 0; 53 var allImgsLoaded = 0; 54 var deferred = $.Deferred(); 55 56 var finishedCallback; 57 var eachCallback; 58 var waitForAll; 59 60 // Handle options object (if passed). 61 if ($.isPlainObject(arguments[0])) { 62 63 waitForAll = arguments[0].waitForAll; 64 eachCallback = arguments[0].each; 65 finishedCallback = arguments[0].finished; 66 67 } else { 68 69 // Handle if using deferred object and only one param was passed in. 70 if (arguments.length === 1 && $.type(arguments[0]) === 'boolean') { 71 waitForAll = arguments[0]; 72 } else { 73 finishedCallback = arguments[0]; 74 eachCallback = arguments[1]; 75 waitForAll = arguments[2]; 76 } 77 78 } 79 80 // Handle missing callbacks. 81 finishedCallback = finishedCallback || $.noop; 82 eachCallback = eachCallback || $.noop; 83 84 // Convert waitForAll to Boolean 85 waitForAll = !! waitForAll; 86 87 // Ensure callbacks are functions. 88 if (!$.isFunction(finishedCallback) || !$.isFunction(eachCallback)) { 89 throw new TypeError('An invalid callback was supplied.'); 90 } 91 92 this.each(function () { 93 // Build a list of all imgs, dependent on what images will 94 // be considered. 95 var obj = $(this); 96 var allImgs = []; 97 // CSS properties which may contain an image. 98 var hasImgProperties = $.waitForImages.hasImageProperties || []; 99 // Element attributes which may contain an image. 100 var hasImageAttributes = $.waitForImages.hasImageAttributes || []; 101 // To match `url()` references. 102 // Spec: http://www.w3.org/TR/CSS2/syndata.html#value-def-uri 103 var matchUrl = /url\(\s*(['"]?)(.*?)\1\s*\)/g; 104 105 if (waitForAll) { 106 107 // Get all elements (including the original), as any one of 108 // them could have a background image. 109 obj.find('*').addBack().each(function () { 110 var element = $(this); 111 112 // If an `img` element, add it. But keep iterating in 113 // case it has a background image too. 114 if (element.is('img:has-src')) { 115 allImgs.push({ 116 src: element.attr('src'), 117 element: element[0] 118 }); 119 } 120 121 $.each(hasImgProperties, function (i, property) { 122 var propertyValue = element.css(property); 123 var match; 124 125 // If it doesn't contain this property, skip. 126 if (!propertyValue) { 127 return true; 128 } 129 130 // Get all url() of this element. 131 while (match = matchUrl.exec(propertyValue)) { 132 allImgs.push({ 133 src: match[2], 134 element: element[0] 135 }); 136 } 137 }); 138 139 $.each(hasImageAttributes, function (i, attribute) { 140 var attributeValue = element.attr(attribute); 141 var attributeValues; 142 143 // If it doesn't contain this property, skip. 144 if (!attributeValue) { 145 return true; 146 } 147 148 // Check for multiple comma separated images 149 attributeValues = attributeValue.split(','); 150 151 $.each(attributeValues, function(i, value) { 152 // Trim value and get string before first 153 // whitespace (for use with srcset). 154 value = $.trim(value).split(' ')[0]; 155 allImgs.push({ 156 src: value, 157 element: element[0] 158 }); 159 }); 160 }); 161 }); 162 } else { 163 // For images only, the task is simpler. 164 obj.find('img:has-src') 165 .each(function () { 166 allImgs.push({ 167 src: this.src, 168 element: this 169 }); 170 }); 171 } 172 173 allImgsLength = allImgs.length; 174 allImgsLoaded = 0; 175 176 // If no images found, don't bother. 177 if (allImgsLength === 0) { 178 finishedCallback.call(obj[0]); 179 deferred.resolveWith(obj[0]); 180 } 181 182 $.each(allImgs, function (i, img) { 183 184 var image = new Image(); 185 var events = 186 'load.' + eventNamespace + ' error.' + eventNamespace; 187 188 // Handle the image loading and error with the same callback. 189 $(image).one(events, function me (event) { 190 // If an error occurred with loading the image, set the 191 // third argument accordingly. 192 var eachArguments = [ 193 allImgsLoaded, 194 allImgsLength, 195 event.type == 'load' 196 ]; 197 allImgsLoaded++; 198 199 eachCallback.apply(img.element, eachArguments); 200 deferred.notifyWith(img.element, eachArguments); 201 202 // Unbind the event listeners. I use this in addition to 203 // `one` as one of those events won't be called (either 204 // 'load' or 'error' will be called). 205 $(this).off(events, me); 206 207 if (allImgsLoaded == allImgsLength) { 208 finishedCallback.call(obj[0]); 209 deferred.resolveWith(obj[0]); 210 return false; 211 } 212 213 }); 214 215 image.src = img.src; 216 }); 217 }); 218 219 return deferred.promise(); 220 221 }; 222}));
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.