Skip to content

Commit b00fe7f

Browse files
committed
Major performance improvements
But still work TODO
1 parent 827ea19 commit b00fe7f

File tree

7 files changed

+460
-219
lines changed

7 files changed

+460
-219
lines changed

Diff for: Gruntfile.js

+1-1
Original file line numberDiff line numberDiff line change
@@ -39,7 +39,7 @@ module.exports = function(grunt) {
3939
},
4040
watch: {
4141
files: ['<%= jshint.files %>'],
42-
tasks: ['jshint']
42+
tasks: ['jshint', 'concat', 'uglify']
4343
}
4444
});
4545

Diff for: dist/lazyload.js

+249
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,249 @@
1+
/*
2+
* Lazy Load - for lazy loading images without jQuery
3+
*/
4+
5+
var lazyLoad = (function (window, document, undefined) {
6+
7+
var _elements,
8+
_settings,
9+
_processedElements = [],
10+
_defaultSettings = {
11+
threshold: 0,
12+
failure_limit: 0,
13+
event: "scroll",
14+
effect: "show",
15+
container: window,
16+
src_data_attribute: "original",
17+
//skip_invisible: true, // TODO: Restore this
18+
show_while_loading: false,
19+
process_callback: null,
20+
load_callback: null,
21+
set_callback: null,
22+
placeholder: "data:image/gif;base64,R0lGODlhAQABAIAAAAAAAP///yH5BAEAAAAALAAAAAABAAEAAAIBRAA7"
23+
},
24+
_supportsAddEventListener = !!window.addEventListener;
25+
26+
function _getOffset(element) {
27+
var theBox = element.getBoundingClientRect(),
28+
documentElement = element.ownerDocument.documentElement;
29+
return {
30+
top: theBox.top + window.pageYOffset - documentElement.clientTop,
31+
left: theBox.left + window.pageXOffset - documentElement.clientLeft
32+
};
33+
}
34+
35+
function _getDocumentWidth() {
36+
return window.innerWidth || (document.documentElement.clientWidth || document.body.clientWidth); //Math.max(visibleWidth, document.body.scrollWidth);
37+
}
38+
39+
function _getDocumentHeight() {
40+
return window.innerHeight || (document.documentElement.clientHeight || document.body.clientHeight); //Math.max(visibleHeight, document.body.scrollHeight);
41+
}
42+
43+
function _isBelowViewport(element) {
44+
var fold,
45+
container = _settings.container;
46+
47+
if (container === undefined || container === window) {
48+
fold = _getDocumentHeight() + window.pageYOffset;
49+
} else {
50+
fold = _getOffset(container).top + container.offsetHeight;
51+
}
52+
53+
return fold <= _getOffset(element).top - _settings.threshold;
54+
}
55+
56+
function _isAtRightOfViewport(element) {
57+
var fold,
58+
container = _settings.container;
59+
60+
if (container === undefined || container === window) {
61+
fold = _getDocumentWidth() + window.pageXOffset;
62+
} else {
63+
fold = _getOffset(container).left + _getDocumentWidth();
64+
}
65+
66+
return fold <= _getOffset(element).left - _settings.threshold;
67+
}
68+
69+
function _isAboveViewport(element) {
70+
var fold,
71+
container = _settings.container;
72+
73+
if (container === undefined || container === window) {
74+
fold = window.pageYOffset;
75+
} else {
76+
fold = _getOffset(container).top;
77+
}
78+
79+
return fold >= _getOffset(element).top + _settings.threshold + element.offsetHeight;
80+
}
81+
82+
function _isAtLeftOfViewport(element) {
83+
var fold,
84+
container = _settings.container;
85+
86+
if (container === undefined || container === window) {
87+
fold = window.pageXOffset;
88+
} else {
89+
fold = _getOffset(container).left;
90+
}
91+
92+
return fold >= _getOffset(element).left + _settings.threshold + element.offsetWidth;
93+
}
94+
95+
function _merge_options(obj1, obj2) {
96+
var obj3 = {}, propertyName;
97+
for (propertyName in obj1) {
98+
if (obj1.hasOwnProperty(propertyName)) {
99+
obj3[propertyName] = obj1[propertyName];
100+
}
101+
}
102+
for (propertyName in obj2) {
103+
if (obj2.hasOwnProperty(propertyName)) {
104+
obj3[propertyName] = obj2[propertyName];
105+
}
106+
}
107+
return obj3;
108+
}
109+
110+
function _getOriginalSrc(element) {
111+
var dataAttributeContent;
112+
dataAttributeContent = element.getAttribute('data-' + _settings.src_data_attribute);
113+
return dataAttributeContent || _settings.placeholder;
114+
}
115+
116+
function _setImageAndDisplay(element) {
117+
/* Setting `src` in the original `img` */
118+
var original = _getOriginalSrc(element);
119+
if (element.nodeName.toLowerCase() === "img") {
120+
element.setAttribute("src", original);
121+
} else {
122+
element.style.backgroundImage = "url('" + original + "')";
123+
}
124+
_callCallback(element, "set_callback");
125+
}
126+
127+
function _callCallback(element, callbackName) {
128+
if (_settings[callbackName]) {
129+
_settings[callbackName].call(element, _elements.length, _settings);
130+
}
131+
}
132+
133+
function _showOnLoad(element) {
134+
135+
var fakeImg;
136+
137+
/* If no src attribute given use data:uri. */
138+
if (!element.getAttribute("src")) {
139+
element.setAttribute("src", _settings.placeholder);
140+
}
141+
/* Creating a new `img` in a DOM fragment. */
142+
fakeImg = document.createElement('img');
143+
/* Listening to the load event */
144+
if (_supportsAddEventListener) {
145+
fakeImg.addEventListener("load", function () {
146+
_callCallback(element, "load_callback");
147+
_setImageAndDisplay(element);
148+
fakeImg.removeEventListener("load");
149+
});
150+
}
151+
else {
152+
// TODO: fallback for IE<9
153+
}
154+
/* Setting the source in the fake image */
155+
fakeImg.setAttribute("src", _getOriginalSrc(element));
156+
}
157+
158+
function _showOnAppear(element) {
159+
if (_supportsAddEventListener) {
160+
element.addEventListener("load", function () {
161+
_callCallback(element, "load_callback");
162+
element.removeEventListener("load");
163+
});
164+
}
165+
else {
166+
// TODO: fallback for IE<9
167+
}
168+
_setImageAndDisplay(element);
169+
}
170+
171+
function _processImage(element) {
172+
//if (-1 === _processedElements.indexOf(element)) { // TODO: This check is necessary? (evaluate not only the scroll event case)
173+
_callCallback(element, "process_callback");
174+
/* Forking behaviour depending on show_while_loading (true value is ideal for progressive jpeg). */
175+
if (_settings.show_while_loading) {
176+
_showOnAppear(element);
177+
} else {
178+
_showOnLoad(element);
179+
}
180+
/* Marking the element as processed so is not processed next time. */
181+
_processedElements.push(element);
182+
//}
183+
}
184+
185+
function _purgeElementsArray() {
186+
_processedElements.forEach(function (element) {
187+
var indexOfProcessedElement = _elements.indexOf(element);
188+
if (indexOfProcessedElement === -1) return;
189+
_elements.splice(indexOfProcessedElement, 1);
190+
});
191+
_processedElements = [];
192+
}
193+
194+
return {
195+
initialize: function (elements, options) {
196+
_elements = Array.prototype.slice.call(elements, 0);
197+
_settings = _merge_options(_defaultSettings, options);
198+
199+
if (_supportsAddEventListener) {
200+
/* If event is scroll, add scroll event listener in the container (not in every single image) */
201+
if (0 === _settings.event.indexOf("scroll")) {
202+
_settings.container.addEventListener(_settings.event, function () {
203+
return lazyLoad.update();
204+
});
205+
}
206+
/* If event is not, add event listener every single image */
207+
else {
208+
_elements.forEach(function (element) {
209+
element.addEventListener(_settings.event, function () {
210+
_processImage(element);
211+
});
212+
});
213+
}
214+
}
215+
else {
216+
// TODO: fallback for IE<9
217+
}
218+
219+
lazyLoad.update();
220+
},
221+
update: function () {
222+
var countBeforeFail = 0;
223+
_elements.forEach(function (element) {
224+
225+
// TODO: Find a way to replicate "isVisible"
226+
/*if (_settings.skip_invisible && !$this.is(":visible")) {
227+
return;
228+
}*/
229+
230+
if (_isAboveViewport(element) ||
231+
_isAtLeftOfViewport(element)) {
232+
/* Nothing. */
233+
} else if (!_isBelowViewport(element) && !_isAtRightOfViewport(element)) {
234+
_processImage(element);
235+
/* If we found an image we'll load, reset the counter */
236+
countBeforeFail = 0;
237+
} else {
238+
if (++countBeforeFail > _settings.failure_limit) {
239+
// This should break the forEach, does it?
240+
return false;
241+
}
242+
}
243+
});
244+
245+
_purgeElementsArray();
246+
}
247+
};
248+
249+
}(window, document));

Diff for: dist/lazyload.min.js

+2-2
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Diff for: dist/lazyload.min.js.map

+1-1
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)