]>
Commit | Line | Data |
---|---|---|
8e0ad1d9 | 1 | /* |
2 | * Lazy Load - jQuery plugin for lazy loading images | |
3 | * | |
4 | * Copyright (c) 2007-2013 Mika Tuupola | |
5 | * | |
6 | * Licensed under the MIT license: | |
7 | * http://www.opensource.org/licenses/mit-license.php | |
8 | * | |
9 | * Project home: | |
10 | * http://www.appelsiini.net/projects/lazyload | |
11 | * | |
12 | * Version: 1.9.3 | |
13 | * | |
14 | */ | |
15 | ||
16 | (function($, window, document, undefined) { | |
17 | var $window = $(window); | |
18 | ||
19 | $.fn.lazyload = function(options) { | |
20 | var elements = this; | |
21 | var $container; | |
22 | var settings = { | |
23 | threshold : 0, | |
24 | failure_limit : 0, | |
25 | event : "scroll", | |
26 | effect : "show", | |
27 | container : window, | |
28 | data_attribute : "original", | |
29 | skip_invisible : true, | |
30 | appear : null, | |
31 | load : null, | |
32 | placeholder : "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAAXNSR0IArs4c6QAAAARnQU1BAACxjwv8YQUAAAAJcEhZcwAADsQAAA7EAZUrDhsAAAANSURBVBhXYzh8+PB/AAffA0nNPuCLAAAAAElFTkSuQmCC" | |
33 | }; | |
34 | ||
35 | function update() { | |
36 | var counter = 0; | |
37 | ||
38 | elements.each(function() { | |
39 | var $this = $(this); | |
40 | if (settings.skip_invisible && !$this.is(":visible")) { | |
41 | return; | |
42 | } | |
43 | if ($.abovethetop(this, settings) || | |
44 | $.leftofbegin(this, settings)) { | |
45 | /* Nothing. */ | |
46 | } else if (!$.belowthefold(this, settings) && | |
47 | !$.rightoffold(this, settings)) { | |
48 | $this.trigger("appear"); | |
49 | /* if we found an image we'll load, reset the counter */ | |
50 | counter = 0; | |
51 | } else { | |
52 | if (++counter > settings.failure_limit) { | |
53 | return false; | |
54 | } | |
55 | } | |
56 | }); | |
57 | ||
58 | } | |
59 | ||
60 | if(options) { | |
61 | /* Maintain BC for a couple of versions. */ | |
62 | if (undefined !== options.failurelimit) { | |
63 | options.failure_limit = options.failurelimit; | |
64 | delete options.failurelimit; | |
65 | } | |
66 | if (undefined !== options.effectspeed) { | |
67 | options.effect_speed = options.effectspeed; | |
68 | delete options.effectspeed; | |
69 | } | |
70 | ||
71 | $.extend(settings, options); | |
72 | } | |
73 | ||
74 | /* Cache container as jQuery as object. */ | |
75 | $container = (settings.container === undefined || | |
76 | settings.container === window) ? $window : $(settings.container); | |
77 | ||
78 | /* Fire one scroll event per scroll. Not one scroll event per image. */ | |
79 | if (0 === settings.event.indexOf("scroll")) { | |
80 | $container.bind(settings.event, function() { | |
81 | return update(); | |
82 | }); | |
83 | } | |
84 | ||
85 | this.each(function() { | |
86 | var self = this; | |
87 | var $self = $(self); | |
88 | ||
89 | self.loaded = false; | |
90 | ||
91 | /* If no src attribute given use data:uri. */ | |
92 | if ($self.attr("src") === undefined || $self.attr("src") === false) { | |
93 | if ($self.is("img")) { | |
94 | $self.attr("src", settings.placeholder); | |
95 | } | |
96 | } | |
97 | ||
98 | /* When appear is triggered load original image. */ | |
99 | $self.one("appear", function() { | |
100 | if (!this.loaded) { | |
101 | if (settings.appear) { | |
102 | var elements_left = elements.length; | |
103 | settings.appear.call(self, elements_left, settings); | |
104 | } | |
105 | $("<img />") | |
106 | .bind("load", function() { | |
107 | ||
108 | var original = $self.attr("data-" + settings.data_attribute); | |
109 | $self.hide(); | |
110 | if ($self.is("img")) { | |
111 | $self.attr("src", original); | |
112 | } else { | |
113 | $self.css("background-image", "url('" + original + "')"); | |
114 | } | |
115 | $self[settings.effect](settings.effect_speed); | |
116 | ||
117 | self.loaded = true; | |
118 | ||
119 | /* Remove image from array so it is not looped next time. */ | |
120 | var temp = $.grep(elements, function(element) { | |
121 | return !element.loaded; | |
122 | }); | |
123 | elements = $(temp); | |
124 | ||
125 | if (settings.load) { | |
126 | var elements_left = elements.length; | |
127 | settings.load.call(self, elements_left, settings); | |
128 | } | |
129 | }) | |
130 | .attr("src", $self.attr("data-" + settings.data_attribute)); | |
131 | } | |
132 | }); | |
133 | ||
134 | /* When wanted event is triggered load original image */ | |
135 | /* by triggering appear. */ | |
136 | if (0 !== settings.event.indexOf("scroll")) { | |
137 | $self.bind(settings.event, function() { | |
138 | if (!self.loaded) { | |
139 | $self.trigger("appear"); | |
140 | } | |
141 | }); | |
142 | } | |
143 | }); | |
144 | ||
145 | /* Check if something appears when window is resized. */ | |
146 | $window.bind("resize", function() { | |
147 | update(); | |
148 | }); | |
149 | ||
150 | /* With IOS5 force loading images when navigating with back button. */ | |
151 | /* Non optimal workaround. */ | |
152 | if ((/(?:iphone|ipod|ipad).*os 5/gi).test(navigator.appVersion)) { | |
153 | $window.bind("pageshow", function(event) { | |
154 | if (event.originalEvent && event.originalEvent.persisted) { | |
155 | elements.each(function() { | |
156 | $(this).trigger("appear"); | |
157 | }); | |
158 | } | |
159 | }); | |
160 | } | |
161 | ||
162 | /* Force initial check if images should appear. */ | |
163 | $(document).ready(function() { | |
164 | update(); | |
165 | }); | |
166 | ||
167 | return this; | |
168 | }; | |
169 | ||
170 | /* Convenience methods in jQuery namespace. */ | |
171 | /* Use as $.belowthefold(element, {threshold : 100, container : window}) */ | |
172 | ||
173 | $.belowthefold = function(element, settings) { | |
174 | var fold; | |
175 | ||
176 | if (settings.container === undefined || settings.container === window) { | |
177 | fold = (window.innerHeight ? window.innerHeight : $window.height()) + $window.scrollTop(); | |
178 | } else { | |
179 | fold = $(settings.container).offset().top + $(settings.container).height(); | |
180 | } | |
181 | ||
182 | return fold <= $(element).offset().top - settings.threshold; | |
183 | }; | |
184 | ||
185 | $.rightoffold = function(element, settings) { | |
186 | var fold; | |
187 | ||
188 | if (settings.container === undefined || settings.container === window) { | |
189 | fold = $window.width() + $window.scrollLeft(); | |
190 | } else { | |
191 | fold = $(settings.container).offset().left + $(settings.container).width(); | |
192 | } | |
193 | ||
194 | return fold <= $(element).offset().left - settings.threshold; | |
195 | }; | |
196 | ||
197 | $.abovethetop = function(element, settings) { | |
198 | var fold; | |
199 | ||
200 | if (settings.container === undefined || settings.container === window) { | |
201 | fold = $window.scrollTop(); | |
202 | } else { | |
203 | fold = $(settings.container).offset().top; | |
204 | } | |
205 | ||
206 | return fold >= $(element).offset().top + settings.threshold + $(element).height(); | |
207 | }; | |
208 | ||
209 | $.leftofbegin = function(element, settings) { | |
210 | var fold; | |
211 | ||
212 | if (settings.container === undefined || settings.container === window) { | |
213 | fold = $window.scrollLeft(); | |
214 | } else { | |
215 | fold = $(settings.container).offset().left; | |
216 | } | |
217 | ||
218 | return fold >= $(element).offset().left + settings.threshold + $(element).width(); | |
219 | }; | |
220 | ||
221 | $.inviewport = function(element, settings) { | |
222 | return !$.rightoffold(element, settings) && !$.leftofbegin(element, settings) && | |
223 | !$.belowthefold(element, settings) && !$.abovethetop(element, settings); | |
224 | }; | |
225 | ||
226 | /* Custom selectors for your convenience. */ | |
227 | /* Use as $("img:below-the-fold").something() or */ | |
228 | /* $("img").filter(":below-the-fold").something() which is faster */ | |
229 | ||
230 | $.extend($.expr[":"], { | |
231 | "below-the-fold" : function(a) { return $.belowthefold(a, {threshold : 0}); }, | |
232 | "above-the-top" : function(a) { return !$.belowthefold(a, {threshold : 0}); }, | |
233 | "right-of-screen": function(a) { return $.rightoffold(a, {threshold : 0}); }, | |
234 | "left-of-screen" : function(a) { return !$.rightoffold(a, {threshold : 0}); }, | |
235 | "in-viewport" : function(a) { return $.inviewport(a, {threshold : 0}); }, | |
236 | /* Maintain BC for couple of versions. */ | |
237 | "above-the-fold" : function(a) { return !$.belowthefold(a, {threshold : 0}); }, | |
238 | "right-of-fold" : function(a) { return $.rightoffold(a, {threshold : 0}); }, | |
239 | "left-of-fold" : function(a) { return !$.rightoffold(a, {threshold : 0}); } | |
240 | }); | |
241 | ||
242 | })(jQuery, window, document); |