@duckafire/lazy-loading-js 2.0.2 → 3.0.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +68 -118
- package/dist/lazy-loading.min.js +1 -0
- package/package.json +29 -7
- package/src/LazyLoadingImage.js +0 -177
package/README.md
CHANGED
|
@@ -1,157 +1,107 @@
|
|
|
1
|
-
|
|
1
|
+
[wiki-lazy-load]: https://en.wikipedia.org/wiki/Lazy_loading "Wikipedia: Lazy Loading technique"
|
|
2
|
+
[int-ob]: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API "Intersection Observer API"
|
|
3
|
+
[caiuse-int-ob]: https://caniuse.com/intersectionobserver "Can I use IntersectionObserver API?"
|
|
4
|
+
[origin-repo]: https://github.com/gyanprabhat7/LazyLoad.JS "From GitHub"
|
|
5
|
+
[int-ob-opt]: https://developer.mozilla.org/en-US/docs/Web/API/Intersection_Observer_API#creating_an_intersection_observer "IntersectionObserver constructor options"
|
|
2
6
|
|
|
3
|
-
##
|
|
7
|
+
## LazyLoading.js
|
|
4
8
|
|
|
5
|
-
|
|
6
|
-
|
|
9
|
+
This project is a no-dependence library that aims to available simple and light
|
|
10
|
+
implementations of the [Lazy Loading][wiki-lazy-load] technique to improve the
|
|
11
|
+
optimization of specific elements, objects, and/or components from FrontEnd WEB pages.
|
|
12
|
+
Currently, it supports:
|
|
7
13
|
|
|
8
|
-
|
|
14
|
+
* Images (`<img/>`).
|
|
9
15
|
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
* [Choose a class](#choose-a-class)
|
|
14
|
-
* [Start the API](#start-the-api)
|
|
15
|
-
* [API Methods](#api-methods)
|
|
16
|
-
* [Constructor](#constructor)
|
|
17
|
-
* [`start`](#start)
|
|
18
|
-
* [`disconnectFromObserver`](#disconnectfromobserver)
|
|
19
|
-
* [Incompatibility browsers](#incompatibility-browsers)
|
|
20
|
-
|
|
21
|
-
### Usage
|
|
22
|
-
|
|
23
|
-
#### Import the API
|
|
24
|
-
|
|
25
|
-
Import the API in your HTML code:
|
|
26
|
-
|
|
27
|
-
``` html
|
|
28
|
-
<script src="https://cdn.jsdelivr.net/npm/@duckafire/lazy-loading-js@2.0.2/src/LazyLoadingImage.js"></script>
|
|
16
|
+
```html
|
|
17
|
+
<!-- CDN (jsDelivr) URL -->
|
|
18
|
+
<script src="https://cdn.jsdelivr.net/npm/@duckafire/lazy-loading-js@3/dist/lazy-loading.min.js"></script>
|
|
29
19
|
```
|
|
30
20
|
|
|
31
|
-
[
|
|
32
|
-
|
|
33
|
-
>
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
Choose which `img` will use the API, then set the properties below:
|
|
38
|
-
|
|
39
|
-
* `data-src`: contains the original image - high quality. It will be used when
|
|
40
|
-
the `img` is visible.
|
|
41
|
-
|
|
42
|
-
* `data-placeholder`: contains an low quality image that will be used when image
|
|
43
|
-
is not visible. Used for avoid the breaking of the page layout.
|
|
44
|
-
|
|
45
|
-
``` html
|
|
46
|
-
<img data-src="./foo.png" data-placeholder="./foo-placeholder.png"/>
|
|
47
|
-
```
|
|
48
|
-
|
|
49
|
-
#### Choose a class
|
|
50
|
-
|
|
51
|
-
Attribute a specific class to all elements whose visibility will be controlled
|
|
52
|
-
by the API.
|
|
53
|
-
|
|
54
|
-
``` html
|
|
55
|
-
<img class="foo" data-src="./foo.png" data-placeholder="./foo-placeholder.png"/>
|
|
56
|
-
```
|
|
57
|
-
|
|
58
|
-
#### Start the API
|
|
59
|
-
|
|
60
|
-
Instance a object using the class (choosed in the last step) as first argument and enjoy!
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
``` html
|
|
64
|
-
<img class="foo" data-src="./foo.png" data-placeholder="./foo-placeholder.png"/>
|
|
65
|
-
|
|
66
|
-
<script>
|
|
67
|
-
new LazyLoadingImage(".foo");
|
|
21
|
+
> [!IMPORTANT]
|
|
22
|
+
> If [`IntersectionObserver`][int-ob] (**core** of this project) is not available in the
|
|
23
|
+
> client's browser, nothing fallback observer algorithm will be implemented and the
|
|
24
|
+
> high quality image will be attributed to `src`.
|
|
25
|
+
> See more about the availability of this class [here][caniuse-int-ob].
|
|
68
26
|
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
</script>
|
|
72
|
-
```
|
|
27
|
+
> [!NOTE]
|
|
28
|
+
> This project is a fork from [gyanprabhat7/LazyLoad.JS][origin-repo].
|
|
73
29
|
|
|
74
|
-
### API methods
|
|
75
30
|
|
|
76
|
-
#### Constructor
|
|
77
31
|
|
|
78
|
-
|
|
79
|
-
the query specificed.
|
|
32
|
+
#### Index
|
|
80
33
|
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
34
|
+
* [LazyLoadingImages](#lazyloadingimages)
|
|
35
|
+
* [Element attributes](#element-attributes)
|
|
36
|
+
* [Methods](#methods)
|
|
37
|
+
* [isApiAvailable](#isapiavailable)
|
|
38
|
+
* [isStarted](#isstarted)
|
|
39
|
+
* [startToObserve](#starttoobserve)
|
|
86
40
|
|
|
87
41
|
> [!IMPORTANT]
|
|
88
|
-
>
|
|
89
|
-
|
|
90
|
-
##### Exceptions
|
|
42
|
+
> To improve the understanding of this documentation, types was added to
|
|
91
43
|
|
|
92
|
-
* None element was found with the specified query.
|
|
93
|
-
* Element type (`img`, `div`, ...) invalid - only `img` is allow.
|
|
94
44
|
|
|
95
|
-
##### Console
|
|
96
45
|
|
|
97
|
-
|
|
46
|
+
### LazyLoadingImages
|
|
98
47
|
|
|
99
|
-
|
|
48
|
+
---
|
|
100
49
|
|
|
101
|
-
|
|
50
|
+
* `constructor(query: string, [options: ILLImagesOptions])`
|
|
51
|
+
* `query`: query selector used to catch target elements.
|
|
52
|
+
* `options`: set of options to customize API behavior.
|
|
102
53
|
|
|
103
|
-
|
|
54
|
+
| Options | Default | Description |
|
|
55
|
+
| :-- | :-: | :-- |
|
|
56
|
+
| waitToStart: boolean | false | it defines API do not have to be started after to create the object. |
|
|
57
|
+
| styleClasses: IStyleClasses | {} | set of lists of CSS classes they have to be added/removed to/from the catched elements when the show/hide event occur. |
|
|
58
|
+
| observerOptions: IIOOptions | {} | options to `IntersectionObserver` constructor. See [this][int-ob-opt] to get more information about. |
|
|
59
|
+
| useSrcAsFallbackToLazySrc: boolean | true | if `true`, it defines `src` content is the lazy quality image if `data-lazy` is undefined, else it defines `src` content is the high quality image if `data-high` is undefined. |
|
|
104
60
|
|
|
105
|
-
|
|
61
|
+
---
|
|
106
62
|
|
|
107
|
-
|
|
63
|
+
#### Element attributes
|
|
108
64
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
| warning | boolean | false | it allows console warning and error messages. |
|
|
65
|
+
* `data-high`: path of the high quality image. It is optional if
|
|
66
|
+
`options.useSrcAsFallbackToLazySrc === false`.
|
|
112
67
|
|
|
113
|
-
|
|
68
|
+
* `data-lazy`: path of the lazy quality image. It is optional if
|
|
69
|
+
`options.useSrcAsFallbackToLazySrc === true`.
|
|
114
70
|
|
|
115
|
-
*
|
|
71
|
+
* `data-style-high` (optional): comman-separated list formed of CSS styles they will
|
|
72
|
+
be given to the catched elements when the show/hide event occur.
|
|
116
73
|
|
|
117
|
-
|
|
74
|
+
* `data-style-lazy` (optional): comman-separated list formed of CSS styles they will
|
|
75
|
+
be given to the catched elements when the show/hide event occur.
|
|
118
76
|
|
|
119
|
-
|
|
77
|
+
#### Methods
|
|
120
78
|
|
|
121
|
-
|
|
79
|
+
##### isApiAvailable
|
|
122
80
|
|
|
123
|
-
|
|
81
|
+
* `isApiAvailable(): boolean`
|
|
124
82
|
|
|
125
|
-
*
|
|
126
|
-
|
|
83
|
+
* Behavior: verify if the API is available.
|
|
84
|
+
* Return: result, in boolean.
|
|
127
85
|
|
|
128
|
-
|
|
86
|
+
---
|
|
129
87
|
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
> [!NOTE]
|
|
133
|
-
> This method is declared inside `#connectToObserver` (*private* method).
|
|
88
|
+
##### isStarted
|
|
134
89
|
|
|
135
|
-
|
|
136
|
-
| :-- | :-- | :-- | :-- |
|
|
137
|
-
| *None* | | | |
|
|
90
|
+
* `isStarted(): boolean`
|
|
138
91
|
|
|
139
|
-
|
|
92
|
+
* Behavior: verify if the API algorithm was started.
|
|
93
|
+
* Return: result, in boolean.
|
|
140
94
|
|
|
141
|
-
|
|
95
|
+
---
|
|
142
96
|
|
|
143
|
-
#####
|
|
97
|
+
##### startToObserve
|
|
144
98
|
|
|
145
|
-
|
|
99
|
+
* `startToObserve(): void`
|
|
146
100
|
|
|
147
|
-
*
|
|
101
|
+
* Behavior: start the API algorithm.
|
|
102
|
+
* Return: none.
|
|
148
103
|
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
* *None.*
|
|
152
|
-
|
|
153
|
-
### Incompatibility browsers
|
|
104
|
+
> [!NOTE]
|
|
105
|
+
> It prints a *warning* in the console, if API is already started.
|
|
154
106
|
|
|
155
|
-
|
|
156
|
-
API*. If the user's browser do not have support to this Standard API, the
|
|
157
|
-
`data-src` image will load without lazy loading.
|
|
107
|
+
---
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
"use strict";const __LL_SrcGroup__=Object.freeze({INIT:0,HIGH:1,LAZY:2});class __LL_TV__{constructor(e){this.exceptionMessage="A type error occur.",this.fallbackWarning=null,this.value=e}expect(e){var t,s;this.isExpAlreadyDefined(),this.isUndef(e);const r=typeof e;if("string"===r){const t=typeof this.value;return this.isValidValue="object"===e?null!==this.value&&t===e:"array"===e?Array.isArray(this.value):t===e,this.exceptionMessage=`Expecting type "${e}", instead "${t}".`,this}if("function"!==r)throw new TypeError(`Expecting constructor, instead "${r}".`);return this.isValidValue=this.value instanceof HTMLImageElement,this.exceptionMessage=`Expecting instance or heir of \`${e.constructor.name}\`, instead \`${null===(s=null===(t=this.value)||void 0===t?void 0:t.constructor)||void 0===s?void 0:s.name}\`.`,this}fallback(e,t=!1){if(void 0!==this.fallbackValue)throw new SyntaxError("Fallback already defined.");return this.isUndef(e),t&&(this.fallbackWarning=new Error("Invalid value type. Using fallback.")),this.fallbackValue=e,this}val(){if(void 0===this.isValidValue)throw new SyntaxError("Expected value not defined.");if(this.isValidValue)return this.value;if(void 0!==this.fallbackValue)return null!==this.fallbackWarning&&console.warn(this.fallbackWarning),this.fallbackValue;throw new TypeError(this.exceptionMessage)}isUndef(e){if(void 0===e)throw new TypeError("`undefined` is invalid.")}isExpAlreadyDefined(){if(void 0!==this.isValidValue)throw new SyntaxError("Expected value already defined.")}}class APIUnavailableError extends Error{constructor(){super("Intersection Observer API is unavailable. High quality images are in use.")}}class __LL_Element__{constructor(e,t){this.curGroup=__LL_SrcGroup__.INIT,this.elem=new __LL_TV__(e).expect(HTMLImageElement).val(),this.setAttribute(),this.imgSrc={high:this.catchSrc("high",!t),lazy:this.catchSrc("lazy",t)},this.styleClasses={high:this.catchStyles("high"),lazy:this.catchStyles("lazy")},this.clearBootAttr()}useSrc(e,t){if(t!==__LL_SrcGroup__.HIGH){if(t!==__LL_SrcGroup__.LAZY)throw new SyntaxError(`Invalid source group: "${t}".`);this.toggleSrc(__LL_SrcGroup__.LAZY,this.imgSrc.lazy)&&this.toggleStyles(__LL_SrcGroup__.LAZY,e)}else this.toggleSrc(__LL_SrcGroup__.HIGH,this.imgSrc.high)&&this.toggleStyles(__LL_SrcGroup__.HIGH,e)}setGroupIndex(e){this.elem.dataset.lliId=e.toString()}getAsHTMLImg(){return this.elem}apiUnavailable(){this.useSrc({high:null,lazy:null},__LL_SrcGroup__.HIGH)}setAttribute(){null===this.elem.getAttribute("loading")&&this.elem.setAttribute("loading","lazy")}catchSrc(e,t){if(void 0!==this.elem.dataset[e])return this.elem.dataset[e];if(t)return this.elem.src;throw new Error(`Element attribute not found: \`data-${e}\`.`)}catchStyles(e){var t;return(null===(t=this.elem.getAttribute("data-style-"+e))||void 0===t?void 0:t.split(",").map(e=>e.trim()))||null}clearBootAttr(){for(const e of["high","lazy","styleHigh","styleLazy"])this.elem.removeAttribute("data-"+e)}toggleSrc(e,t){return this.curGroup!==e&&(this.curGroup=e,this.elem.src=t,!0)}toggleStyles(e,t){this.toggleIndieStyles(e,t),this.toggleIndieStyles(e,this.styleClasses)}toggleIndieStyles(e,t){let s=t.lazy,r=t.high;e===__LL_SrcGroup__.LAZY&&(s=t.high,r=t.lazy),null!==s&&this.elem.classList.remove(...s),null!==r&&this.elem.classList.add(...r)}}class __LL_ElementsGroup__{constructor(e,t,s){this.elements=[],this.styleClasses={high:this.valStyle(s.high),lazy:this.valStyle(s.lazy)},this.catchElements(new __LL_TV__(e).expect("string").val(),t)}useSrc(e,t){this.elements[e].useSrc(this.styleClasses,t)}startToObserve(e){this.elements.forEach((t,s)=>{t.setGroupIndex(s),e.observe(t.getAsHTMLImg())})}apiUnavailable(){for(let e=0;e<this.elements.length;e++)this.apiUnavailable()}valStyle(e){if(!e)return null;for(const t of new __LL_TV__(e).expect("array").val())new __LL_TV__(t).expect("string").val();return e}catchElements(e,t){document.querySelectorAll(e).forEach(e=>{this.elements.push(new __LL_Element__(e,t))})}}class __LL_Observer__{constructor(e,t){this.isAvailable();const s={root:new __LL_TV__(e.root).expect(HTMLElement).fallback(null).val(),rootMargin:new __LL_TV__(e.rootMargin).expect("string").fallback("0px 0px 0px 0px").val(),scrollMargin:new __LL_TV__(e.scrollMargin).expect("string").fallback("0px 0px 0px 0px").val(),threshold:this.valThreshold(e.threshold)};this.api=this.startAPI(s),this.elementsGroup=t}useSrc(e,t){this.elementsGroup.useSrc(parseInt(e.target.dataset.lliId),t)}startToObserve(){this.elementsGroup.startToObserve(this.api)}valThreshold(e){if(!Array.isArray(e))return new __LL_TV__(e).expect("number").fallback(0).val();for(const t of e)new __LL_TV__(t).expect("number").val();return e}isAvailable(){if(void 0===window.IntersectionObserver)throw this.elementsGroup.apiUnavailable(),new APIUnavailableError}startAPI(e){return new IntersectionObserver(e=>{e.forEach(e=>{this.useSrc(e,e.isIntersecting?__LL_SrcGroup__.HIGH:__LL_SrcGroup__.LAZY)})},e)}}class LazyLoadingImages{constructor(e,t){this.isApiAvail=!0,this.started=!1;const s=new __LL_TV__(t).expect("object").fallback({},!0).val();try{this.observer=new __LL_Observer__(s.observerOptions||{},new __LL_ElementsGroup__(e,s.useSrcAsFallbackToLazySrc||!0,s.styleClasses||{}))}catch(e){throw e instanceof APIUnavailableError&&(this.isApiAvail=!1),e}s.waitToStart||this.startToObserve()}isApiAvailable(){return this.isApiAvail}isStarted(){return this.started}startToObserve(){this.started?console.warn(new Error("API already started.")):(this.started=!0,this.observer.startToObserve())}}
|
package/package.json
CHANGED
|
@@ -1,24 +1,46 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "@duckafire/lazy-loading-js",
|
|
3
3
|
"author": "duckafire",
|
|
4
|
-
"version": "
|
|
4
|
+
"version": "3.0.1",
|
|
5
5
|
"license": "Zlib",
|
|
6
|
-
"description": "Simple lazy loading
|
|
7
|
-
"keywords": [
|
|
6
|
+
"description": "Simple, no-dependeces, lazy loading implementation to FrontEnd WEB",
|
|
7
|
+
"keywords": [
|
|
8
|
+
"client",
|
|
9
|
+
"html",
|
|
10
|
+
"images",
|
|
11
|
+
"web",
|
|
12
|
+
"front-end",
|
|
13
|
+
"optimization",
|
|
14
|
+
"lazy",
|
|
15
|
+
"loading",
|
|
16
|
+
"lazy-loading"
|
|
17
|
+
],
|
|
18
|
+
"devDependencies": {
|
|
19
|
+
"terser": "^5.43.1",
|
|
20
|
+
"typescript": "^4.9.5"
|
|
21
|
+
},
|
|
8
22
|
"repository": {
|
|
9
23
|
"type": "git",
|
|
10
24
|
"url": "git+https://github.com/duckafire/lazy-loading-js.git"
|
|
11
25
|
},
|
|
26
|
+
"scripts": {
|
|
27
|
+
"build": "./scripts.js build",
|
|
28
|
+
"clear": "./scripts.js clear",
|
|
29
|
+
"compile": "./scripts.js compile",
|
|
30
|
+
"help": "./scripts.js help",
|
|
31
|
+
"minify": "./scripts.js minify",
|
|
32
|
+
"publish": "./scripts.js clear && ./scripts.js build && npm publish"
|
|
33
|
+
},
|
|
12
34
|
"files": [
|
|
13
35
|
"LICENSE",
|
|
14
36
|
"README.md",
|
|
15
|
-
"
|
|
37
|
+
"dist/*.min.js"
|
|
16
38
|
],
|
|
17
39
|
"custom-fields": {
|
|
18
40
|
"cloud-repostories": [
|
|
19
|
-
"https://github.com/duckafire/lazy-loading-js
|
|
20
|
-
"https://gitlab.com/duckafire/lazy-loading-js
|
|
21
|
-
"https://npmjs.com/package/@duckafire/lazy-loading-js
|
|
41
|
+
"https://github.com/duckafire/lazy-loading-js",
|
|
42
|
+
"https://gitlab.com/duckafire/lazy-loading-js",
|
|
43
|
+
"https://npmjs.com/package/@duckafire/lazy-loading-js"
|
|
22
44
|
]
|
|
23
45
|
}
|
|
24
46
|
}
|
package/src/LazyLoadingImage.js
DELETED
|
@@ -1,177 +0,0 @@
|
|
|
1
|
-
/*
|
|
2
|
-
Zlib License
|
|
3
|
-
|
|
4
|
-
Copyright (C) 2025 DuckAfire <duckafire.github.io/nest>
|
|
5
|
-
|
|
6
|
-
This software is provided 'as-is', without any express or implied
|
|
7
|
-
warranty. In no event will the authors be held liable for any damages
|
|
8
|
-
arising from the use of this software.
|
|
9
|
-
|
|
10
|
-
Permission is granted to anyone to use this software for any purpose,
|
|
11
|
-
including commercial applications, and to alter it and redistribute it
|
|
12
|
-
freely, subject to the following restrictions:
|
|
13
|
-
|
|
14
|
-
1. The origin of this software must not be misrepresented; you must not
|
|
15
|
-
claim that you wrote the original software. If you use this software
|
|
16
|
-
in a product, an acknowledgment in the product documentation would be
|
|
17
|
-
appreciated but is not required.
|
|
18
|
-
2. Altered source versions must be plainly marked as such, and must not be
|
|
19
|
-
misrepresented as being the original software.
|
|
20
|
-
3. This notice may not be removed or altered from any source distribution.
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
class LazyLoadingImage {
|
|
24
|
-
#items; #hasSupport;
|
|
25
|
-
|
|
26
|
-
#started = false;
|
|
27
|
-
|
|
28
|
-
#ELEMENT_INSTANCE = HTMLImageElement;
|
|
29
|
-
|
|
30
|
-
#HIDED = "-1";
|
|
31
|
-
#AWAITING = "0";
|
|
32
|
-
#SHOWED = "1";
|
|
33
|
-
|
|
34
|
-
constructor(query, startWarning, awaitToStart) {
|
|
35
|
-
this.#items = document.querySelectorAll(query);
|
|
36
|
-
|
|
37
|
-
if(this.#items.length == 0)
|
|
38
|
-
throw new Error(`None was found. Query: "${query}"`);
|
|
39
|
-
|
|
40
|
-
this.#items.forEach(item => {
|
|
41
|
-
if(!(item instanceof this.#ELEMENT_INSTANCE))
|
|
42
|
-
throw new Error(`Invalid instance. Expected "${this.constructor.name}" instead "${item.constructor.name}".` );
|
|
43
|
-
|
|
44
|
-
if(item instanceof HTMLImageElement)
|
|
45
|
-
item.loading = "lazy";
|
|
46
|
-
});
|
|
47
|
-
|
|
48
|
-
if(!awaitToStart)
|
|
49
|
-
this.start(startWarning);
|
|
50
|
-
}
|
|
51
|
-
|
|
52
|
-
start(warning) {
|
|
53
|
-
if(this.#started){
|
|
54
|
-
if(warning){
|
|
55
|
-
console.warn(
|
|
56
|
-
(this.hasSupport)
|
|
57
|
-
? "This instance already was started."
|
|
58
|
-
: "This browser do not support the Intersection Observer API."
|
|
59
|
-
);
|
|
60
|
-
}
|
|
61
|
-
|
|
62
|
-
return;
|
|
63
|
-
}
|
|
64
|
-
|
|
65
|
-
this.#started = true;
|
|
66
|
-
this.#hasSupport = ("IntersectionObserver" in window)
|
|
67
|
-
|
|
68
|
-
if(this.#hasSupport){
|
|
69
|
-
this.#items.forEach(item => {
|
|
70
|
-
this.#awaitToWorking(item);
|
|
71
|
-
this.#connectToObserver(item);
|
|
72
|
-
});
|
|
73
|
-
return;
|
|
74
|
-
}
|
|
75
|
-
|
|
76
|
-
this.#showAllWithoutObserver();
|
|
77
|
-
|
|
78
|
-
if(warning){
|
|
79
|
-
console.error(
|
|
80
|
-
"This browser do not suppor the Intersection Observer API - from JavaScript. " +
|
|
81
|
-
"So the resources that depend of it it will be loaded without optimizations of loading."
|
|
82
|
-
);
|
|
83
|
-
}
|
|
84
|
-
}
|
|
85
|
-
|
|
86
|
-
#showAllWithoutObserver(){
|
|
87
|
-
this.#items.forEach(item => {
|
|
88
|
-
this.#showSource(item);
|
|
89
|
-
});
|
|
90
|
-
}
|
|
91
|
-
|
|
92
|
-
#checkItemPosition(pos0, pos1, isWidth){
|
|
93
|
-
const max = window["inner" + (isWidth ? "Width" : "Height")];
|
|
94
|
-
|
|
95
|
-
return (pos0 >= 0 && pos0 <= max) || (pos1 >= 0 && pos1 <= max);
|
|
96
|
-
}
|
|
97
|
-
|
|
98
|
-
#awaitToWorking(item){
|
|
99
|
-
this.#setItemProperties(item);
|
|
100
|
-
|
|
101
|
-
item.onload = () => {
|
|
102
|
-
let loader = new Image();
|
|
103
|
-
loader.src = item.dataset.src;
|
|
104
|
-
|
|
105
|
-
loader.onload = () => {
|
|
106
|
-
loader = null; // "throw" in the collect garbage
|
|
107
|
-
item.dataset.awaiting = "no";
|
|
108
|
-
|
|
109
|
-
// hitbox
|
|
110
|
-
const hb = item.getBoundingClientRect();
|
|
111
|
-
|
|
112
|
-
// if the screen was maintened stopped, after page (re)load,
|
|
113
|
-
// the Intersection... will not update
|
|
114
|
-
if(this.#checkItemPosition(hb.top, hb.bottom) || this.#checkItemPosition(hb.left, hb.right, true))
|
|
115
|
-
this.#showSource(item, this.#SHOWED);
|
|
116
|
-
}
|
|
117
|
-
}
|
|
118
|
-
}
|
|
119
|
-
|
|
120
|
-
#setItemProperties(item){
|
|
121
|
-
item.src = item.dataset.placeholder;
|
|
122
|
-
item.dataset.currentSrc = item.dataset.placeholder;
|
|
123
|
-
item.dataset.state = this.#AWAITING;
|
|
124
|
-
item.dataset.awaiting = "yes";
|
|
125
|
-
}
|
|
126
|
-
|
|
127
|
-
#connectToObserver(item){
|
|
128
|
-
const api = new IntersectionObserver(entities => {
|
|
129
|
-
entities.forEach(entity => {
|
|
130
|
-
if(entity.target.dataset.awaiting == "yes")
|
|
131
|
-
return;
|
|
132
|
-
|
|
133
|
-
if(entity.isIntersecting)
|
|
134
|
-
this.#showSource(entity.target, this.#SHOWED);
|
|
135
|
-
|
|
136
|
-
else
|
|
137
|
-
this.#hideSource(entity.target, this.#HIDED);
|
|
138
|
-
});
|
|
139
|
-
});
|
|
140
|
-
|
|
141
|
-
api.observe(item);
|
|
142
|
-
|
|
143
|
-
if(this.disconnectFromObserver == undefined){
|
|
144
|
-
this.disconnectFromObserver = () => {
|
|
145
|
-
this.#started = false;
|
|
146
|
-
|
|
147
|
-
this.#items.forEach(item => {
|
|
148
|
-
api.unobserve(item);
|
|
149
|
-
entity.target.dataset.state = this.#AWAITING;
|
|
150
|
-
});
|
|
151
|
-
}
|
|
152
|
-
}
|
|
153
|
-
}
|
|
154
|
-
|
|
155
|
-
#updateSource(item, state, dataProperty){
|
|
156
|
-
if(item.dataset[dataProperty] != undefined){
|
|
157
|
-
// avoid unnecessary reload
|
|
158
|
-
if((item.dataset.state != state || item.dataset.state == this.#AWAITING) && item.dataset.currentSrc != item.dataset[dataProperty]){
|
|
159
|
-
item.dataset.state = state;
|
|
160
|
-
item.src = item.dataset[dataProperty];
|
|
161
|
-
item.dataset.currentSrc = item.dataset[dataProperty];
|
|
162
|
-
}
|
|
163
|
-
|
|
164
|
-
return;
|
|
165
|
-
}
|
|
166
|
-
|
|
167
|
-
throw new Error(`Data property "data-${dataProperty}" not found.`);
|
|
168
|
-
}
|
|
169
|
-
|
|
170
|
-
#showSource(item, state){
|
|
171
|
-
this.#updateSource(item, state, "src");
|
|
172
|
-
}
|
|
173
|
-
|
|
174
|
-
#hideSource(item, state){
|
|
175
|
-
this.#updateSource(item, state, "placeholder");
|
|
176
|
-
}
|
|
177
|
-
}
|