-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathjquery.lazyload.js
More file actions
189 lines (156 loc) · 7.64 KB
/
jquery.lazyload.js
File metadata and controls
189 lines (156 loc) · 7.64 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
/*
* jQuery lazyLoad plugin, version 1.0 [2012-06-22]
* Copyright 2012, Perfect Sense Digital, LLC
* Author: Brendan Brelsford [brendanb@gmail.com]
* Licensed under the MIT license [http://opensource.org/licenses/MIT]
*
* Usage:
*
* Invocation
*
* $('.classSelector').lazyLoad();
*
* Invocation with $.Deferred chaining
*
* $('.classSelector').lazyLoad().then(function() { ... });
*
* Events:
*
* The lazyLoad plugin returns a $.Deferred, which covers the equivalent of a "complete" event. In the specific case of lazy-loading images,
* an "error" event will be triggered on the <img> if the lazyLoad fails. This allows the UI to respond to bad image URLs. Since iframe loading
* doesn't provide an equivalent, the event will never be triggered for iframes.
*
* Options:
*
* Options are passed as a flat javascript object with the following allowed keys:
*
* "srcProp" - The HTML attribute in which the src value is stored.
* Allowed Values: any non-empty string, although "data-" prefixed values are preferred not to conflict with reserved attribute names.
* Default Value: "data-src"
*
* "removeSrcProp" - Indicates whether the attribute keyed by "srcProp" should be removed after the lazyLoad has completed. This does not affect
* the behavior of lazyLoad when it is invoked multiple times on the same element. It will always be called only once.
* Allowed Values: true / false
* Default Value: true
*
* "descend" - Indicates whether to search for descendents of the current jQuery set that contain the attribute keyed by "srcProp" and lazy-load them.
* Allowed Values: true / false
* Default Value: true
*
* "loadingClass" - CSS class applied to the objects to be loaded. This class will be applied as soon as lazyLoad is called and removed from each
* DOMNodeElement as it finishes loading.
* Allowed Values: any non-empty string
* Default Value: "loading"
*
* "maxTimeout" - The time (in milliseconds) after which the $.Deferred returned by lazyLoad will resolve whether or not all pending loads have completed.
* Allowed Values: integer > 0
* Default Value: 1000
*
* Examples:
*
* Add lazy-loading into a carousel / slide-show (e.g. Twitter bootstrap-carousel.js):
*
* var context = this;
* var callback = function() { -- original code to show the slide at specified index -- };
* $toSlide.lazyLoad().then(function() {
* callback.call(context);
* });
**/
if (typeof jQuery !== 'undefined') {
(function($) {
$.fn.lazyLoad = function(opts) {
var options = $.extend({
'srcProp': 'data-src',
'removeSrcProp': true,
'descend': true,
'loadingClass': 'loading',
'maxTimeout': 1000
}, opts);
/* Filter objects to only those that haven't yet been lazy-loaded */
var $objects = $(this).filter(function(index) {
return !($(this).data('lazyLoad') === true);
});
/* If "descend" is set to true, find descendants with attribute "options.srcProp" */
var $children = null;
if(options.descend === true) {
$children = $objects.add($objects.find('[' + options.srcProp + ']'));
}
/* Further reduce the objects to only those that have attribute "options.srcProp" */
$objects = $objects.filter('[' + options.srcProp + ']');
/* Add children if any were found */
if($children !== null && $children.size() > 0) {
$objects.add($children);
}
/* Set data to indicate that the image has been lazy-loaded. This flag is set before
* any actual work is done to remove the potential for race conditions that might lead
* to one image being loaded twice. */
$objects.data('lazyLoad', true);
var dfdList = [];
$objects.each(function() {
var $loadObject = $(this);
var src = $loadObject.attr('src');
var newSrc = $loadObject.attr(options.srcProp);
/* if the image has not been lazy-loaded and has a srcProp, proceed with loading */
if(newSrc != null) {
/* add a new deferred for this image to the array */
var dfd = new $.Deferred();
dfdList.push(dfd);
/* add loading class for CSS convenience */
$loadObject.addClass(options.loadingClass);
if($loadObject.is('img')) {
/* create an anonymous Image and define its load callback */
var i = new Image();
var $i = $(i)
$i.load(function() {
/* change src attribute to reflect the loaded srcProp */
$loadObject.attr('src', newSrc);
/* if "removeSrcProp" is set to true, remove the srcProp from the image element */
if(options.removeSrcProp) {
$loadObject.removeAttr(options.srcProp);
}
/* delete the anonymous image */
delete(i);
/* remove CSS loading class */
$loadObject.removeClass(options.loadingClass);
/* resolve this image's deferred */
dfd.resolve();
});
$i.error(function() {
$loadObject.trigger('error');
});
/* initiate loading of this image by setting its src prop.
load callback will execute when loading is complete */
i.src = newSrc;
}
if($loadObject.is('iframe')) {
$loadObject.load(function() {
/* if "removeSrcProp" is set to true, remove the srcProp from the iframe element */
if(options.removeSrcProp) {
$loadObject.removeAttr(options.srcProp);
}
/* remove CSS loading class */
$loadObject.removeClass(options.loadingClass);
/* resolve this image's deferred */
dfd.resolve();
});
$loadObject.attr('src', newSrc);
}
}
});
/* add timeout capability to returned deferred */
var loadOrTimeout = new $.Deferred();
/* when all images have loaded, resolve the returned deferred */
$.when.apply(null, dfdList).then(function() {
loadOrTimeout.resolve();
});
/* alternatively, if a maxTimeout is defined, resolve the returned deferred after the specified timeout has expired */
if(typeof(options.maxTimeout) === "number") {
setTimeout(function() {
loadOrTimeout.resolve();
}, options.maxTimeout);
}
/* return a deferred that will resolve after all images have loaded or after a specified timeout has expired */
return loadOrTimeout;
};
})(jQuery);
}