PageSourceSearch

https://www.citics.com.hk/includes/js/jquery/plugins/waitForImages/src/jquery.waitforimages.js

js citics.com.hk collected 2026-10-02 14:53:28 UTC 7,968 bytes, 219 lines download raw bytes

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

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.