forked from 1000ch/lazyload-image
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathlazyload-image.js
121 lines (98 loc) · 3.31 KB
/
lazyload-image.js
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
/**
* <lazyload-image>
* HTMLImageElement extension for lazy loading.
* http://github.com/1000ch/lazyload-image
*
* Copyright 1000ch
* licensed under the MIT license.
*/
(function () {
'use strict';
var FALLBACK_IMAGE = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAYAAAAfFcSJAAAAEElEQVR42gEFAPr/AP///wAI/AL+Sr4t6gAAAABJRU5ErkJggg==';
var DEFAULT_OFFSET = 0;
/**
* throttle
* @param fn
* @param delay
* @returns {Function}
* @private
* @description forked from underscore.js
*/
function throttle(fn, delay) {
var context, args, result;
var timeout = null;
var previous = 0;
return function() {
var now = Date.now();
if (!previous) {
previous = now;
}
var remaining = delay - (now - previous);
context = this;
args = arguments;
if (remaining <= 0) {
clearTimeout(timeout);
timeout = null;
previous = now;
result = fn.apply(context, args);
context = args = null;
}
return result;
};
}
// create prototype from HTMLImageElement
var LazyloadImagePrototype = Object.create(HTMLImageElement.prototype);
// lifecycle callbacks
LazyloadImagePrototype.createdCallback = function () {
var that = this;
// swap original src attribute
this.original = this.currentSrc || this.src;
this.src = FALLBACK_IMAGE;
// get offset attribute for pre-loading
this.offset = Number(this.getAttribute('offset')) || DEFAULT_OFFSET;
this.onLoad = function (e) {
window.removeEventListener('scroll', that.onScroll);
};
this.onError = function (e) {
that.removeAttribute('srcset');
that.src = FALLBACK_IMAGE;
window.removeEventListener('scroll', that.onScroll);
};
this.onScroll = throttle(function (e) {
var rect = that.getBoundingClientRect();
var top = document.documentElement.scrollTop - that.offset;
var bottom = document.documentElement.clientHeight + that.offset;
if ((rect.bottom > top && rect.bottom < bottom) ||
(rect.top > top && rect.bottom < bottom) ||
(rect.top > top && rect.top < bottom )) {
that.addEventListener('load', that.onLoad);
that.addEventListener('error', that.onError);
that.src = that.original;
}
}, 300);
};
LazyloadImagePrototype.attachedCallback = function () {
var rect = this.getBoundingClientRect();
var top = document.documentElement.scrollTop - this.offset;
var bottom = document.documentElement.clientHeight + this.offset;
if ((rect.bottom > top && rect.bottom < bottom) ||
(rect.top > top && rect.bottom < bottom) ||
(rect.top > top && rect.top < bottom )) {
this.addEventListener('load', this.onLoad);
this.addEventListener('error', this.onError);
this.src = this.original;
} else {
window.addEventListener('scroll', this.onScroll);
}
};
LazyloadImagePrototype.detachedCallback = function () {
this.removeEventListener('load', this.onLoad);
this.removeEventListener('error', this.onError);
window.removeEventListener('scroll', this.onScroll);
};
// register element as lazyload-image
window.LazyloadImage = document.registerElement('lazyload-image', {
prototype: LazyloadImagePrototype,
extends: 'img'
});
})();