Skip to content

Commit 146b6ba

Browse files
authored
feat: add a mutationObserver to reload when some valid attributes changes (#192)
* feat: add a mutationObserver to reload when some valid attributes changes
1 parent 3f9bb22 commit 146b6ba

File tree

8 files changed

+149
-21
lines changed

8 files changed

+149
-21
lines changed

.gitignore

+1
Original file line numberDiff line numberDiff line change
@@ -4,3 +4,4 @@ node_modules
44
.DS_Store
55
thumbs.db
66
*.log*
7+
coverage

README.md

+3-1
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,9 @@
1212
- supports <img>, <picture>, iframes, videos, audios, responsive images, background images and multiple background images etc.
1313
- even supports LQIP (Low Quality Image Placeholder)
1414
- is completely free and open source.
15+
- it will reload when the valid attributes change.
1516

16-
It is written with an aim to lazy load images, iframes, ads, videos or any other element using the recently added [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) with tremendous performance benefits.
17+
It is written with an aim to lazy load images, iframes, ads, videos or any other element using the recently added [Intersection Observer API](https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API) and [MutationObserver](https://developer.mozilla.org/en-US/docs/Web/API/MutationObserver) with tremendous performance benefits.
1718

1819
## Featured in:
1920
- [Web | Google Developers](https://developers.google.com/web/fundamentals/performance/lazy-loading-guidance/images-and-video/)
@@ -112,6 +113,7 @@ or with custom options:
112113
const observer = lozad('.lozad', {
113114
rootMargin: '10px 0px', // syntax similar to that of CSS Margin
114115
threshold: 0.1 // ratio of element convergence
116+
enableAutoReload: true // it will reload the new image when validating attributes changes
115117
});
116118
observer.observe();
117119
```

demo/index.html

+10-2
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@ <h1><a href="https://github.com/ApoorvSaxena/lozad.js"><strong>Lozad.js</strong>
5858
<h1>Lozad.js - Performant Lazy Loading Library</h1>
5959
</article>
6060
<article class="thumb">
61-
<img class="lozad" data-placeholder-background="#583624" data-src="images/thumbs/01.jpg" data-index="1" />
61+
<img class="lozad" id="mutativeImg1" data-placeholder-background="#583624" data-src="images/thumbs/01.jpg" data-index="1" />
6262
<noscript><img src="images/thumbs/01.jpg" data-index="1" /></noscript>
6363
<h2>Image 1</h2>
6464
</article>
@@ -68,7 +68,7 @@ <h2>Image 1</h2>
6868
<h2>Image 2</h2>
6969
</article>
7070
<article class="thumb">
71-
<img class="lozad" data-placeholder-background="#352629" data-src="images/thumbs/03.jpg" data-index="3" />
71+
<img class="lozad" id="mutativeImg2" data-placeholder-background="#352629" data-src="images/thumbs/03.jpg" data-index="3" />
7272
<noscript><img src="images/thumbs/03.jpg" data-index="3" /></noscript>
7373
<h2>Image 3</h2>
7474
</article>
@@ -284,6 +284,7 @@ <h1>&lt;video> example</h1>
284284
// Initialize library to lazy load images
285285
var observer = lozad('.lozad', {
286286
threshold: 0.1,
287+
enableAutoReload: true,
287288
load: function(el) {
288289
el.src = el.getAttribute("data-src");
289290
el.onload = function() {
@@ -298,6 +299,13 @@ <h1>&lt;video> example</h1>
298299
threshold: 0.1
299300
})
300301

302+
window.onload = function () {
303+
setTimeout(function () {
304+
document.querySelector('#mutativeImg1').dataset.src = 'images/thumbs/02.jpg'
305+
document.querySelector('#mutativeImg2').dataset.src = 'images/thumbs/02.jpg'
306+
toastr["success"]("Once data-src change, the element render again.")
307+
}, 3000)
308+
}
301309
// Background observer
302310
// with default `load` method
303311
var backgroundObserver = lozad('.lozad-background', {

dist/lozad.es.js

+32-5
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*! lozad.js - v1.16.0 - 2020-09-06
1+
/*! lozad.js - v1.16.0 - 2020-09-10
22
* https://github.com/ApoorvSaxena/lozad.js
33
* Copyright (c) 2020 Apoorv Saxena; Licensed MIT */
44

@@ -10,9 +10,19 @@
1010
*/
1111
const isIE = typeof document !== 'undefined' && document.documentMode;
1212

13+
/**
14+
*
15+
* @param {string} type
16+
*
17+
*/
18+
const support = type => window && window[type];
19+
20+
const validAttribute = ['data-iesrc', 'data-alt', 'data-src', 'data-srcset', 'data-background-image', 'data-toggle-class'];
21+
1322
const defaultConfig = {
1423
rootMargin: '0px',
1524
threshold: 0,
25+
enableAutoReload: false,
1626
load(element) {
1727
if (element.nodeName.toLowerCase() === 'picture') {
1828
let img = element.querySelector('img');
@@ -114,6 +124,14 @@ const onIntersection = (load, loaded) => (entries, observer) => {
114124
});
115125
};
116126

127+
const onMutation = load => entries => {
128+
entries.forEach(entry => {
129+
if (isLoaded(entry.target) && entry.type === 'attributes' && validAttribute.indexOf(entry.attributeName) > -1) {
130+
load(entry.target);
131+
}
132+
});
133+
};
134+
117135
const getElements = (selector, root = document) => {
118136
if (selector instanceof Element) {
119137
return [selector]
@@ -127,17 +145,21 @@ const getElements = (selector, root = document) => {
127145
};
128146

129147
function lozad (selector = '.lozad', options = {}) {
130-
const {root, rootMargin, threshold, load, loaded} = Object.assign({}, defaultConfig, options);
148+
const {root, rootMargin, threshold, enableAutoReload, load, loaded} = Object.assign({}, defaultConfig, options);
131149
let observer;
132-
133-
if (typeof window !== 'undefined' && window.IntersectionObserver) {
150+
let mutationObserver;
151+
if (support('IntersectionObserver')) {
134152
observer = new IntersectionObserver(onIntersection(load, loaded), {
135153
root,
136154
rootMargin,
137155
threshold
138156
});
139157
}
140158

159+
if (support('MutationObserver') && enableAutoReload) {
160+
mutationObserver = new MutationObserver(onMutation(load, loaded));
161+
}
162+
141163
const elements = getElements(selector, root);
142164
for (let i = 0; i < elements.length; i++) {
143165
preLoad(elements[i]);
@@ -153,6 +175,10 @@ function lozad (selector = '.lozad', options = {}) {
153175
}
154176

155177
if (observer) {
178+
if (mutationObserver && enableAutoReload) {
179+
mutationObserver.observe(elements[i], {subtree: true, attributes: true, attributeFilter: validAttribute});
180+
}
181+
156182
observer.observe(elements[i]);
157183
continue
158184
}
@@ -171,7 +197,8 @@ function lozad (selector = '.lozad', options = {}) {
171197
markAsLoaded(element);
172198
loaded(element);
173199
},
174-
observer
200+
observer,
201+
mutationObserver
175202
}
176203
}
177204

dist/lozad.js

+36-4
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
/*! lozad.js - v1.16.0 - 2020-09-06
1+
/*! lozad.js - v1.16.0 - 2020-09-10
22
* https://github.com/ApoorvSaxena/lozad.js
33
* Copyright (c) 2020 Apoorv Saxena; Licensed MIT */
44

@@ -16,9 +16,21 @@
1616
*/
1717
var isIE = typeof document !== 'undefined' && document.documentMode;
1818

19+
/**
20+
*
21+
* @param {string} type
22+
*
23+
*/
24+
var support = function support(type) {
25+
return window && window[type];
26+
};
27+
28+
var validAttribute = ['data-iesrc', 'data-alt', 'data-src', 'data-srcset', 'data-background-image', 'data-toggle-class'];
29+
1930
var defaultConfig = {
2031
rootMargin: '0px',
2132
threshold: 0,
33+
enableAutoReload: false,
2234
load: function load(element) {
2335
if (element.nodeName.toLowerCase() === 'picture') {
2436
var img = element.querySelector('img');
@@ -124,6 +136,16 @@
124136
};
125137
};
126138

139+
var onMutation = function onMutation(load) {
140+
return function (entries) {
141+
entries.forEach(function (entry) {
142+
if (isLoaded(entry.target) && entry.type === 'attributes' && validAttribute.indexOf(entry.attributeName) > -1) {
143+
load(entry.target);
144+
}
145+
});
146+
};
147+
};
148+
127149
var getElements = function getElements(selector) {
128150
var root = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : document;
129151

@@ -146,19 +168,24 @@
146168
root = _Object$assign.root,
147169
rootMargin = _Object$assign.rootMargin,
148170
threshold = _Object$assign.threshold,
171+
enableAutoReload = _Object$assign.enableAutoReload,
149172
load = _Object$assign.load,
150173
loaded = _Object$assign.loaded;
151174

152175
var observer = void 0;
153-
154-
if (typeof window !== 'undefined' && window.IntersectionObserver) {
176+
var mutationObserver = void 0;
177+
if (support('IntersectionObserver')) {
155178
observer = new IntersectionObserver(onIntersection(load, loaded), {
156179
root: root,
157180
rootMargin: rootMargin,
158181
threshold: threshold
159182
});
160183
}
161184

185+
if (support('MutationObserver') && enableAutoReload) {
186+
mutationObserver = new MutationObserver(onMutation(load, loaded));
187+
}
188+
162189
var elements = getElements(selector, root);
163190
for (var i = 0; i < elements.length; i++) {
164191
preLoad(elements[i]);
@@ -174,6 +201,10 @@
174201
}
175202

176203
if (observer) {
204+
if (mutationObserver && enableAutoReload) {
205+
mutationObserver.observe(elements[_i], { subtree: true, attributes: true, attributeFilter: validAttribute });
206+
}
207+
177208
observer.observe(elements[_i]);
178209
continue;
179210
}
@@ -193,7 +224,8 @@
193224
loaded(element);
194225
},
195226

196-
observer: observer
227+
observer: observer,
228+
mutationObserver: mutationObserver
197229
};
198230
}
199231

dist/lozad.min.js

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

src/lozad.js

+31-4
Original file line numberDiff line numberDiff line change
@@ -5,9 +5,19 @@
55
*/
66
const isIE = typeof document !== 'undefined' && document.documentMode
77

8+
/**
9+
*
10+
* @param {string} type
11+
*
12+
*/
13+
const support = type => window && window[type]
14+
15+
const validAttribute = ['data-iesrc', 'data-alt', 'data-src', 'data-srcset', 'data-background-image', 'data-toggle-class']
16+
817
const defaultConfig = {
918
rootMargin: '0px',
1019
threshold: 0,
20+
enableAutoReload: false,
1121
load(element) {
1222
if (element.nodeName.toLowerCase() === 'picture') {
1323
let img = element.querySelector('img')
@@ -109,6 +119,14 @@ const onIntersection = (load, loaded) => (entries, observer) => {
109119
})
110120
}
111121

122+
const onMutation = load => entries => {
123+
entries.forEach(entry => {
124+
if (isLoaded(entry.target) && entry.type === 'attributes' && validAttribute.indexOf(entry.attributeName) > -1) {
125+
load(entry.target)
126+
}
127+
})
128+
}
129+
112130
const getElements = (selector, root = document) => {
113131
if (selector instanceof Element) {
114132
return [selector]
@@ -122,17 +140,21 @@ const getElements = (selector, root = document) => {
122140
}
123141

124142
export default function (selector = '.lozad', options = {}) {
125-
const {root, rootMargin, threshold, load, loaded} = Object.assign({}, defaultConfig, options)
143+
const {root, rootMargin, threshold, enableAutoReload, load, loaded} = Object.assign({}, defaultConfig, options)
126144
let observer
127-
128-
if (typeof window !== 'undefined' && window.IntersectionObserver) {
145+
let mutationObserver
146+
if (support('IntersectionObserver')) {
129147
observer = new IntersectionObserver(onIntersection(load, loaded), {
130148
root,
131149
rootMargin,
132150
threshold
133151
})
134152
}
135153

154+
if (support('MutationObserver') && enableAutoReload) {
155+
mutationObserver = new MutationObserver(onMutation(load, loaded))
156+
}
157+
136158
const elements = getElements(selector, root)
137159
for (let i = 0; i < elements.length; i++) {
138160
preLoad(elements[i])
@@ -148,6 +170,10 @@ export default function (selector = '.lozad', options = {}) {
148170
}
149171

150172
if (observer) {
173+
if (mutationObserver && enableAutoReload) {
174+
mutationObserver.observe(elements[i], {subtree: true, attributes: true, attributeFilter: validAttribute})
175+
}
176+
151177
observer.observe(elements[i])
152178
continue
153179
}
@@ -166,6 +192,7 @@ export default function (selector = '.lozad', options = {}) {
166192
markAsLoaded(element)
167193
loaded(element)
168194
},
169-
observer
195+
observer,
196+
mutationObserver
170197
}
171198
}

0 commit comments

Comments
 (0)