From d61cd432977028325fe3a99624d60339911a5611 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 2 Jul 2023 16:39:44 +0300 Subject: [PATCH 001/185] Feature: Lazy bg option --- README.md | 25 +++++----------- src/lazy.js | 86 +++++++++++++++++++++++++++++++++++++++++------------ 2 files changed, 75 insertions(+), 36 deletions(-) diff --git a/README.md b/README.md index baf3eeb..c3129d1 100644 --- a/README.md +++ b/README.md @@ -4,32 +4,23 @@ Lazy Load Images is a JavaScript utility that allows you to lazy load visual con ## Usage -To use Lazy Load Images, include the `lazyLoadImages` function in your JavaScript code. The function takes two optional parameters: +To use Lazy Load Images, include the `lazyLoad` function in your JavaScript code. The function takes two optional parameters: -- `selector` (string, default: '[lazy]'): CSS selector for lazy load items. -- `options` (object): IntersectionObserver options. +- `selector` (string, default: 'lazy'): CSS selector for lazy load items. +- `observerOptions` (object): Options for the Intersection Observer. -If no selector is provided, the default selector '[lazy]' will be used. -If no options are provided, default options will be used. - -```html - - -``` +If no selector is provided, the default selector 'lazy' will be used. +If no observer options are provided, default options will be used. ```javascript -lazyLoad(); - -// Or - -lazyLoad('[lazy]', { +lazyLoad('lazy', { root: null, threshold: 1, rootMargin: '300px 0px', }); ``` -The lazy load functionality will be applied to all elements that match the given selector. When an element approaches the visible area of the screen, its 'lazy' attribute will be used as the source for the 'src' attribute, and the element will be marked as loaded by adding the '-loaded' class. +The lazy load functionality will be applied to all elements that match the specified selector. When an element comes into view, its 'lazy' attribute will be used as the source for the 'src' attribute, and the element will be marked as loaded by adding the '-loaded' class. ## Developer @@ -37,4 +28,4 @@ The lazy load functionality will be applied to all elements that match the given ## License -[MIT](https://choosealicense.com/licenses/mit/) +[MIT License](https://choosealicense.com/licenses/mit/). diff --git a/src/lazy.js b/src/lazy.js index a915ff2..7f85055 100644 --- a/src/lazy.js +++ b/src/lazy.js @@ -1,36 +1,84 @@ /** - * Lazy loads visual content when it approaches - * the visible area of the screen to increase - * page loading speed. + * Lazily loads assets based on intersection observer. * - * @param {string} [selector='[lazy]'] - CSS selector for lazy load items. - * @param {Object} [options] - IntersectionObserver options. + * @param {string} [selector='lazy'] - Selector for lazy load elements. + * @param {IntersectionObserverInit} [observerOptions={ + * root: null, + * threshold: 1, + * rootMargin: '300px 0px', + * }] - Options for the intersection observer. */ -const lazyLoad = (selector = '[lazy]', options = {}) => { - const lazyLoadItems = document.querySelectorAll(selector); - - const defaultOptions = { +const lazyLoad = ( + selector = 'lazy', + observerOptions = { root: null, threshold: 1, rootMargin: '300px 0px', + } +) => { + /** + * Options for lazy loading. + * + * @type {object} + * + * @property {string} tag - Attribute name for lazy load elements. + * @property {string} backgroundImage - Attribute name for lazy load elements with background image. + * @property {string} loaded - Class name to add when the asset is loaded. + */ + const options = { + tag: selector, + backgroundImage: `${selector}-bg`, + loaded: '-loaded', }; - const mergedOptions = { ...defaultOptions, ...options }; + /** + * Loads the asset for the given element. + * + * @param {HTMLElement} element - The element to load the asset for. + */ + const loadAsset = (element) => { + const assetPath = element.getAttribute(options.tag); + + if (!assetPath) return; + + if (element.hasAttribute(options.backgroundImage)) { + element.style.backgroundImage = `url(${assetPath})`; + element.removeAttribute(options.backgroundImage); + } else { + element.setAttribute('src', assetPath); + } + + element.classList.add(options.loaded); + element.removeAttribute(options.tag); + }; - const observer = new IntersectionObserver((entries, observer) => { + /** + * Handles the intersection of lazy load elements. + * + * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer. + * @param {IntersectionObserver} observer - The intersection observer instance. + */ + const handleIntersection = (entries, observer) => { entries.forEach((entry) => { if (!entry.isIntersecting) return; - const target = entry.target; - const value = target.getAttribute('lazy'); + loadAsset(entry.target); + observer.unobserve(entry.target); + }); + }; - target.classList.add('-loaded'); - target.removeAttribute('lazy'); - target.setAttribute('src', value); + const observer = new IntersectionObserver( + handleIntersection, + observerOptions + ); - observer.unobserve(target); - }); - }, mergedOptions); + /** + * Select 'selector' which is not empty. + * `[lazy]:not([lazy=''])` + */ + const lazyLoadItems = document.querySelectorAll( + `[${options.tag}]:not([${options.tag}=''])` + ); lazyLoadItems.forEach((item) => observer.observe(item)); }; From 6a1716fc5610dcc704e49f4e486bc73716f84aac Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 9 Jul 2023 00:55:54 +0300 Subject: [PATCH 002/185] Delete: Developer section --- README.md | 4 ---- 1 file changed, 4 deletions(-) diff --git a/README.md b/README.md index c3129d1..ab3d5d8 100644 --- a/README.md +++ b/README.md @@ -22,10 +22,6 @@ lazyLoad('lazy', { The lazy load functionality will be applied to all elements that match the specified selector. When an element comes into view, its 'lazy' attribute will be used as the source for the 'src' attribute, and the element will be marked as loaded by adding the '-loaded' class. -## Developer - -[@drementer](https://github.com/drementer) - ## License [MIT License](https://choosealicense.com/licenses/mit/). From 022048fb5dbe926d0d178b560ae5b394eafb807d Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 9 Jul 2023 00:56:54 +0300 Subject: [PATCH 003/185] Delete: Unused script --- package.json | 3 --- 1 file changed, 3 deletions(-) diff --git a/package.json b/package.json index 1c4e759..0713efc 100644 --- a/package.json +++ b/package.json @@ -3,9 +3,6 @@ "version": "1.0.5", "homepage": "https://github.com/drementer/lazy-load.js", "description": "Loads visual content when it approaches the visible area of ​​the screen to increase page loading speed.", - "scripts": { - "build": "parcel build src/lazy.js --dist-dir dist --no-source-maps" - }, "keywords": [ "js", "lazy", From cfd1ef393b9168afb4363758f4a5b623dcf9c85f Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 9 Jul 2023 00:57:13 +0300 Subject: [PATCH 004/185] Update: Version --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 0713efc..c5f36c3 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lazy-load.js", - "version": "1.0.5", + "version": "1.0.6", "homepage": "https://github.com/drementer/lazy-load.js", "description": "Loads visual content when it approaches the visible area of ​​the screen to increase page loading speed.", "keywords": [ From 2068b264ac5cbe0fe870fdeda5023579e1bdd80c Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 9 Jul 2023 00:57:39 +0300 Subject: [PATCH 005/185] Add: Source and main --- package.json | 2 ++ 1 file changed, 2 insertions(+) diff --git a/package.json b/package.json index c5f36c3..651f1b5 100644 --- a/package.json +++ b/package.json @@ -3,6 +3,8 @@ "version": "1.0.6", "homepage": "https://github.com/drementer/lazy-load.js", "description": "Loads visual content when it approaches the visible area of ​​the screen to increase page loading speed.", + "source": "src/index.js", + "main": "src/index.js", "keywords": [ "js", "lazy", From 68b44059ca951974f757065093fa28a994163253 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 9 Jul 2023 00:58:16 +0300 Subject: [PATCH 006/185] Update: Package info order --- package.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 651f1b5..8baf1be 100644 --- a/package.json +++ b/package.json @@ -12,12 +12,12 @@ "lazy-load.js" ], "author": "drementer (https://github.com/drementer)", - "license": "MIT", "repository": { "type": "git", "url": "git+https://github.com/drementer/lazy-load.js.git" }, "bugs": { "url": "https://github.com/drementer/lazy-load.js/issues" - } + }, + "license": "MIT" } From ab60e7f2631184655f88fc7b19824e9082197336 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 9 Jul 2023 00:58:45 +0300 Subject: [PATCH 007/185] Refactor: Prettier --- package.json | 40 ++++++++++++++++++++-------------------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/package.json b/package.json index 8baf1be..3e31672 100644 --- a/package.json +++ b/package.json @@ -1,23 +1,23 @@ { - "name": "lazy-load.js", - "version": "1.0.6", - "homepage": "https://github.com/drementer/lazy-load.js", - "description": "Loads visual content when it approaches the visible area of ​​the screen to increase page loading speed.", - "source": "src/index.js", + "name": "lazy-load.js", + "version": "1.0.6", + "homepage": "https://github.com/drementer/lazy-load.js", + "description": "Loads visual content when it approaches the visible area of ​​the screen to increase page loading speed.", + "source": "src/index.js", "main": "src/index.js", - "keywords": [ - "js", - "lazy", - "lazy load", - "lazy-load.js" - ], - "author": "drementer (https://github.com/drementer)", - "repository": { - "type": "git", - "url": "git+https://github.com/drementer/lazy-load.js.git" - }, - "bugs": { - "url": "https://github.com/drementer/lazy-load.js/issues" - }, - "license": "MIT" + "keywords": [ + "js", + "lazy", + "lazy load", + "lazy-load.js" + ], + "author": "drementer (https://github.com/drementer)", + "repository": { + "type": "git", + "url": "git+https://github.com/drementer/lazy-load.js.git" + }, + "bugs": { + "url": "https://github.com/drementer/lazy-load.js/issues" + }, + "license": "MIT" } From 69249db3d1710bd324065ebf36a4e6151cb9137b Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 9 Jul 2023 00:59:00 +0300 Subject: [PATCH 008/185] Update: File name --- src/{lazy.js => index.js} | 10 +++++----- test/index.html | 2 +- 2 files changed, 6 insertions(+), 6 deletions(-) rename src/{lazy.js => index.js} (96%) diff --git a/src/lazy.js b/src/index.js similarity index 96% rename from src/lazy.js rename to src/index.js index 7f85055..1d15cf6 100644 --- a/src/lazy.js +++ b/src/index.js @@ -72,13 +72,13 @@ const lazyLoad = ( observerOptions ); - /** - * Select 'selector' which is not empty. - * `[lazy]:not([lazy=''])` - */ + /** + * Select 'selector' which is not empty. + * `[lazy]:not([lazy=''])` + */ const lazyLoadItems = document.querySelectorAll( `[${options.tag}]:not([${options.tag}=''])` ); lazyLoadItems.forEach((item) => observer.observe(item)); -}; +}; \ No newline at end of file diff --git a/test/index.html b/test/index.html index bc53a52..3631246 100644 --- a/test/index.html +++ b/test/index.html @@ -39,7 +39,7 @@ Random Image - + From eb15bd874f339cbf329d5b1b3deaf18f69fa46d3 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Tue, 1 Aug 2023 23:24:59 +0300 Subject: [PATCH 012/185] Update: func names --- src/index.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/index.js b/src/index.js index 8547934..bede9bb 100644 --- a/src/index.js +++ b/src/index.js @@ -46,7 +46,7 @@ const lazyLoad = (selector = '[lazy]', options = {}) => { * @param {string} assetAttr - The asset URL attribute value. * @param {string} assetAlt - The asset alt attribute value. */ - const loadAssetImage = (img, assetAttr, assetAlt) => { + const loadImage = (img, assetAttr, assetAlt) => { img.src = assetAttr; img.alt = assetAlt; }; @@ -60,13 +60,13 @@ const lazyLoad = (selector = '[lazy]', options = {}) => { * @param {string} assetAttr - The asset URL attribute value. * @param {string} assetAlt - The asset alt attribute value. */ - const loadAssetPicture = (element, assetAttr, assetAlt) => { + const loadPicture = (element, assetAttr, assetAlt) => { let img = element.querySelector('img'); if (!img) { img = document.createElement('img'); element.append(img); } - loadAssetImage(img, assetAttr, assetAlt); + loadImage(img, assetAttr, assetAlt); }; /** @@ -77,7 +77,7 @@ const lazyLoad = (selector = '[lazy]', options = {}) => { * @param {HTMLVideoElement} element - The video element to load the asset for. * @param {string} assetAttr - The asset URL attribute value. */ - const loadAssetVideo = (element, assetAttr) => { + const loadVideo = (element, assetAttr) => { element.src = assetAttr; }; @@ -99,9 +99,9 @@ const lazyLoad = (selector = '[lazy]', options = {}) => { const assetAlt = element.getAttribute(`lazy-alt`) || ''; const backgroundAttr = element.getAttribute(`lazy-background`); - if (isImage) return loadAssetImage(element, assetAttr, assetAlt); - if (isPicture) return loadAssetPicture(element, assetAttr, assetAlt); - if (isVideo) return loadAssetVideo(element, assetAttr); + if (isImage) return loadImage(element, assetAttr, assetAlt); + if (isPicture) return loadPicture(element, assetAttr, assetAlt); + if (isVideo) return loadVideo(element, assetAttr); element.src = assetAttr; }; From eb06a955581d11c618e04a760b5bdae0ebf0bc42 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Tue, 1 Aug 2023 23:31:10 +0300 Subject: [PATCH 013/185] Add: new func --- src/index.js | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/index.js b/src/index.js index bede9bb..e366cfb 100644 --- a/src/index.js +++ b/src/index.js @@ -51,6 +51,10 @@ const lazyLoad = (selector = '[lazy]', options = {}) => { img.alt = assetAlt; }; + const loadBackground = (element, assetAttr) => { + element.style.background = `url(${assetAttr})`; + }; + /** * Loads the asset for the given picture element. * @@ -99,6 +103,7 @@ const lazyLoad = (selector = '[lazy]', options = {}) => { const assetAlt = element.getAttribute(`lazy-alt`) || ''; const backgroundAttr = element.getAttribute(`lazy-background`); + if (backgroundAttr) return loadBackground(element, backgroundAttr); if (isImage) return loadImage(element, assetAttr, assetAlt); if (isPicture) return loadPicture(element, assetAttr, assetAlt); if (isVideo) return loadVideo(element, assetAttr); From bcc37cb0bbb24465871135fb16cc7f979ccdddaf Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 3 Aug 2023 00:16:11 +0300 Subject: [PATCH 014/185] Update: comment blocks --- src/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index e366cfb..e1cc3f8 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,5 @@ /** - * Lazy loads assets for elements with lazy attributes (e.g., lazy-src, lazy-alt). + * Lazy loads assets for elements. * * @param {string} [selector="[lazy]"] - The CSS selector for lazy loadable elements. * @param {Object} [options={}] - Additional options for configuring the lazy loading behavior. @@ -10,7 +10,7 @@ const lazyLoad = (selector = '[lazy]', options = {}) => { * * @type {Object} * - * @param {string} [otag=selector] - The CSS selector for lazy loadable elements. + * @param {string} [tag=selector] - The CSS selector for lazy loadable elements. * @param {string} [toggleClass="-loaded"] - The class name to toggle on elements after loading. * @param {Function} [onLoaded=(element)=>{}] - Callback function to execute when an element is successfully loaded. * @param {Function} [onError=(element, error)=>{}] - Callback function to execute when an error occurs during loading. From 0ba50c45ac13e091dc220b6e8907684b4dc71cf4 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 6 Aug 2023 11:40:35 +0300 Subject: [PATCH 015/185] Update: Console log type for error --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index e1cc3f8..230fcbf 100644 --- a/src/index.js +++ b/src/index.js @@ -21,7 +21,7 @@ const lazyLoad = (selector = '[lazy]', options = {}) => { toggleClass: '-loaded', onLoaded: () => {}, onError: (element, error) => { - console.log('🚀 Error on ~ element, error:', element, error); + console.error('🚀 Error on ~ element, error:', element, error); }, observer: { root: null, From d309578bbe4f31f3e863a923ac5aed9bd68660d1 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 6 Aug 2023 11:41:50 +0300 Subject: [PATCH 016/185] Update: Comment blocks --- src/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index 230fcbf..a0c1abd 100644 --- a/src/index.js +++ b/src/index.js @@ -1,5 +1,5 @@ /** - * Lazy loads assets for elements. + * Lazy load assets. * * @param {string} [selector="[lazy]"] - The CSS selector for lazy loadable elements. * @param {Object} [options={}] - Additional options for configuring the lazy loading behavior. @@ -12,8 +12,8 @@ const lazyLoad = (selector = '[lazy]', options = {}) => { * * @param {string} [tag=selector] - The CSS selector for lazy loadable elements. * @param {string} [toggleClass="-loaded"] - The class name to toggle on elements after loading. - * @param {Function} [onLoaded=(element)=>{}] - Callback function to execute when an element is successfully loaded. - * @param {Function} [onError=(element, error)=>{}] - Callback function to execute when an error occurs during loading. + * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded. + * @param {Function} [onError] - Callback function to execute when an error occurs during loading. * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. */ const defaultOptions = { From eed043a2066b10a2669f82dc7c35331417fc3c60 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 7 Aug 2023 23:51:55 +0300 Subject: [PATCH 017/185] Fix: target entry --- src/index.js | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/index.js b/src/index.js index a0c1abd..aa7f3fd 100644 --- a/src/index.js +++ b/src/index.js @@ -122,14 +122,15 @@ const lazyLoad = (selector = '[lazy]', options = {}) => { const handleIntersection = (entries, observer) => { entries.forEach((entry) => { if (!entry.isIntersecting) return; + const { target } = entry; try { - loadAsset(entry.target); - options.onLoaded(entry); + loadAsset(target); + options.onLoaded(target); } catch (error) { - options.onError(entry, error); + options.onError(target, error); } finally { - observer.unobserve(entry.target); + observer.unobserve(target); // bunun tam testini yapmak lazim } }); }; From fb6ae4b27816f324bc8379eff8d8138b3c297e69 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 7 Aug 2023 23:52:17 +0300 Subject: [PATCH 018/185] Feature: Split to module --- src/assetLoader.js | 75 ++++++++++++++++++++++++++++++++ src/index.js | 106 +++------------------------------------------ src/options.js | 26 +++++++++++ test/index.html | 12 +---- test/index.js | 8 ++++ 5 files changed, 116 insertions(+), 111 deletions(-) create mode 100644 src/assetLoader.js create mode 100644 src/options.js create mode 100644 test/index.js diff --git a/src/assetLoader.js b/src/assetLoader.js new file mode 100644 index 0000000..887d33c --- /dev/null +++ b/src/assetLoader.js @@ -0,0 +1,75 @@ +/** + * Loads the asset for the given image element. + * + * @private + * + * @param {HTMLImageElement} img - The image element to load the asset for. + * @param {string} assetAttr - The asset URL attribute value. + * @param {string} assetAlt - The asset alt attribute value. + */ +const loadImage = (img, assetAttr, assetAlt) => { + img.src = assetAttr; + img.alt = assetAlt; +}; + +const loadBackground = (element, assetAttr) => { + element.style.background = `url(${assetAttr})`; +}; + +/** + * Loads the asset for the given picture element. + * + * @private + * + * @param {HTMLPictureElement} element - The picture element to load the asset for. + * @param {string} assetAttr - The asset URL attribute value. + * @param {string} assetAlt - The asset alt attribute value. + */ +const loadPicture = (element, assetAttr, assetAlt) => { + let img = element.querySelector('img'); + if (!img) { + img = document.createElement('img'); + element.append(img); + } + loadImage(img, assetAttr, assetAlt); +}; + +/** + * Loads the asset for the given video element. + * + * @private + * + * @param {HTMLVideoElement} element - The video element to load the asset for. + * @param {string} assetAttr - The asset URL attribute value. + */ +const loadVideo = (element, assetAttr) => { + element.src = assetAttr; +}; + +/** + * Loads the asset for the given element based on its type (img, picture, video). + * + * @private + * + * @param {HTMLElement} element - The element to load the asset for. + */ +const loadAsset = (element) => { + const elementType = element.tagName.toLowerCase(); + + const isImage = elementType === 'img'; + const isPicture = elementType === 'picture'; + const isVideo = elementType === 'video'; + + const assetAttr = element.getAttribute(`lazy-src`); + const assetAlt = element.getAttribute(`lazy-alt`) || ''; + const backgroundAttr = element.getAttribute(`lazy-background`); + + if (backgroundAttr) return loadBackground(element, backgroundAttr); + if (isImage) return loadImage(element, assetAttr, assetAlt); + if (isPicture) return loadPicture(element, assetAttr, assetAlt); + if (isVideo) return loadVideo(element, assetAttr); + + element.src = assetAttr; +}; + +export default loadAsset; diff --git a/src/index.js b/src/index.js index aa7f3fd..d58442f 100644 --- a/src/index.js +++ b/src/index.js @@ -1,35 +1,13 @@ +import defaultOptions from './options.js'; +import loadAsset from './assetLoader.js'; + /** * Lazy load assets. * * @param {string} [selector="[lazy]"] - The CSS selector for lazy loadable elements. * @param {Object} [options={}] - Additional options for configuring the lazy loading behavior. */ -const lazyLoad = (selector = '[lazy]', options = {}) => { - /** - * Default options for lazy loading behavior. - * - * @type {Object} - * - * @param {string} [tag=selector] - The CSS selector for lazy loadable elements. - * @param {string} [toggleClass="-loaded"] - The class name to toggle on elements after loading. - * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded. - * @param {Function} [onError] - Callback function to execute when an error occurs during loading. - * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. - */ - const defaultOptions = { - tag: selector, - toggleClass: '-loaded', - onLoaded: () => {}, - onError: (element, error) => { - console.error('🚀 Error on ~ element, error:', element, error); - }, - observer: { - root: null, - threshold: 1, - rootMargin: '300px 0px', - }, - }; - +const lazyLoad = (options = {}) => { /** * Options object for configuring the lazy loading behavior. * @@ -37,80 +15,6 @@ const lazyLoad = (selector = '[lazy]', options = {}) => { */ options = { ...defaultOptions, ...options }; - /** - * Loads the asset for the given image element. - * - * @private - * - * @param {HTMLImageElement} img - The image element to load the asset for. - * @param {string} assetAttr - The asset URL attribute value. - * @param {string} assetAlt - The asset alt attribute value. - */ - const loadImage = (img, assetAttr, assetAlt) => { - img.src = assetAttr; - img.alt = assetAlt; - }; - - const loadBackground = (element, assetAttr) => { - element.style.background = `url(${assetAttr})`; - }; - - /** - * Loads the asset for the given picture element. - * - * @private - * - * @param {HTMLPictureElement} element - The picture element to load the asset for. - * @param {string} assetAttr - The asset URL attribute value. - * @param {string} assetAlt - The asset alt attribute value. - */ - const loadPicture = (element, assetAttr, assetAlt) => { - let img = element.querySelector('img'); - if (!img) { - img = document.createElement('img'); - element.append(img); - } - loadImage(img, assetAttr, assetAlt); - }; - - /** - * Loads the asset for the given video element. - * - * @private - * - * @param {HTMLVideoElement} element - The video element to load the asset for. - * @param {string} assetAttr - The asset URL attribute value. - */ - const loadVideo = (element, assetAttr) => { - element.src = assetAttr; - }; - - /** - * Loads the asset for the given element based on its type (img, picture, video). - * - * @private - * - * @param {HTMLElement} element - The element to load the asset for. - */ - const loadAsset = (element) => { - const elementType = element.tagName.toLowerCase(); - - const isImage = elementType === 'img'; - const isPicture = elementType === 'picture'; - const isVideo = elementType === 'video'; - - const assetAttr = element.getAttribute(`lazy-src`); - const assetAlt = element.getAttribute(`lazy-alt`) || ''; - const backgroundAttr = element.getAttribute(`lazy-background`); - - if (backgroundAttr) return loadBackground(element, backgroundAttr); - if (isImage) return loadImage(element, assetAttr, assetAlt); - if (isPicture) return loadPicture(element, assetAttr, assetAlt); - if (isVideo) return loadVideo(element, assetAttr); - - element.src = assetAttr; - }; - /** * Handles the intersection of lazy load elements. * @@ -154,3 +58,5 @@ const lazyLoad = (selector = '[lazy]', options = {}) => { lazyLoadItems.forEach((item) => observer.observe(item)); }; + +export default lazyLoad; diff --git a/src/options.js b/src/options.js new file mode 100644 index 0000000..de9584f --- /dev/null +++ b/src/options.js @@ -0,0 +1,26 @@ +/** + * Default options for lazy loading behavior. + * + * @type {Object} + * + * @param {string} [tag=selector] - The CSS selector for lazy loadable elements. + * @param {string} [toggleClass="-loaded"] - The class name to toggle on elements after loading. + * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded. + * @param {Function} [onError] - Callback function to execute when an error occurs during loading. + * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. + */ +const defaultOptions = { + tag: '[lazy]', + toggleClass: '-loaded', + onLoaded: () => {}, + onError: (element, error) => { + console.error('🚀 Error on ~ element, error:', element, error); + }, + observer: { + root: null, + threshold: 1, + rootMargin: '300px 0px', + }, +}; + +export default defaultOptions; diff --git a/test/index.html b/test/index.html index 3bd1ae5..795b0c2 100644 --- a/test/index.html +++ b/test/index.html @@ -39,17 +39,7 @@ Random Image Random Image - - - - - + \ No newline at end of file diff --git a/test/index.js b/test/index.js new file mode 100644 index 0000000..9056932 --- /dev/null +++ b/test/index.js @@ -0,0 +1,8 @@ +import lazyLoad from '/src/index.js'; + +lazyLoad({ + tag: '[lazy]', + onLoaded: (element) => { + console.log(element); + }, +}); From 8dbbdb66cbedcf5f85f028eacd82be7d28eeb18f Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 10 Aug 2023 23:06:18 +0300 Subject: [PATCH 019/185] Update: Split selector and tag options --- src/options.js | 3 ++- test/index.js | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/options.js b/src/options.js index de9584f..4c3dc68 100644 --- a/src/options.js +++ b/src/options.js @@ -10,7 +10,8 @@ * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. */ const defaultOptions = { - tag: '[lazy]', + tag: 'lazy', + selector: '[lazy]', toggleClass: '-loaded', onLoaded: () => {}, onError: (element, error) => { diff --git a/test/index.js b/test/index.js index 9056932..8b1aa27 100644 --- a/test/index.js +++ b/test/index.js @@ -1,7 +1,6 @@ import lazyLoad from '/src/index.js'; lazyLoad({ - tag: '[lazy]', onLoaded: (element) => { console.log(element); }, From dbd2c94a324995bc754619bc21a01282d0c0452f Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 10 Aug 2023 23:06:39 +0300 Subject: [PATCH 020/185] Update: Observer default options --- src/options.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/options.js b/src/options.js index 4c3dc68..163537c 100644 --- a/src/options.js +++ b/src/options.js @@ -20,7 +20,7 @@ const defaultOptions = { observer: { root: null, threshold: 1, - rootMargin: '300px 0px', + rootMargin: '100% 0px', // Burayı daha detalı araştırmam gerek }, }; From 670dd456f79461619b251a36cfa19e341dc0f480 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 10 Aug 2023 23:07:19 +0300 Subject: [PATCH 021/185] Add: options parameter to dynamic selector and tag options --- src/assetLoader.js | 9 +++++---- src/index.js | 2 +- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index 887d33c..ff36514 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -53,16 +53,17 @@ const loadVideo = (element, assetAttr) => { * * @param {HTMLElement} element - The element to load the asset for. */ -const loadAsset = (element) => { +const loadAsset = (element, options) => { + const { tag } = options; const elementType = element.tagName.toLowerCase(); const isImage = elementType === 'img'; const isPicture = elementType === 'picture'; const isVideo = elementType === 'video'; - const assetAttr = element.getAttribute(`lazy-src`); - const assetAlt = element.getAttribute(`lazy-alt`) || ''; - const backgroundAttr = element.getAttribute(`lazy-background`); + const assetAttr = element.getAttribute(`${tag}-src`); + const assetAlt = element.getAttribute(`${tag}-alt`) || ''; + const backgroundAttr = element.getAttribute(`${tag}-background`); if (backgroundAttr) return loadBackground(element, backgroundAttr); if (isImage) return loadImage(element, assetAttr, assetAlt); diff --git a/src/index.js b/src/index.js index d58442f..15b6055 100644 --- a/src/index.js +++ b/src/index.js @@ -29,7 +29,7 @@ const lazyLoad = (options = {}) => { const { target } = entry; try { - loadAsset(target); + loadAsset(target, options); options.onLoaded(target); } catch (error) { options.onError(target, error); From 2aa638b89783f73bf765630fe53452242804df54 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 10 Aug 2023 23:07:32 +0300 Subject: [PATCH 022/185] Update: Naming --- src/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index 15b6055..c795c35 100644 --- a/src/index.js +++ b/src/index.js @@ -5,15 +5,15 @@ import loadAsset from './assetLoader.js'; * Lazy load assets. * * @param {string} [selector="[lazy]"] - The CSS selector for lazy loadable elements. - * @param {Object} [options={}] - Additional options for configuring the lazy loading behavior. + * @param {Object} [settings={}] - Additional options for configuring the lazy loading behavior. */ -const lazyLoad = (options = {}) => { +const lazyLoad = (settings = {}) => { /** * Options object for configuring the lazy loading behavior. * * @type {Object} */ - options = { ...defaultOptions, ...options }; + const options = { ...defaultOptions, ...settings }; /** * Handles the intersection of lazy load elements. From fb26d2a9741ed56a6c31c3eb4434722c6ab63814 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 10 Aug 2023 23:08:50 +0300 Subject: [PATCH 023/185] Update: select paraneeter --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index c795c35..373a8a1 100644 --- a/src/index.js +++ b/src/index.js @@ -54,7 +54,7 @@ const lazyLoad = (settings = {}) => { * * @type {NodeList} */ - const lazyLoadItems = document.querySelectorAll(options.tag); + const lazyLoadItems = document.querySelectorAll(options.selector); lazyLoadItems.forEach((item) => observer.observe(item)); }; From 087e15944b348633d919e402519b131af69113c0 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 10 Aug 2023 23:48:41 +0300 Subject: [PATCH 024/185] Add: Parcel to project --- package.json | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index 3e31672..a2df7d9 100644 --- a/package.json +++ b/package.json @@ -4,7 +4,11 @@ "homepage": "https://github.com/drementer/lazy-load.js", "description": "Loads visual content when it approaches the visible area of ​​the screen to increase page loading speed.", "source": "src/index.js", - "main": "src/index.js", + "module": "dist/lazy-load.js", + "scripts": { + "watch": "parcel watch", + "build": "parcel build --no-source-maps --no-cache" + }, "keywords": [ "js", "lazy", @@ -19,5 +23,9 @@ "bugs": { "url": "https://github.com/drementer/lazy-load.js/issues" }, - "license": "MIT" + "license": "MIT", + "devDependencies": { + "@parcel/resolver-glob": "^2.9.3", + "parcel": "^2.9.3" + } } From b4ed0c8225508f3890b2294c910f3e40885eec2e Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 10 Aug 2023 23:48:52 +0300 Subject: [PATCH 025/185] Add: Production --- dist/lazy-load.js | 143 ++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 143 insertions(+) create mode 100644 dist/lazy-load.js diff --git a/dist/lazy-load.js b/dist/lazy-load.js new file mode 100644 index 0000000..56f5dbd --- /dev/null +++ b/dist/lazy-load.js @@ -0,0 +1,143 @@ +/** + * Default options for lazy loading behavior. + * + * @type {Object} + * + * @param {string} [tag=selector] - The CSS selector for lazy loadable elements. + * @param {string} [toggleClass="-loaded"] - The class name to toggle on elements after loading. + * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded. + * @param {Function} [onError] - Callback function to execute when an error occurs during loading. + * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. + */ const $db127449446b8099$var$defaultOptions = { + tag: "lazy", + selector: "[lazy]", + toggleClass: "-loaded", + onLoaded: ()=>{}, + onError: (element, error)=>{ + console.error("\uD83D\uDE80 Error on ~ element, error:", element, error); + }, + observer: { + root: null, + threshold: 1, + rootMargin: "100% 0px" + } +}; +var $db127449446b8099$export$2e2bcd8739ae039 = $db127449446b8099$var$defaultOptions; + + +/** + * Loads the asset for the given image element. + * + * @private + * + * @param {HTMLImageElement} img - The image element to load the asset for. + * @param {string} assetAttr - The asset URL attribute value. + * @param {string} assetAlt - The asset alt attribute value. + */ const $fa423858cf60d4ae$var$loadImage = (img, assetAttr, assetAlt)=>{ + img.src = assetAttr; + img.alt = assetAlt; +}; +const $fa423858cf60d4ae$var$loadBackground = (element, assetAttr)=>{ + element.style.background = `url(${assetAttr})`; +}; +/** + * Loads the asset for the given picture element. + * + * @private + * + * @param {HTMLPictureElement} element - The picture element to load the asset for. + * @param {string} assetAttr - The asset URL attribute value. + * @param {string} assetAlt - The asset alt attribute value. + */ const $fa423858cf60d4ae$var$loadPicture = (element, assetAttr, assetAlt)=>{ + let img = element.querySelector("img"); + if (!img) { + img = document.createElement("img"); + element.append(img); + } + $fa423858cf60d4ae$var$loadImage(img, assetAttr, assetAlt); +}; +/** + * Loads the asset for the given video element. + * + * @private + * + * @param {HTMLVideoElement} element - The video element to load the asset for. + * @param {string} assetAttr - The asset URL attribute value. + */ const $fa423858cf60d4ae$var$loadVideo = (element, assetAttr)=>{ + element.src = assetAttr; +}; +/** + * Loads the asset for the given element based on its type (img, picture, video). + * + * @private + * + * @param {HTMLElement} element - The element to load the asset for. + */ const $fa423858cf60d4ae$var$loadAsset = (element, options)=>{ + const { tag: tag } = options; + const elementType = element.tagName.toLowerCase(); + const isImage = elementType === "img"; + const isPicture = elementType === "picture"; + const isVideo = elementType === "video"; + const assetAttr = element.getAttribute(`${tag}-src`); + const assetAlt = element.getAttribute(`${tag}-alt`) || ""; + const backgroundAttr = element.getAttribute(`${tag}-background`); + if (backgroundAttr) return $fa423858cf60d4ae$var$loadBackground(element, backgroundAttr); + if (isImage) return $fa423858cf60d4ae$var$loadImage(element, assetAttr, assetAlt); + if (isPicture) return $fa423858cf60d4ae$var$loadPicture(element, assetAttr, assetAlt); + if (isVideo) return $fa423858cf60d4ae$var$loadVideo(element, assetAttr); + element.src = assetAttr; +}; +var $fa423858cf60d4ae$export$2e2bcd8739ae039 = $fa423858cf60d4ae$var$loadAsset; + + +/** + * Lazy load assets. + * + * @param {string} [selector="[lazy]"] - The CSS selector for lazy loadable elements. + * @param {Object} [settings={}] - Additional options for configuring the lazy loading behavior. + */ const $82cbb5a2f3a1bcd0$var$lazyLoad = (settings = {})=>{ + /** + * Options object for configuring the lazy loading behavior. + * + * @type {Object} + */ const options = { + ...(0, $db127449446b8099$export$2e2bcd8739ae039), + ...settings + }; + /** + * Handles the intersection of lazy load elements. + * + * @private + * + * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer. + * @param {IntersectionObserver} observer - The intersection observer instance. + */ const handleIntersection = (entries, observer)=>{ + entries.forEach((entry)=>{ + if (!entry.isIntersecting) return; + const { target: target } = entry; + try { + (0, $fa423858cf60d4ae$export$2e2bcd8739ae039)(target, options); + options.onLoaded(target); + } catch (error) { + options.onError(target, error); + } finally{ + observer.unobserve(target); // bunun tam testini yapmak lazim + } + }); + }; + /** + * IntersectionObserver used for lazy loading. + * + * @type {IntersectionObserver} + */ const observer = new IntersectionObserver(handleIntersection, options.observer); + /** + * NodeList of lazy loadable elements. + * + * @type {NodeList} + */ const lazyLoadItems = document.querySelectorAll(options.selector); + lazyLoadItems.forEach((item)=>observer.observe(item)); +}; +var $82cbb5a2f3a1bcd0$export$2e2bcd8739ae039 = $82cbb5a2f3a1bcd0$var$lazyLoad; + + +export {$82cbb5a2f3a1bcd0$export$2e2bcd8739ae039 as default}; From d88b045271b14d2dfdd2f2babe29f69314d6edfd Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 10 Aug 2023 23:49:12 +0300 Subject: [PATCH 026/185] Update: Liblary path --- test/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/index.js b/test/index.js index 8b1aa27..88e9c2c 100644 --- a/test/index.js +++ b/test/index.js @@ -1,4 +1,4 @@ -import lazyLoad from '/src/index.js'; +import lazyLoad from '/dist/lazy-load.js'; lazyLoad({ onLoaded: (element) => { From a0a6f8f573dafd1fc4866dd5518e536ca48ffa55 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 10 Aug 2023 23:49:25 +0300 Subject: [PATCH 027/185] Add: ignored folders --- .gitignore | 2 ++ 1 file changed, 2 insertions(+) diff --git a/.gitignore b/.gitignore index 3d3c9a9..e91ed5b 100644 --- a/.gitignore +++ b/.gitignore @@ -3,4 +3,6 @@ [Dd]esktop.ini # Project +node_modules/ +.parcel-cache/ package-lock.json \ No newline at end of file From 99cb88bb4e404ae41a5f7493eb73e5f1adefa776 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 10 Aug 2023 23:55:39 +0300 Subject: [PATCH 028/185] Add: Global comment via jsdoc --- dist/lazy-load.js | 8 ++++++++ src/index.js | 10 ++++++++++ 2 files changed, 18 insertions(+) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index 56f5dbd..41b0fdd 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -1,4 +1,12 @@ /** + * Lazy-load.js + * + * @author drementer + * @module lazyLoad + * @version 1.0.6 + * @license MIT + * @see {@link https://github.com/drementer/lazy-load.js} + */ /** * Default options for lazy loading behavior. * * @type {Object} diff --git a/src/index.js b/src/index.js index 373a8a1..66a1be1 100644 --- a/src/index.js +++ b/src/index.js @@ -1,3 +1,13 @@ +/** + * Lazy-load.js + * + * @author drementer + * @module lazyLoad + * @version 1.0.6 + * @license MIT + * @see {@link https://github.com/drementer/lazy-load.js} + */ + import defaultOptions from './options.js'; import loadAsset from './assetLoader.js'; From 7b76f03ec534fb402e4803e2a51d51b924d9b7ff Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 13 Aug 2023 23:58:41 +0300 Subject: [PATCH 029/185] Remove: return keyword for never need it --- src/assetLoader.js | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index ff36514..831b708 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -65,10 +65,10 @@ const loadAsset = (element, options) => { const assetAlt = element.getAttribute(`${tag}-alt`) || ''; const backgroundAttr = element.getAttribute(`${tag}-background`); - if (backgroundAttr) return loadBackground(element, backgroundAttr); - if (isImage) return loadImage(element, assetAttr, assetAlt); - if (isPicture) return loadPicture(element, assetAttr, assetAlt); - if (isVideo) return loadVideo(element, assetAttr); + if (backgroundAttr) loadBackground(element, backgroundAttr); + if (isImage) loadImage(element, assetAttr, assetAlt); + if (isPicture) loadPicture(element, assetAttr, assetAlt); + if (isVideo) loadVideo(element, assetAttr); element.src = assetAttr; }; From e64136e5d21d78ee72e3bafb93a76016794be799 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 23 Aug 2023 22:48:23 +0300 Subject: [PATCH 030/185] Add: Dynamic load function selections --- dist/lazy-load.js | 46 ++++++++++++++++++++++--------------------- dist/lazy-load.js.map | 1 + src/assetLoader.js | 20 ++++++++++--------- 3 files changed, 36 insertions(+), 31 deletions(-) create mode 100644 dist/lazy-load.js.map diff --git a/dist/lazy-load.js b/dist/lazy-load.js index 41b0fdd..4b551c8 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -16,7 +16,7 @@ * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded. * @param {Function} [onError] - Callback function to execute when an error occurs during loading. * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. - */ const $db127449446b8099$var$defaultOptions = { + */ const $50e97065b94a2e88$var$defaultOptions = { tag: "lazy", selector: "[lazy]", toggleClass: "-loaded", @@ -30,7 +30,7 @@ rootMargin: "100% 0px" } }; -var $db127449446b8099$export$2e2bcd8739ae039 = $db127449446b8099$var$defaultOptions; +var $50e97065b94a2e88$export$2e2bcd8739ae039 = $50e97065b94a2e88$var$defaultOptions; /** @@ -41,11 +41,11 @@ var $db127449446b8099$export$2e2bcd8739ae039 = $db127449446b8099$var$defaultOpti * @param {HTMLImageElement} img - The image element to load the asset for. * @param {string} assetAttr - The asset URL attribute value. * @param {string} assetAlt - The asset alt attribute value. - */ const $fa423858cf60d4ae$var$loadImage = (img, assetAttr, assetAlt)=>{ + */ const $f85e789b098d4f3c$var$loadImage = (img, assetAttr, assetAlt)=>{ img.src = assetAttr; img.alt = assetAlt; }; -const $fa423858cf60d4ae$var$loadBackground = (element, assetAttr)=>{ +const $f85e789b098d4f3c$var$loadBackground = (element, assetAttr)=>{ element.style.background = `url(${assetAttr})`; }; /** @@ -56,13 +56,13 @@ const $fa423858cf60d4ae$var$loadBackground = (element, assetAttr)=>{ * @param {HTMLPictureElement} element - The picture element to load the asset for. * @param {string} assetAttr - The asset URL attribute value. * @param {string} assetAlt - The asset alt attribute value. - */ const $fa423858cf60d4ae$var$loadPicture = (element, assetAttr, assetAlt)=>{ + */ const $f85e789b098d4f3c$var$loadPicture = (element, assetAttr, assetAlt)=>{ let img = element.querySelector("img"); if (!img) { img = document.createElement("img"); element.append(img); } - $fa423858cf60d4ae$var$loadImage(img, assetAttr, assetAlt); + $f85e789b098d4f3c$var$loadImage(img, assetAttr, assetAlt); }; /** * Loads the asset for the given video element. @@ -71,7 +71,7 @@ const $fa423858cf60d4ae$var$loadBackground = (element, assetAttr)=>{ * * @param {HTMLVideoElement} element - The video element to load the asset for. * @param {string} assetAttr - The asset URL attribute value. - */ const $fa423858cf60d4ae$var$loadVideo = (element, assetAttr)=>{ + */ const $f85e789b098d4f3c$var$loadVideo = (element, assetAttr)=>{ element.src = assetAttr; }; /** @@ -80,22 +80,23 @@ const $fa423858cf60d4ae$var$loadBackground = (element, assetAttr)=>{ * @private * * @param {HTMLElement} element - The element to load the asset for. - */ const $fa423858cf60d4ae$var$loadAsset = (element, options)=>{ + */ const $f85e789b098d4f3c$var$loadAsset = (element, options)=>{ const { tag: tag } = options; + const loadFunctions = { + img: $f85e789b098d4f3c$var$loadImage, + picture: $f85e789b098d4f3c$var$loadPicture, + video: $f85e789b098d4f3c$var$loadVideo + }; const elementType = element.tagName.toLowerCase(); - const isImage = elementType === "img"; - const isPicture = elementType === "picture"; - const isVideo = elementType === "video"; + const loadFunction = loadFunctions[elementType]; const assetAttr = element.getAttribute(`${tag}-src`); const assetAlt = element.getAttribute(`${tag}-alt`) || ""; const backgroundAttr = element.getAttribute(`${tag}-background`); - if (backgroundAttr) return $fa423858cf60d4ae$var$loadBackground(element, backgroundAttr); - if (isImage) return $fa423858cf60d4ae$var$loadImage(element, assetAttr, assetAlt); - if (isPicture) return $fa423858cf60d4ae$var$loadPicture(element, assetAttr, assetAlt); - if (isVideo) return $fa423858cf60d4ae$var$loadVideo(element, assetAttr); - element.src = assetAttr; + if (backgroundAttr) return $f85e789b098d4f3c$var$loadBackground(element, backgroundAttr); + if (loadFunction) return loadFunction(element, assetAttr, assetAlt); + throw new Error(`Invalid element type: ${elementType}`); }; -var $fa423858cf60d4ae$export$2e2bcd8739ae039 = $fa423858cf60d4ae$var$loadAsset; +var $f85e789b098d4f3c$export$2e2bcd8739ae039 = $f85e789b098d4f3c$var$loadAsset; /** @@ -103,13 +104,13 @@ var $fa423858cf60d4ae$export$2e2bcd8739ae039 = $fa423858cf60d4ae$var$loadAsset; * * @param {string} [selector="[lazy]"] - The CSS selector for lazy loadable elements. * @param {Object} [settings={}] - Additional options for configuring the lazy loading behavior. - */ const $82cbb5a2f3a1bcd0$var$lazyLoad = (settings = {})=>{ + */ const $cf838c15c8b009ba$var$lazyLoad = (settings = {})=>{ /** * Options object for configuring the lazy loading behavior. * * @type {Object} */ const options = { - ...(0, $db127449446b8099$export$2e2bcd8739ae039), + ...(0, $50e97065b94a2e88$export$2e2bcd8739ae039), ...settings }; /** @@ -124,7 +125,7 @@ var $fa423858cf60d4ae$export$2e2bcd8739ae039 = $fa423858cf60d4ae$var$loadAsset; if (!entry.isIntersecting) return; const { target: target } = entry; try { - (0, $fa423858cf60d4ae$export$2e2bcd8739ae039)(target, options); + (0, $f85e789b098d4f3c$export$2e2bcd8739ae039)(target, options); options.onLoaded(target); } catch (error) { options.onError(target, error); @@ -145,7 +146,8 @@ var $fa423858cf60d4ae$export$2e2bcd8739ae039 = $fa423858cf60d4ae$var$loadAsset; */ const lazyLoadItems = document.querySelectorAll(options.selector); lazyLoadItems.forEach((item)=>observer.observe(item)); }; -var $82cbb5a2f3a1bcd0$export$2e2bcd8739ae039 = $82cbb5a2f3a1bcd0$var$lazyLoad; +var $cf838c15c8b009ba$export$2e2bcd8739ae039 = $cf838c15c8b009ba$var$lazyLoad; -export {$82cbb5a2f3a1bcd0$export$2e2bcd8739ae039 as default}; +export {$cf838c15c8b009ba$export$2e2bcd8739ae039 as default}; +//# sourceMappingURL=lazy-load.js.map diff --git a/dist/lazy-load.js.map b/dist/lazy-load.js.map new file mode 100644 index 0000000..2e19f0a --- /dev/null +++ b/dist/lazy-load.js.map @@ -0,0 +1 @@ +{"mappings":"AAAA;;;;;;;;ACAA;;;;;;;;;;CAUC,GACD,MAAM,uCAAiB;IACrB,KAAK;IACL,UAAU;IACV,aAAa;IACb,UAAU,KAAO;IACjB,SAAS,CAAC,SAAS;QACjB,QAAQ,MAAM,2CAAiC,SAAS;IAC1D;IACA,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;IAEA,2CAAe;;CDlBd;AERD;;;;;;;;CAQC,GACD,MAAM,kCAAY,CAAC,KAAK,WAAW;IACjC,IAAI,MAAM;IACV,IAAI,MAAM;AACZ;AAEA,MAAM,uCAAiB,CAAC,SAAS;IAC/B,QAAQ,MAAM,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AAChD;AAEA;;;;;;;;CAQC,GACD,MAAM,oCAAc,CAAC,SAAS,WAAW;IACvC,IAAI,MAAM,QAAQ,cAAc;IAChC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,OAAO;IACjB;IACA,gCAAU,KAAK,WAAW;AAC5B;AAEA;;;;;;;CAOC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM;AAChB;AAEA;;;;;;CAMC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,MAAM,OAAE,GAAG,EAAE,GAAG;IAEhB,MAAM,gBAAgB;QACpB,KAAK;QACL,SAAS;QACT,OAAO;IACT;IAEA,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,eAAe,aAAa,CAAC,YAAY;IAE/C,MAAM,YAAY,QAAQ,aAAa,CAAC,EAAE,IAAI,IAAI,CAAC;IACnD,MAAM,WAAW,QAAQ,aAAa,CAAC,EAAE,IAAI,IAAI,CAAC,KAAK;IACvD,MAAM,iBAAiB,QAAQ,aAAa,CAAC,EAAE,IAAI,WAAW,CAAC;IAG/D,IAAI,gBAAgB,OAAO,qCAAe,SAAS;IACnD,IAAI,cAAc,OAAO,aAAa,SAAS,WAAW;IAE1D,MAAM,IAAI,MAAM,CAAC,sBAAsB,EAAE,YAAY,CAAC;AACxD;IAEA,2CAAe;;;AFjEf;;;;;CAKC,GACD,MAAM,iCAAW,CAAC,WAAW,CAAC,CAAC;IAC7B;;;;GAIC,GACD,MAAM,UAAU;QAAE,GAAG,CAAA,GAAA,wCAAa,CAAC;QAAE,GAAG,QAAQ;IAAC;IAEjD;;;;;;;GAOC,GACD,MAAM,qBAAqB,CAAC,SAAS;QACnC,QAAQ,QAAQ,CAAC;YACf,IAAI,CAAC,MAAM,gBAAgB;YAC3B,MAAM,UAAE,MAAM,EAAE,GAAG;YAEnB,IAAI;gBACF,CAAA,GAAA,wCAAQ,EAAE,QAAQ;gBAClB,QAAQ,SAAS;YACnB,EAAE,OAAO,OAAO;gBACd,QAAQ,QAAQ,QAAQ;YAC1B,SAAU;gBACR,SAAS,UAAU,SAAS,iCAAiC;YAC/D;QACF;IACF;IAEA;;;;GAIC,GACD,MAAM,WAAW,IAAI,qBACnB,oBACA,QAAQ;IAGV;;;;GAIC,GACD,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ;IAExD,cAAc,QAAQ,CAAC,OAAS,SAAS,QAAQ;AACnD;IAEA,2CAAe","sources":["src/index.js","src/options.js","src/assetLoader.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.6\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './options.js';\nimport loadAsset from './assetLoader.js';\n\n/**\n * Lazy load assets.\n *\n * @param {string} [selector=\"[lazy]\"] - The CSS selector for lazy loadable elements.\n * @param {Object} [settings={}] - Additional options for configuring the lazy loading behavior.\n */\nconst lazyLoad = (settings = {}) => {\n /**\n * Options object for configuring the lazy loading behavior.\n *\n * @type {Object}\n */\n const options = { ...defaultOptions, ...settings };\n\n /**\n * Handles the intersection of lazy load elements.\n *\n * @private\n *\n * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer.\n * @param {IntersectionObserver} observer - The intersection observer instance.\n */\n const handleIntersection = (entries, observer) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n const { target } = entry;\n\n try {\n loadAsset(target, options);\n options.onLoaded(target);\n } catch (error) {\n options.onError(target, error);\n } finally {\n observer.unobserve(target); // bunun tam testini yapmak lazim\n }\n });\n };\n\n /**\n * IntersectionObserver used for lazy loading.\n *\n * @type {IntersectionObserver}\n */\n const observer = new IntersectionObserver(\n handleIntersection,\n options.observer\n );\n\n /**\n * NodeList of lazy loadable elements.\n *\n * @type {NodeList}\n */\n const lazyLoadItems = document.querySelectorAll(options.selector);\n\n lazyLoadItems.forEach((item) => observer.observe(item));\n};\n\nexport default lazyLoad;\n","/**\n * Default options for lazy loading behavior.\n *\n * @type {Object}\n *\n * @param {string} [tag=selector] - The CSS selector for lazy loadable elements.\n * @param {string} [toggleClass=\"-loaded\"] - The class name to toggle on elements after loading.\n * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded.\n * @param {Function} [onError] - Callback function to execute when an error occurs during loading.\n * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading.\n */\nconst defaultOptions = {\n tag: 'lazy',\n selector: '[lazy]',\n toggleClass: '-loaded',\n onLoaded: () => {},\n onError: (element, error) => {\n console.error('🚀 Error on ~ element, error:', element, error);\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px', // Burayı daha detalı araştırmam gerek\n },\n};\n\nexport default defaultOptions;\n","/**\n * Loads the asset for the given image element.\n *\n * @private\n *\n * @param {HTMLImageElement} img - The image element to load the asset for.\n * @param {string} assetAttr - The asset URL attribute value.\n * @param {string} assetAlt - The asset alt attribute value.\n */\nconst loadImage = (img, assetAttr, assetAlt) => {\n img.src = assetAttr;\n img.alt = assetAlt;\n};\n\nconst loadBackground = (element, assetAttr) => {\n element.style.background = `url(${assetAttr})`;\n};\n\n/**\n * Loads the asset for the given picture element.\n *\n * @private\n *\n * @param {HTMLPictureElement} element - The picture element to load the asset for.\n * @param {string} assetAttr - The asset URL attribute value.\n * @param {string} assetAlt - The asset alt attribute value.\n */\nconst loadPicture = (element, assetAttr, assetAlt) => {\n let img = element.querySelector('img');\n if (!img) {\n img = document.createElement('img');\n element.append(img);\n }\n loadImage(img, assetAttr, assetAlt);\n};\n\n/**\n * Loads the asset for the given video element.\n *\n * @private\n *\n * @param {HTMLVideoElement} element - The video element to load the asset for.\n * @param {string} assetAttr - The asset URL attribute value.\n */\nconst loadVideo = (element, assetAttr) => {\n element.src = assetAttr;\n};\n\n/**\n * Loads the asset for the given element based on its type (img, picture, video).\n *\n * @private\n *\n * @param {HTMLElement} element - The element to load the asset for.\n */\nconst loadAsset = (element, options) => {\n const { tag } = options;\n\n const loadFunctions = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n };\n\n const elementType = element.tagName.toLowerCase();\n const loadFunction = loadFunctions[elementType];\n\n const assetAttr = element.getAttribute(`${tag}-src`);\n const assetAlt = element.getAttribute(`${tag}-alt`) || '';\n const backgroundAttr = element.getAttribute(`${tag}-background`);\n\n\n if (backgroundAttr) return loadBackground(element, backgroundAttr);\n if (loadFunction) return loadFunction(element, assetAttr, assetAlt);\n\n throw new Error(`Invalid element type: ${elementType}`);\n};\n\nexport default loadAsset;\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file diff --git a/src/assetLoader.js b/src/assetLoader.js index 831b708..04e215b 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -55,22 +55,24 @@ const loadVideo = (element, assetAttr) => { */ const loadAsset = (element, options) => { const { tag } = options; - const elementType = element.tagName.toLowerCase(); - const isImage = elementType === 'img'; - const isPicture = elementType === 'picture'; - const isVideo = elementType === 'video'; + const loadFunctions = { + img: loadImage, + picture: loadPicture, + video: loadVideo, + }; + + const elementType = element.tagName.toLowerCase(); + const loadFunction = loadFunctions[elementType]; const assetAttr = element.getAttribute(`${tag}-src`); const assetAlt = element.getAttribute(`${tag}-alt`) || ''; const backgroundAttr = element.getAttribute(`${tag}-background`); - if (backgroundAttr) loadBackground(element, backgroundAttr); - if (isImage) loadImage(element, assetAttr, assetAlt); - if (isPicture) loadPicture(element, assetAttr, assetAlt); - if (isVideo) loadVideo(element, assetAttr); + if (backgroundAttr) return loadBackground(element, backgroundAttr); + if (loadFunction) return loadFunction(element, assetAttr, assetAlt); - element.src = assetAttr; + throw new Error(`Invalid element type: ${elementType}`); }; export default loadAsset; From f614d0e023b718c1b8df8437ee090063c5327d8e Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 23 Aug 2023 23:08:49 +0300 Subject: [PATCH 031/185] Update: Rename params --- dist/lazy-load.js | 30 +++++++++++++++--------------- dist/lazy-load.js.map | 2 +- src/assetLoader.js | 32 +++++++++++++++++--------------- 3 files changed, 33 insertions(+), 31 deletions(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index 4b551c8..0cad5b3 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -38,15 +38,15 @@ var $50e97065b94a2e88$export$2e2bcd8739ae039 = $50e97065b94a2e88$var$defaultOpti * * @private * - * @param {HTMLImageElement} img - The image element to load the asset for. - * @param {string} assetAttr - The asset URL attribute value. - * @param {string} assetAlt - The asset alt attribute value. - */ const $f85e789b098d4f3c$var$loadImage = (img, assetAttr, assetAlt)=>{ - img.src = assetAttr; - img.alt = assetAlt; + * @param {HTMLImageElement} element - The image element to load the asset for. + * @param {string} src - The asset path attribute value. + * @param {string} alt - The asset alt attribute value. + */ const $f85e789b098d4f3c$var$loadImage = (element, src, alt)=>{ + element.src = src; + element.alt = alt; }; -const $f85e789b098d4f3c$var$loadBackground = (element, assetAttr)=>{ - element.style.background = `url(${assetAttr})`; +const $f85e789b098d4f3c$var$loadBackground = (element, src)=>{ + element.style.background = `url(${src})`; }; /** * Loads the asset for the given picture element. @@ -54,15 +54,15 @@ const $f85e789b098d4f3c$var$loadBackground = (element, assetAttr)=>{ * @private * * @param {HTMLPictureElement} element - The picture element to load the asset for. - * @param {string} assetAttr - The asset URL attribute value. - * @param {string} assetAlt - The asset alt attribute value. - */ const $f85e789b098d4f3c$var$loadPicture = (element, assetAttr, assetAlt)=>{ + * @param {string} src - The asset URL attribute value. + * @param {string} alt - The asset alt attribute value. + */ const $f85e789b098d4f3c$var$loadPicture = (element, src, alt)=>{ let img = element.querySelector("img"); if (!img) { img = document.createElement("img"); element.append(img); } - $f85e789b098d4f3c$var$loadImage(img, assetAttr, assetAlt); + $f85e789b098d4f3c$var$loadImage(img, src, alt); }; /** * Loads the asset for the given video element. @@ -70,9 +70,9 @@ const $f85e789b098d4f3c$var$loadBackground = (element, assetAttr)=>{ * @private * * @param {HTMLVideoElement} element - The video element to load the asset for. - * @param {string} assetAttr - The asset URL attribute value. - */ const $f85e789b098d4f3c$var$loadVideo = (element, assetAttr)=>{ - element.src = assetAttr; + * @param {string} src - The asset URL attribute value. + */ const $f85e789b098d4f3c$var$loadVideo = (element, src)=>{ + element.src = src; }; /** * Loads the asset for the given element based on its type (img, picture, video). diff --git a/dist/lazy-load.js.map b/dist/lazy-load.js.map index 2e19f0a..3920cc1 100644 --- a/dist/lazy-load.js.map +++ b/dist/lazy-load.js.map @@ -1 +1 @@ -{"mappings":"AAAA;;;;;;;;ACAA;;;;;;;;;;CAUC,GACD,MAAM,uCAAiB;IACrB,KAAK;IACL,UAAU;IACV,aAAa;IACb,UAAU,KAAO;IACjB,SAAS,CAAC,SAAS;QACjB,QAAQ,MAAM,2CAAiC,SAAS;IAC1D;IACA,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;IAEA,2CAAe;;CDlBd;AERD;;;;;;;;CAQC,GACD,MAAM,kCAAY,CAAC,KAAK,WAAW;IACjC,IAAI,MAAM;IACV,IAAI,MAAM;AACZ;AAEA,MAAM,uCAAiB,CAAC,SAAS;IAC/B,QAAQ,MAAM,aAAa,CAAC,IAAI,EAAE,UAAU,CAAC,CAAC;AAChD;AAEA;;;;;;;;CAQC,GACD,MAAM,oCAAc,CAAC,SAAS,WAAW;IACvC,IAAI,MAAM,QAAQ,cAAc;IAChC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,OAAO;IACjB;IACA,gCAAU,KAAK,WAAW;AAC5B;AAEA;;;;;;;CAOC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM;AAChB;AAEA;;;;;;CAMC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,MAAM,OAAE,GAAG,EAAE,GAAG;IAEhB,MAAM,gBAAgB;QACpB,KAAK;QACL,SAAS;QACT,OAAO;IACT;IAEA,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,eAAe,aAAa,CAAC,YAAY;IAE/C,MAAM,YAAY,QAAQ,aAAa,CAAC,EAAE,IAAI,IAAI,CAAC;IACnD,MAAM,WAAW,QAAQ,aAAa,CAAC,EAAE,IAAI,IAAI,CAAC,KAAK;IACvD,MAAM,iBAAiB,QAAQ,aAAa,CAAC,EAAE,IAAI,WAAW,CAAC;IAG/D,IAAI,gBAAgB,OAAO,qCAAe,SAAS;IACnD,IAAI,cAAc,OAAO,aAAa,SAAS,WAAW;IAE1D,MAAM,IAAI,MAAM,CAAC,sBAAsB,EAAE,YAAY,CAAC;AACxD;IAEA,2CAAe;;;AFjEf;;;;;CAKC,GACD,MAAM,iCAAW,CAAC,WAAW,CAAC,CAAC;IAC7B;;;;GAIC,GACD,MAAM,UAAU;QAAE,GAAG,CAAA,GAAA,wCAAa,CAAC;QAAE,GAAG,QAAQ;IAAC;IAEjD;;;;;;;GAOC,GACD,MAAM,qBAAqB,CAAC,SAAS;QACnC,QAAQ,QAAQ,CAAC;YACf,IAAI,CAAC,MAAM,gBAAgB;YAC3B,MAAM,UAAE,MAAM,EAAE,GAAG;YAEnB,IAAI;gBACF,CAAA,GAAA,wCAAQ,EAAE,QAAQ;gBAClB,QAAQ,SAAS;YACnB,EAAE,OAAO,OAAO;gBACd,QAAQ,QAAQ,QAAQ;YAC1B,SAAU;gBACR,SAAS,UAAU,SAAS,iCAAiC;YAC/D;QACF;IACF;IAEA;;;;GAIC,GACD,MAAM,WAAW,IAAI,qBACnB,oBACA,QAAQ;IAGV;;;;GAIC,GACD,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ;IAExD,cAAc,QAAQ,CAAC,OAAS,SAAS,QAAQ;AACnD;IAEA,2CAAe","sources":["src/index.js","src/options.js","src/assetLoader.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.6\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './options.js';\nimport loadAsset from './assetLoader.js';\n\n/**\n * Lazy load assets.\n *\n * @param {string} [selector=\"[lazy]\"] - The CSS selector for lazy loadable elements.\n * @param {Object} [settings={}] - Additional options for configuring the lazy loading behavior.\n */\nconst lazyLoad = (settings = {}) => {\n /**\n * Options object for configuring the lazy loading behavior.\n *\n * @type {Object}\n */\n const options = { ...defaultOptions, ...settings };\n\n /**\n * Handles the intersection of lazy load elements.\n *\n * @private\n *\n * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer.\n * @param {IntersectionObserver} observer - The intersection observer instance.\n */\n const handleIntersection = (entries, observer) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n const { target } = entry;\n\n try {\n loadAsset(target, options);\n options.onLoaded(target);\n } catch (error) {\n options.onError(target, error);\n } finally {\n observer.unobserve(target); // bunun tam testini yapmak lazim\n }\n });\n };\n\n /**\n * IntersectionObserver used for lazy loading.\n *\n * @type {IntersectionObserver}\n */\n const observer = new IntersectionObserver(\n handleIntersection,\n options.observer\n );\n\n /**\n * NodeList of lazy loadable elements.\n *\n * @type {NodeList}\n */\n const lazyLoadItems = document.querySelectorAll(options.selector);\n\n lazyLoadItems.forEach((item) => observer.observe(item));\n};\n\nexport default lazyLoad;\n","/**\n * Default options for lazy loading behavior.\n *\n * @type {Object}\n *\n * @param {string} [tag=selector] - The CSS selector for lazy loadable elements.\n * @param {string} [toggleClass=\"-loaded\"] - The class name to toggle on elements after loading.\n * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded.\n * @param {Function} [onError] - Callback function to execute when an error occurs during loading.\n * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading.\n */\nconst defaultOptions = {\n tag: 'lazy',\n selector: '[lazy]',\n toggleClass: '-loaded',\n onLoaded: () => {},\n onError: (element, error) => {\n console.error('🚀 Error on ~ element, error:', element, error);\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px', // Burayı daha detalı araştırmam gerek\n },\n};\n\nexport default defaultOptions;\n","/**\n * Loads the asset for the given image element.\n *\n * @private\n *\n * @param {HTMLImageElement} img - The image element to load the asset for.\n * @param {string} assetAttr - The asset URL attribute value.\n * @param {string} assetAlt - The asset alt attribute value.\n */\nconst loadImage = (img, assetAttr, assetAlt) => {\n img.src = assetAttr;\n img.alt = assetAlt;\n};\n\nconst loadBackground = (element, assetAttr) => {\n element.style.background = `url(${assetAttr})`;\n};\n\n/**\n * Loads the asset for the given picture element.\n *\n * @private\n *\n * @param {HTMLPictureElement} element - The picture element to load the asset for.\n * @param {string} assetAttr - The asset URL attribute value.\n * @param {string} assetAlt - The asset alt attribute value.\n */\nconst loadPicture = (element, assetAttr, assetAlt) => {\n let img = element.querySelector('img');\n if (!img) {\n img = document.createElement('img');\n element.append(img);\n }\n loadImage(img, assetAttr, assetAlt);\n};\n\n/**\n * Loads the asset for the given video element.\n *\n * @private\n *\n * @param {HTMLVideoElement} element - The video element to load the asset for.\n * @param {string} assetAttr - The asset URL attribute value.\n */\nconst loadVideo = (element, assetAttr) => {\n element.src = assetAttr;\n};\n\n/**\n * Loads the asset for the given element based on its type (img, picture, video).\n *\n * @private\n *\n * @param {HTMLElement} element - The element to load the asset for.\n */\nconst loadAsset = (element, options) => {\n const { tag } = options;\n\n const loadFunctions = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n };\n\n const elementType = element.tagName.toLowerCase();\n const loadFunction = loadFunctions[elementType];\n\n const assetAttr = element.getAttribute(`${tag}-src`);\n const assetAlt = element.getAttribute(`${tag}-alt`) || '';\n const backgroundAttr = element.getAttribute(`${tag}-background`);\n\n\n if (backgroundAttr) return loadBackground(element, backgroundAttr);\n if (loadFunction) return loadFunction(element, assetAttr, assetAlt);\n\n throw new Error(`Invalid element type: ${elementType}`);\n};\n\nexport default loadAsset;\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file +{"mappings":"AAAA;;;;;;;;ACAA;;;;;;;;;;CAUC,GACD,MAAM,uCAAiB;IACrB,KAAK;IACL,UAAU;IACV,aAAa;IACb,UAAU,KAAO;IACjB,SAAS,CAAC,SAAS;QACjB,QAAQ,MAAM,2CAAiC,SAAS;IAC1D;IACA,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;IAEA,2CAAe;;CDlBd;AERD;;;;;;;;CAQC,GACD,MAAM,kCAAY,CAAC,SAAS,KAAK;IAC/B,QAAQ,MAAM;IACd,QAAQ,MAAM;AAChB;AAEA,MAAM,uCAAiB,CAAC,SAAS;IAC/B,QAAQ,MAAM,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1C;AAEA;;;;;;;;CAQC,GACD,MAAM,oCAAc,CAAC,SAAS,KAAK;IACjC,IAAI,MAAM,QAAQ,cAAc;IAChC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,OAAO;IACjB;IACA,gCAAU,KAAK,KAAK;AACtB;AAEA;;;;;;;CAOC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM;AAChB;AAEA;;;;;;CAMC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,MAAM,OAAE,GAAG,EAAE,GAAG;IAEhB,MAAM,gBAAgB;QACpB,KAAK;QACL,SAAS;QACT,OAAO;IACT;IAEA,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,eAAe,aAAa,CAAC,YAAY;IAE/C,MAAM,YAAY,QAAQ,aAAa,CAAC,EAAE,IAAI,IAAI,CAAC;IACnD,MAAM,WAAW,QAAQ,aAAa,CAAC,EAAE,IAAI,IAAI,CAAC,KAAK;IACvD,MAAM,iBAAiB,QAAQ,aAAa,CAAC,EAAE,IAAI,WAAW,CAAC;IAE/D,IAAI,gBAAgB,OAAO,qCAAe,SAAS;IACnD,IAAI,cAAc,OAAO,aAAa,SAAS,WAAW;IAE1D,MAAM,IAAI,MAAM,CAAC,sBAAsB,EAAE,YAAY,CAAC;AACxD;IAEA,2CAAe;;;AFhEf;;;;;CAKC,GACD,MAAM,iCAAW,CAAC,WAAW,CAAC,CAAC;IAC7B;;;;GAIC,GACD,MAAM,UAAU;QAAE,GAAG,CAAA,GAAA,wCAAa,CAAC;QAAE,GAAG,QAAQ;IAAC;IAEjD;;;;;;;GAOC,GACD,MAAM,qBAAqB,CAAC,SAAS;QACnC,QAAQ,QAAQ,CAAC;YACf,IAAI,CAAC,MAAM,gBAAgB;YAC3B,MAAM,UAAE,MAAM,EAAE,GAAG;YAEnB,IAAI;gBACF,CAAA,GAAA,wCAAQ,EAAE,QAAQ;gBAClB,QAAQ,SAAS;YACnB,EAAE,OAAO,OAAO;gBACd,QAAQ,QAAQ,QAAQ;YAC1B,SAAU;gBACR,SAAS,UAAU,SAAS,iCAAiC;YAC/D;QACF;IACF;IAEA;;;;GAIC,GACD,MAAM,WAAW,IAAI,qBACnB,oBACA,QAAQ;IAGV;;;;GAIC,GACD,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ;IAExD,cAAc,QAAQ,CAAC,OAAS,SAAS,QAAQ;AACnD;IAEA,2CAAe","sources":["src/index.js","src/options.js","src/assetLoader.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.6\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './options.js';\nimport loadAsset from './assetLoader.js';\n\n/**\n * Lazy load assets.\n *\n * @param {string} [selector=\"[lazy]\"] - The CSS selector for lazy loadable elements.\n * @param {Object} [settings={}] - Additional options for configuring the lazy loading behavior.\n */\nconst lazyLoad = (settings = {}) => {\n /**\n * Options object for configuring the lazy loading behavior.\n *\n * @type {Object}\n */\n const options = { ...defaultOptions, ...settings };\n\n /**\n * Handles the intersection of lazy load elements.\n *\n * @private\n *\n * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer.\n * @param {IntersectionObserver} observer - The intersection observer instance.\n */\n const handleIntersection = (entries, observer) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n const { target } = entry;\n\n try {\n loadAsset(target, options);\n options.onLoaded(target);\n } catch (error) {\n options.onError(target, error);\n } finally {\n observer.unobserve(target); // bunun tam testini yapmak lazim\n }\n });\n };\n\n /**\n * IntersectionObserver used for lazy loading.\n *\n * @type {IntersectionObserver}\n */\n const observer = new IntersectionObserver(\n handleIntersection,\n options.observer\n );\n\n /**\n * NodeList of lazy loadable elements.\n *\n * @type {NodeList}\n */\n const lazyLoadItems = document.querySelectorAll(options.selector);\n\n lazyLoadItems.forEach((item) => observer.observe(item));\n};\n\nexport default lazyLoad;\n","/**\n * Default options for lazy loading behavior.\n *\n * @type {Object}\n *\n * @param {string} [tag=selector] - The CSS selector for lazy loadable elements.\n * @param {string} [toggleClass=\"-loaded\"] - The class name to toggle on elements after loading.\n * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded.\n * @param {Function} [onError] - Callback function to execute when an error occurs during loading.\n * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading.\n */\nconst defaultOptions = {\n tag: 'lazy',\n selector: '[lazy]',\n toggleClass: '-loaded',\n onLoaded: () => {},\n onError: (element, error) => {\n console.error('🚀 Error on ~ element, error:', element, error);\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px', // Burayı daha detalı araştırmam gerek\n },\n};\n\nexport default defaultOptions;\n","/**\n * Loads the asset for the given image element.\n *\n * @private\n *\n * @param {HTMLImageElement} element - The image element to load the asset for.\n * @param {string} src - The asset path attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadImage = (element, src, alt) => {\n element.src = src;\n element.alt = alt;\n};\n\nconst loadBackground = (element, src) => {\n element.style.background = `url(${src})`;\n};\n\n/**\n * Loads the asset for the given picture element.\n *\n * @private\n *\n * @param {HTMLPictureElement} element - The picture element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadPicture = (element, src, alt) => {\n let img = element.querySelector('img');\n if (!img) {\n img = document.createElement('img');\n element.append(img);\n }\n loadImage(img, src, alt);\n};\n\n/**\n * Loads the asset for the given video element.\n *\n * @private\n *\n * @param {HTMLVideoElement} element - The video element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n */\nconst loadVideo = (element, src) => {\n element.src = src;\n};\n\n/**\n * Loads the asset for the given element based on its type (img, picture, video).\n *\n * @private\n *\n * @param {HTMLElement} element - The element to load the asset for.\n */\nconst loadAsset = (element, options) => {\n const { tag } = options;\n\n const loadFunctions = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n };\n\n const elementType = element.tagName.toLowerCase();\n const loadFunction = loadFunctions[elementType];\n\n const assetAttr = element.getAttribute(`${tag}-src`);\n const assetAlt = element.getAttribute(`${tag}-alt`) || '';\n const backgroundAttr = element.getAttribute(`${tag}-background`);\n\n if (backgroundAttr) return loadBackground(element, backgroundAttr);\n if (loadFunction) return loadFunction(element, assetAttr, assetAlt);\n\n throw new Error(`Invalid element type: ${elementType}`);\n};\n\nexport default loadAsset;\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file diff --git a/src/assetLoader.js b/src/assetLoader.js index 04e215b..d8267f7 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -3,17 +3,17 @@ * * @private * - * @param {HTMLImageElement} img - The image element to load the asset for. - * @param {string} assetAttr - The asset URL attribute value. - * @param {string} assetAlt - The asset alt attribute value. + * @param {HTMLImageElement} element - The image element to load the asset for. + * @param {string} src - The asset path attribute value. + * @param {string} alt - The asset alt attribute value. */ -const loadImage = (img, assetAttr, assetAlt) => { - img.src = assetAttr; - img.alt = assetAlt; +const loadImage = (element, src, alt) => { + element.src = src; + element.alt = alt; }; -const loadBackground = (element, assetAttr) => { - element.style.background = `url(${assetAttr})`; +const loadBackground = (element, src) => { + element.style.background = `url(${src})`; }; /** @@ -22,16 +22,18 @@ const loadBackground = (element, assetAttr) => { * @private * * @param {HTMLPictureElement} element - The picture element to load the asset for. - * @param {string} assetAttr - The asset URL attribute value. - * @param {string} assetAlt - The asset alt attribute value. + * @param {string} src - The asset URL attribute value. + * @param {string} alt - The asset alt attribute value. */ -const loadPicture = (element, assetAttr, assetAlt) => { +const loadPicture = (element, src, alt) => { let img = element.querySelector('img'); + if (!img) { img = document.createElement('img'); element.append(img); } - loadImage(img, assetAttr, assetAlt); + + loadImage(img, src, alt); }; /** @@ -40,10 +42,10 @@ const loadPicture = (element, assetAttr, assetAlt) => { * @private * * @param {HTMLVideoElement} element - The video element to load the asset for. - * @param {string} assetAttr - The asset URL attribute value. + * @param {string} src - The asset URL attribute value. */ -const loadVideo = (element, assetAttr) => { - element.src = assetAttr; +const loadVideo = (element, src) => { + element.src = src; }; /** From 59d1b2d74781cc88267eb9cdc5585fe696722de8 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 23 Aug 2023 23:33:40 +0300 Subject: [PATCH 032/185] Add: Handler function --- dist/lazy-load.js | 10 ++++++---- dist/lazy-load.js.map | 2 +- src/index.js | 12 ++++++++---- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index 0cad5b3..be9fff3 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -121,18 +121,20 @@ var $f85e789b098d4f3c$export$2e2bcd8739ae039 = $f85e789b098d4f3c$var$loadAsset; * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer. * @param {IntersectionObserver} observer - The intersection observer instance. */ const handleIntersection = (entries, observer)=>{ - entries.forEach((entry)=>{ + const { onLoaded: onLoaded, onError: onError } = options; + const handler = (entry)=>{ if (!entry.isIntersecting) return; const { target: target } = entry; try { (0, $f85e789b098d4f3c$export$2e2bcd8739ae039)(target, options); - options.onLoaded(target); + onLoaded(target); } catch (error) { - options.onError(target, error); + onError(target, error); } finally{ observer.unobserve(target); // bunun tam testini yapmak lazim } - }); + }; + entries.forEach(handler); }; /** * IntersectionObserver used for lazy loading. diff --git a/dist/lazy-load.js.map b/dist/lazy-load.js.map index 3920cc1..79393ab 100644 --- a/dist/lazy-load.js.map +++ b/dist/lazy-load.js.map @@ -1 +1 @@ -{"mappings":"AAAA;;;;;;;;ACAA;;;;;;;;;;CAUC,GACD,MAAM,uCAAiB;IACrB,KAAK;IACL,UAAU;IACV,aAAa;IACb,UAAU,KAAO;IACjB,SAAS,CAAC,SAAS;QACjB,QAAQ,MAAM,2CAAiC,SAAS;IAC1D;IACA,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;IAEA,2CAAe;;CDlBd;AERD;;;;;;;;CAQC,GACD,MAAM,kCAAY,CAAC,SAAS,KAAK;IAC/B,QAAQ,MAAM;IACd,QAAQ,MAAM;AAChB;AAEA,MAAM,uCAAiB,CAAC,SAAS;IAC/B,QAAQ,MAAM,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1C;AAEA;;;;;;;;CAQC,GACD,MAAM,oCAAc,CAAC,SAAS,KAAK;IACjC,IAAI,MAAM,QAAQ,cAAc;IAChC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,OAAO;IACjB;IACA,gCAAU,KAAK,KAAK;AACtB;AAEA;;;;;;;CAOC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM;AAChB;AAEA;;;;;;CAMC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,MAAM,OAAE,GAAG,EAAE,GAAG;IAEhB,MAAM,gBAAgB;QACpB,KAAK;QACL,SAAS;QACT,OAAO;IACT;IAEA,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,eAAe,aAAa,CAAC,YAAY;IAE/C,MAAM,YAAY,QAAQ,aAAa,CAAC,EAAE,IAAI,IAAI,CAAC;IACnD,MAAM,WAAW,QAAQ,aAAa,CAAC,EAAE,IAAI,IAAI,CAAC,KAAK;IACvD,MAAM,iBAAiB,QAAQ,aAAa,CAAC,EAAE,IAAI,WAAW,CAAC;IAE/D,IAAI,gBAAgB,OAAO,qCAAe,SAAS;IACnD,IAAI,cAAc,OAAO,aAAa,SAAS,WAAW;IAE1D,MAAM,IAAI,MAAM,CAAC,sBAAsB,EAAE,YAAY,CAAC;AACxD;IAEA,2CAAe;;;AFhEf;;;;;CAKC,GACD,MAAM,iCAAW,CAAC,WAAW,CAAC,CAAC;IAC7B;;;;GAIC,GACD,MAAM,UAAU;QAAE,GAAG,CAAA,GAAA,wCAAa,CAAC;QAAE,GAAG,QAAQ;IAAC;IAEjD;;;;;;;GAOC,GACD,MAAM,qBAAqB,CAAC,SAAS;QACnC,QAAQ,QAAQ,CAAC;YACf,IAAI,CAAC,MAAM,gBAAgB;YAC3B,MAAM,UAAE,MAAM,EAAE,GAAG;YAEnB,IAAI;gBACF,CAAA,GAAA,wCAAQ,EAAE,QAAQ;gBAClB,QAAQ,SAAS;YACnB,EAAE,OAAO,OAAO;gBACd,QAAQ,QAAQ,QAAQ;YAC1B,SAAU;gBACR,SAAS,UAAU,SAAS,iCAAiC;YAC/D;QACF;IACF;IAEA;;;;GAIC,GACD,MAAM,WAAW,IAAI,qBACnB,oBACA,QAAQ;IAGV;;;;GAIC,GACD,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ;IAExD,cAAc,QAAQ,CAAC,OAAS,SAAS,QAAQ;AACnD;IAEA,2CAAe","sources":["src/index.js","src/options.js","src/assetLoader.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.6\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './options.js';\nimport loadAsset from './assetLoader.js';\n\n/**\n * Lazy load assets.\n *\n * @param {string} [selector=\"[lazy]\"] - The CSS selector for lazy loadable elements.\n * @param {Object} [settings={}] - Additional options for configuring the lazy loading behavior.\n */\nconst lazyLoad = (settings = {}) => {\n /**\n * Options object for configuring the lazy loading behavior.\n *\n * @type {Object}\n */\n const options = { ...defaultOptions, ...settings };\n\n /**\n * Handles the intersection of lazy load elements.\n *\n * @private\n *\n * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer.\n * @param {IntersectionObserver} observer - The intersection observer instance.\n */\n const handleIntersection = (entries, observer) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n const { target } = entry;\n\n try {\n loadAsset(target, options);\n options.onLoaded(target);\n } catch (error) {\n options.onError(target, error);\n } finally {\n observer.unobserve(target); // bunun tam testini yapmak lazim\n }\n });\n };\n\n /**\n * IntersectionObserver used for lazy loading.\n *\n * @type {IntersectionObserver}\n */\n const observer = new IntersectionObserver(\n handleIntersection,\n options.observer\n );\n\n /**\n * NodeList of lazy loadable elements.\n *\n * @type {NodeList}\n */\n const lazyLoadItems = document.querySelectorAll(options.selector);\n\n lazyLoadItems.forEach((item) => observer.observe(item));\n};\n\nexport default lazyLoad;\n","/**\n * Default options for lazy loading behavior.\n *\n * @type {Object}\n *\n * @param {string} [tag=selector] - The CSS selector for lazy loadable elements.\n * @param {string} [toggleClass=\"-loaded\"] - The class name to toggle on elements after loading.\n * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded.\n * @param {Function} [onError] - Callback function to execute when an error occurs during loading.\n * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading.\n */\nconst defaultOptions = {\n tag: 'lazy',\n selector: '[lazy]',\n toggleClass: '-loaded',\n onLoaded: () => {},\n onError: (element, error) => {\n console.error('🚀 Error on ~ element, error:', element, error);\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px', // Burayı daha detalı araştırmam gerek\n },\n};\n\nexport default defaultOptions;\n","/**\n * Loads the asset for the given image element.\n *\n * @private\n *\n * @param {HTMLImageElement} element - The image element to load the asset for.\n * @param {string} src - The asset path attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadImage = (element, src, alt) => {\n element.src = src;\n element.alt = alt;\n};\n\nconst loadBackground = (element, src) => {\n element.style.background = `url(${src})`;\n};\n\n/**\n * Loads the asset for the given picture element.\n *\n * @private\n *\n * @param {HTMLPictureElement} element - The picture element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadPicture = (element, src, alt) => {\n let img = element.querySelector('img');\n if (!img) {\n img = document.createElement('img');\n element.append(img);\n }\n loadImage(img, src, alt);\n};\n\n/**\n * Loads the asset for the given video element.\n *\n * @private\n *\n * @param {HTMLVideoElement} element - The video element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n */\nconst loadVideo = (element, src) => {\n element.src = src;\n};\n\n/**\n * Loads the asset for the given element based on its type (img, picture, video).\n *\n * @private\n *\n * @param {HTMLElement} element - The element to load the asset for.\n */\nconst loadAsset = (element, options) => {\n const { tag } = options;\n\n const loadFunctions = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n };\n\n const elementType = element.tagName.toLowerCase();\n const loadFunction = loadFunctions[elementType];\n\n const assetAttr = element.getAttribute(`${tag}-src`);\n const assetAlt = element.getAttribute(`${tag}-alt`) || '';\n const backgroundAttr = element.getAttribute(`${tag}-background`);\n\n if (backgroundAttr) return loadBackground(element, backgroundAttr);\n if (loadFunction) return loadFunction(element, assetAttr, assetAlt);\n\n throw new Error(`Invalid element type: ${elementType}`);\n};\n\nexport default loadAsset;\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file +{"mappings":"AAAA;;;;;;;;ACAA;;;;;;;;;;CAUC,GACD,MAAM,uCAAiB;IACrB,KAAK;IACL,UAAU;IACV,aAAa;IACb,UAAU,KAAO;IACjB,SAAS,CAAC,SAAS;QACjB,QAAQ,MAAM,2CAAiC,SAAS;IAC1D;IACA,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;IAEA,2CAAe;;CDlBd;AERD;;;;;;;;CAQC,GACD,MAAM,kCAAY,CAAC,SAAS,KAAK;IAC/B,QAAQ,MAAM;IACd,QAAQ,MAAM;AAChB;AAEA,MAAM,uCAAiB,CAAC,SAAS;IAC/B,QAAQ,MAAM,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1C;AAEA;;;;;;;;CAQC,GACD,MAAM,oCAAc,CAAC,SAAS,KAAK;IACjC,IAAI,MAAM,QAAQ,cAAc;IAEhC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,OAAO;IACjB;IAEA,gCAAU,KAAK,KAAK;AACtB;AAEA;;;;;;;CAOC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM;AAChB;AAEA;;;;;;CAMC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,MAAM,OAAE,GAAG,EAAE,GAAG;IAEhB,MAAM,gBAAgB;QACpB,KAAK;QACL,SAAS;QACT,OAAO;IACT;IAEA,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,eAAe,aAAa,CAAC,YAAY;IAE/C,MAAM,YAAY,QAAQ,aAAa,CAAC,EAAE,IAAI,IAAI,CAAC;IACnD,MAAM,WAAW,QAAQ,aAAa,CAAC,EAAE,IAAI,IAAI,CAAC,KAAK;IACvD,MAAM,iBAAiB,QAAQ,aAAa,CAAC,EAAE,IAAI,WAAW,CAAC;IAE/D,IAAI,gBAAgB,OAAO,qCAAe,SAAS;IACnD,IAAI,cAAc,OAAO,aAAa,SAAS,WAAW;IAE1D,MAAM,IAAI,MAAM,CAAC,sBAAsB,EAAE,YAAY,CAAC;AACxD;IAEA,2CAAe;;;AFlEf;;;;;CAKC,GACD,MAAM,iCAAW,CAAC,WAAW,CAAC,CAAC;IAC7B;;;;GAIC,GACD,MAAM,UAAU;QAAE,GAAG,CAAA,GAAA,wCAAa,CAAC;QAAE,GAAG,QAAQ;IAAC;IAEjD;;;;;;;GAOC,GACD,MAAM,qBAAqB,CAAC,SAAS;QACnC,MAAM,YAAE,QAAQ,WAAE,OAAO,EAAE,GAAG;QAE9B,MAAM,UAAU,CAAC;YACf,IAAI,CAAC,MAAM,gBAAgB;YAC3B,MAAM,UAAE,MAAM,EAAE,GAAG;YAEnB,IAAI;gBACF,CAAA,GAAA,wCAAQ,EAAE,QAAQ;gBAClB,SAAS;YACX,EAAE,OAAO,OAAO;gBACd,QAAQ,QAAQ;YAClB,SAAU;gBACR,SAAS,UAAU,SAAS,iCAAiC;YAC/D;QACF;QAEA,QAAQ,QAAQ;IAClB;IAEA;;;;GAIC,GACD,MAAM,WAAW,IAAI,qBACnB,oBACA,QAAQ;IAGV;;;;GAIC,GACD,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ;IAExD,cAAc,QAAQ,CAAC,OAAS,SAAS,QAAQ;AACnD;IAEA,2CAAe","sources":["src/index.js","src/options.js","src/assetLoader.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.6\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './options.js';\nimport loadAsset from './assetLoader.js';\n\n/**\n * Lazy load assets.\n *\n * @param {string} [selector=\"[lazy]\"] - The CSS selector for lazy loadable elements.\n * @param {Object} [settings={}] - Additional options for configuring the lazy loading behavior.\n */\nconst lazyLoad = (settings = {}) => {\n /**\n * Options object for configuring the lazy loading behavior.\n *\n * @type {Object}\n */\n const options = { ...defaultOptions, ...settings };\n\n /**\n * Handles the intersection of lazy load elements.\n *\n * @private\n *\n * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer.\n * @param {IntersectionObserver} observer - The intersection observer instance.\n */\n const handleIntersection = (entries, observer) => {\n const { onLoaded, onError } = options;\n\n const handler = (entry) => {\n if (!entry.isIntersecting) return;\n const { target } = entry;\n\n try {\n loadAsset(target, options);\n onLoaded(target);\n } catch (error) {\n onError(target, error);\n } finally {\n observer.unobserve(target); // bunun tam testini yapmak lazim\n }\n };\n\n entries.forEach(handler);\n };\n\n /**\n * IntersectionObserver used for lazy loading.\n *\n * @type {IntersectionObserver}\n */\n const observer = new IntersectionObserver(\n handleIntersection,\n options.observer\n );\n\n /**\n * NodeList of lazy loadable elements.\n *\n * @type {NodeList}\n */\n const lazyLoadItems = document.querySelectorAll(options.selector);\n\n lazyLoadItems.forEach((item) => observer.observe(item));\n};\n\nexport default lazyLoad;\n","/**\n * Default options for lazy loading behavior.\n *\n * @type {Object}\n *\n * @param {string} [tag=selector] - The CSS selector for lazy loadable elements.\n * @param {string} [toggleClass=\"-loaded\"] - The class name to toggle on elements after loading.\n * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded.\n * @param {Function} [onError] - Callback function to execute when an error occurs during loading.\n * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading.\n */\nconst defaultOptions = {\n tag: 'lazy',\n selector: '[lazy]',\n toggleClass: '-loaded',\n onLoaded: () => {},\n onError: (element, error) => {\n console.error('🚀 Error on ~ element, error:', element, error);\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px', // Burayı daha detalı araştırmam gerek\n },\n};\n\nexport default defaultOptions;\n","/**\n * Loads the asset for the given image element.\n *\n * @private\n *\n * @param {HTMLImageElement} element - The image element to load the asset for.\n * @param {string} src - The asset path attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadImage = (element, src, alt) => {\n element.src = src;\n element.alt = alt;\n};\n\nconst loadBackground = (element, src) => {\n element.style.background = `url(${src})`;\n};\n\n/**\n * Loads the asset for the given picture element.\n *\n * @private\n *\n * @param {HTMLPictureElement} element - The picture element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadPicture = (element, src, alt) => {\n let img = element.querySelector('img');\n\n if (!img) {\n img = document.createElement('img');\n element.append(img);\n }\n\n loadImage(img, src, alt);\n};\n\n/**\n * Loads the asset for the given video element.\n *\n * @private\n *\n * @param {HTMLVideoElement} element - The video element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n */\nconst loadVideo = (element, src) => {\n element.src = src;\n};\n\n/**\n * Loads the asset for the given element based on its type (img, picture, video).\n *\n * @private\n *\n * @param {HTMLElement} element - The element to load the asset for.\n */\nconst loadAsset = (element, options) => {\n const { tag } = options;\n\n const loadFunctions = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n };\n\n const elementType = element.tagName.toLowerCase();\n const loadFunction = loadFunctions[elementType];\n\n const assetAttr = element.getAttribute(`${tag}-src`);\n const assetAlt = element.getAttribute(`${tag}-alt`) || '';\n const backgroundAttr = element.getAttribute(`${tag}-background`);\n\n if (backgroundAttr) return loadBackground(element, backgroundAttr);\n if (loadFunction) return loadFunction(element, assetAttr, assetAlt);\n\n throw new Error(`Invalid element type: ${elementType}`);\n};\n\nexport default loadAsset;\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file diff --git a/src/index.js b/src/index.js index 66a1be1..8823b73 100644 --- a/src/index.js +++ b/src/index.js @@ -34,19 +34,23 @@ const lazyLoad = (settings = {}) => { * @param {IntersectionObserver} observer - The intersection observer instance. */ const handleIntersection = (entries, observer) => { - entries.forEach((entry) => { + const { onLoaded, onError } = options; + + const handler = (entry) => { if (!entry.isIntersecting) return; const { target } = entry; try { loadAsset(target, options); - options.onLoaded(target); + onLoaded(target); } catch (error) { - options.onError(target, error); + onError(target, error); } finally { observer.unobserve(target); // bunun tam testini yapmak lazim } - }); + }; + + entries.forEach(handler); }; /** From e3065fffb4b0f5056e7e41e492b31b79426fb225 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 23 Aug 2023 23:45:58 +0300 Subject: [PATCH 033/185] Update: Test file lang --- test/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/index.html b/test/index.html index 795b0c2..5d70c7e 100644 --- a/test/index.html +++ b/test/index.html @@ -1,5 +1,5 @@ - + From 896a7f93757ad2b6e675f1ccc4edc39ad93b5089 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 23 Aug 2023 23:46:18 +0300 Subject: [PATCH 034/185] Add: External CSS file --- test/index.html | 21 +-------------------- test/style.css | 23 +++++++++++++++++++++++ 2 files changed, 24 insertions(+), 20 deletions(-) create mode 100644 test/style.css diff --git a/test/index.html b/test/index.html index 5d70c7e..e39d64e 100644 --- a/test/index.html +++ b/test/index.html @@ -5,26 +5,7 @@ Lazy-load.js - + diff --git a/test/style.css b/test/style.css new file mode 100644 index 0000000..e6ce6a0 --- /dev/null +++ b/test/style.css @@ -0,0 +1,23 @@ +img { + position: relative; + display: block; + + margin: 1rem auto; + width: 400px; + height: auto; + max-width: 100%; + aspect-ratio: 1 / 1; + + border-radius: 10px; +} +img::after { + content: ''; + + position: absolute; + inset: 0; + + width: 100%; + height: 100%; + + background-color: #e4e4e4; +} From 25d6be27db336f8ae00c35dd87066092008451cb Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 24 Aug 2023 00:06:23 +0300 Subject: [PATCH 035/185] Refactor: Prettier --- test/index.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/test/index.js b/test/index.js index 88e9c2c..8b6e86a 100644 --- a/test/index.js +++ b/test/index.js @@ -1,7 +1,5 @@ import lazyLoad from '/dist/lazy-load.js'; lazyLoad({ - onLoaded: (element) => { - console.log(element); - }, + onLoaded: (element) => console.log(element), }); From 49ba7f1fab7c54a2fe79e3880e03151597a23779 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 24 Aug 2023 00:06:41 +0300 Subject: [PATCH 036/185] Update: Rename object --- src/options.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/options.js b/src/options.js index 163537c..3e11abf 100644 --- a/src/options.js +++ b/src/options.js @@ -9,7 +9,7 @@ * @param {Function} [onError] - Callback function to execute when an error occurs during loading. * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. */ -const defaultOptions = { +const options = { tag: 'lazy', selector: '[lazy]', toggleClass: '-loaded', @@ -24,4 +24,4 @@ const defaultOptions = { }, }; -export default defaultOptions; +export default options; From 3a8635718359e407ba7fab7db48ca3fa4c5e9863 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 24 Aug 2023 00:07:07 +0300 Subject: [PATCH 037/185] Add: Global variables --- dist/lazy-load.js | 8 ++++---- dist/lazy-load.js.map | 2 +- src/index.js | 5 ++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index be9fff3..6b2705f 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -16,7 +16,7 @@ * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded. * @param {Function} [onError] - Callback function to execute when an error occurs during loading. * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. - */ const $50e97065b94a2e88$var$defaultOptions = { + */ const $50e97065b94a2e88$var$options = { tag: "lazy", selector: "[lazy]", toggleClass: "-loaded", @@ -30,7 +30,7 @@ rootMargin: "100% 0px" } }; -var $50e97065b94a2e88$export$2e2bcd8739ae039 = $50e97065b94a2e88$var$defaultOptions; +var $50e97065b94a2e88$export$2e2bcd8739ae039 = $50e97065b94a2e88$var$options; /** @@ -113,6 +113,7 @@ var $f85e789b098d4f3c$export$2e2bcd8739ae039 = $f85e789b098d4f3c$var$loadAsset; ...(0, $50e97065b94a2e88$export$2e2bcd8739ae039), ...settings }; + const { onLoaded: onLoaded, onError: onError, selector: selector } = options; /** * Handles the intersection of lazy load elements. * @@ -121,7 +122,6 @@ var $f85e789b098d4f3c$export$2e2bcd8739ae039 = $f85e789b098d4f3c$var$loadAsset; * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer. * @param {IntersectionObserver} observer - The intersection observer instance. */ const handleIntersection = (entries, observer)=>{ - const { onLoaded: onLoaded, onError: onError } = options; const handler = (entry)=>{ if (!entry.isIntersecting) return; const { target: target } = entry; @@ -145,7 +145,7 @@ var $f85e789b098d4f3c$export$2e2bcd8739ae039 = $f85e789b098d4f3c$var$loadAsset; * NodeList of lazy loadable elements. * * @type {NodeList} - */ const lazyLoadItems = document.querySelectorAll(options.selector); + */ const lazyLoadItems = document.querySelectorAll(selector); lazyLoadItems.forEach((item)=>observer.observe(item)); }; var $cf838c15c8b009ba$export$2e2bcd8739ae039 = $cf838c15c8b009ba$var$lazyLoad; diff --git a/dist/lazy-load.js.map b/dist/lazy-load.js.map index 79393ab..f204da5 100644 --- a/dist/lazy-load.js.map +++ b/dist/lazy-load.js.map @@ -1 +1 @@ -{"mappings":"AAAA;;;;;;;;ACAA;;;;;;;;;;CAUC,GACD,MAAM,uCAAiB;IACrB,KAAK;IACL,UAAU;IACV,aAAa;IACb,UAAU,KAAO;IACjB,SAAS,CAAC,SAAS;QACjB,QAAQ,MAAM,2CAAiC,SAAS;IAC1D;IACA,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;IAEA,2CAAe;;CDlBd;AERD;;;;;;;;CAQC,GACD,MAAM,kCAAY,CAAC,SAAS,KAAK;IAC/B,QAAQ,MAAM;IACd,QAAQ,MAAM;AAChB;AAEA,MAAM,uCAAiB,CAAC,SAAS;IAC/B,QAAQ,MAAM,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1C;AAEA;;;;;;;;CAQC,GACD,MAAM,oCAAc,CAAC,SAAS,KAAK;IACjC,IAAI,MAAM,QAAQ,cAAc;IAEhC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,OAAO;IACjB;IAEA,gCAAU,KAAK,KAAK;AACtB;AAEA;;;;;;;CAOC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM;AAChB;AAEA;;;;;;CAMC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,MAAM,OAAE,GAAG,EAAE,GAAG;IAEhB,MAAM,gBAAgB;QACpB,KAAK;QACL,SAAS;QACT,OAAO;IACT;IAEA,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,eAAe,aAAa,CAAC,YAAY;IAE/C,MAAM,YAAY,QAAQ,aAAa,CAAC,EAAE,IAAI,IAAI,CAAC;IACnD,MAAM,WAAW,QAAQ,aAAa,CAAC,EAAE,IAAI,IAAI,CAAC,KAAK;IACvD,MAAM,iBAAiB,QAAQ,aAAa,CAAC,EAAE,IAAI,WAAW,CAAC;IAE/D,IAAI,gBAAgB,OAAO,qCAAe,SAAS;IACnD,IAAI,cAAc,OAAO,aAAa,SAAS,WAAW;IAE1D,MAAM,IAAI,MAAM,CAAC,sBAAsB,EAAE,YAAY,CAAC;AACxD;IAEA,2CAAe;;;AFlEf;;;;;CAKC,GACD,MAAM,iCAAW,CAAC,WAAW,CAAC,CAAC;IAC7B;;;;GAIC,GACD,MAAM,UAAU;QAAE,GAAG,CAAA,GAAA,wCAAa,CAAC;QAAE,GAAG,QAAQ;IAAC;IAEjD;;;;;;;GAOC,GACD,MAAM,qBAAqB,CAAC,SAAS;QACnC,MAAM,YAAE,QAAQ,WAAE,OAAO,EAAE,GAAG;QAE9B,MAAM,UAAU,CAAC;YACf,IAAI,CAAC,MAAM,gBAAgB;YAC3B,MAAM,UAAE,MAAM,EAAE,GAAG;YAEnB,IAAI;gBACF,CAAA,GAAA,wCAAQ,EAAE,QAAQ;gBAClB,SAAS;YACX,EAAE,OAAO,OAAO;gBACd,QAAQ,QAAQ;YAClB,SAAU;gBACR,SAAS,UAAU,SAAS,iCAAiC;YAC/D;QACF;QAEA,QAAQ,QAAQ;IAClB;IAEA;;;;GAIC,GACD,MAAM,WAAW,IAAI,qBACnB,oBACA,QAAQ;IAGV;;;;GAIC,GACD,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ;IAExD,cAAc,QAAQ,CAAC,OAAS,SAAS,QAAQ;AACnD;IAEA,2CAAe","sources":["src/index.js","src/options.js","src/assetLoader.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.6\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './options.js';\nimport loadAsset from './assetLoader.js';\n\n/**\n * Lazy load assets.\n *\n * @param {string} [selector=\"[lazy]\"] - The CSS selector for lazy loadable elements.\n * @param {Object} [settings={}] - Additional options for configuring the lazy loading behavior.\n */\nconst lazyLoad = (settings = {}) => {\n /**\n * Options object for configuring the lazy loading behavior.\n *\n * @type {Object}\n */\n const options = { ...defaultOptions, ...settings };\n\n /**\n * Handles the intersection of lazy load elements.\n *\n * @private\n *\n * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer.\n * @param {IntersectionObserver} observer - The intersection observer instance.\n */\n const handleIntersection = (entries, observer) => {\n const { onLoaded, onError } = options;\n\n const handler = (entry) => {\n if (!entry.isIntersecting) return;\n const { target } = entry;\n\n try {\n loadAsset(target, options);\n onLoaded(target);\n } catch (error) {\n onError(target, error);\n } finally {\n observer.unobserve(target); // bunun tam testini yapmak lazim\n }\n };\n\n entries.forEach(handler);\n };\n\n /**\n * IntersectionObserver used for lazy loading.\n *\n * @type {IntersectionObserver}\n */\n const observer = new IntersectionObserver(\n handleIntersection,\n options.observer\n );\n\n /**\n * NodeList of lazy loadable elements.\n *\n * @type {NodeList}\n */\n const lazyLoadItems = document.querySelectorAll(options.selector);\n\n lazyLoadItems.forEach((item) => observer.observe(item));\n};\n\nexport default lazyLoad;\n","/**\n * Default options for lazy loading behavior.\n *\n * @type {Object}\n *\n * @param {string} [tag=selector] - The CSS selector for lazy loadable elements.\n * @param {string} [toggleClass=\"-loaded\"] - The class name to toggle on elements after loading.\n * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded.\n * @param {Function} [onError] - Callback function to execute when an error occurs during loading.\n * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading.\n */\nconst defaultOptions = {\n tag: 'lazy',\n selector: '[lazy]',\n toggleClass: '-loaded',\n onLoaded: () => {},\n onError: (element, error) => {\n console.error('🚀 Error on ~ element, error:', element, error);\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px', // Burayı daha detalı araştırmam gerek\n },\n};\n\nexport default defaultOptions;\n","/**\n * Loads the asset for the given image element.\n *\n * @private\n *\n * @param {HTMLImageElement} element - The image element to load the asset for.\n * @param {string} src - The asset path attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadImage = (element, src, alt) => {\n element.src = src;\n element.alt = alt;\n};\n\nconst loadBackground = (element, src) => {\n element.style.background = `url(${src})`;\n};\n\n/**\n * Loads the asset for the given picture element.\n *\n * @private\n *\n * @param {HTMLPictureElement} element - The picture element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadPicture = (element, src, alt) => {\n let img = element.querySelector('img');\n\n if (!img) {\n img = document.createElement('img');\n element.append(img);\n }\n\n loadImage(img, src, alt);\n};\n\n/**\n * Loads the asset for the given video element.\n *\n * @private\n *\n * @param {HTMLVideoElement} element - The video element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n */\nconst loadVideo = (element, src) => {\n element.src = src;\n};\n\n/**\n * Loads the asset for the given element based on its type (img, picture, video).\n *\n * @private\n *\n * @param {HTMLElement} element - The element to load the asset for.\n */\nconst loadAsset = (element, options) => {\n const { tag } = options;\n\n const loadFunctions = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n };\n\n const elementType = element.tagName.toLowerCase();\n const loadFunction = loadFunctions[elementType];\n\n const assetAttr = element.getAttribute(`${tag}-src`);\n const assetAlt = element.getAttribute(`${tag}-alt`) || '';\n const backgroundAttr = element.getAttribute(`${tag}-background`);\n\n if (backgroundAttr) return loadBackground(element, backgroundAttr);\n if (loadFunction) return loadFunction(element, assetAttr, assetAlt);\n\n throw new Error(`Invalid element type: ${elementType}`);\n};\n\nexport default loadAsset;\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file +{"mappings":"AAAA;;;;;;;;ACAA;;;;;;;;;;CAUC,GACD,MAAM,gCAAU;IACd,KAAK;IACL,UAAU;IACV,aAAa;IACb,UAAU,KAAO;IACjB,SAAS,CAAC,SAAS;QACjB,QAAQ,MAAM,2CAAiC,SAAS;IAC1D;IACA,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;IAEA,2CAAe;;CDlBd;AERD;;;;;;;;CAQC,GACD,MAAM,kCAAY,CAAC,SAAS,KAAK;IAC/B,QAAQ,MAAM;IACd,QAAQ,MAAM;AAChB;AAEA,MAAM,uCAAiB,CAAC,SAAS;IAC/B,QAAQ,MAAM,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1C;AAEA;;;;;;;;CAQC,GACD,MAAM,oCAAc,CAAC,SAAS,KAAK;IACjC,IAAI,MAAM,QAAQ,cAAc;IAEhC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,OAAO;IACjB;IAEA,gCAAU,KAAK,KAAK;AACtB;AAEA;;;;;;;CAOC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM;AAChB;AAEA;;;;;;CAMC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,MAAM,OAAE,GAAG,EAAE,GAAG;IAEhB,MAAM,gBAAgB;QACpB,KAAK;QACL,SAAS;QACT,OAAO;IACT;IAEA,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,eAAe,aAAa,CAAC,YAAY;IAE/C,MAAM,YAAY,QAAQ,aAAa,CAAC,EAAE,IAAI,IAAI,CAAC;IACnD,MAAM,WAAW,QAAQ,aAAa,CAAC,EAAE,IAAI,IAAI,CAAC,KAAK;IACvD,MAAM,iBAAiB,QAAQ,aAAa,CAAC,EAAE,IAAI,WAAW,CAAC;IAE/D,IAAI,gBAAgB,OAAO,qCAAe,SAAS;IACnD,IAAI,cAAc,OAAO,aAAa,SAAS,WAAW;IAE1D,MAAM,IAAI,MAAM,CAAC,sBAAsB,EAAE,YAAY,CAAC;AACxD;IAEA,2CAAe;;;AFlEf;;;;;CAKC,GACD,MAAM,iCAAW,CAAC,WAAW,CAAC,CAAC;IAC7B;;;;GAIC,GACD,MAAM,UAAU;QAAE,GAAG,CAAA,GAAA,wCAAa,CAAC;QAAE,GAAG,QAAQ;IAAC;IACjD,MAAM,YAAE,QAAQ,WAAE,OAAO,YAAE,QAAQ,EAAE,GAAG;IAExC;;;;;;;GAOC,GACD,MAAM,qBAAqB,CAAC,SAAS;QACnC,MAAM,UAAU,CAAC;YACf,IAAI,CAAC,MAAM,gBAAgB;YAC3B,MAAM,UAAE,MAAM,EAAE,GAAG;YAEnB,IAAI;gBACF,CAAA,GAAA,wCAAQ,EAAE,QAAQ;gBAClB,SAAS;YACX,EAAE,OAAO,OAAO;gBACd,QAAQ,QAAQ;YAClB,SAAU;gBACR,SAAS,UAAU,SAAS,iCAAiC;YAC/D;QACF;QAEA,QAAQ,QAAQ;IAClB;IAEA;;;;GAIC,GACD,MAAM,WAAW,IAAI,qBACnB,oBACA,QAAQ;IAGV;;;;GAIC,GACD,MAAM,gBAAgB,SAAS,iBAAiB;IAEhD,cAAc,QAAQ,CAAC,OAAS,SAAS,QAAQ;AACnD;IAEA,2CAAe","sources":["src/index.js","src/options.js","src/assetLoader.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.6\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './options.js';\nimport loadAsset from './assetLoader.js';\n\n/**\n * Lazy load assets.\n *\n * @param {string} [selector=\"[lazy]\"] - The CSS selector for lazy loadable elements.\n * @param {Object} [settings={}] - Additional options for configuring the lazy loading behavior.\n */\nconst lazyLoad = (settings = {}) => {\n /**\n * Options object for configuring the lazy loading behavior.\n *\n * @type {Object}\n */\n const options = { ...defaultOptions, ...settings };\n const { onLoaded, onError, selector } = options;\n\n /**\n * Handles the intersection of lazy load elements.\n *\n * @private\n *\n * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer.\n * @param {IntersectionObserver} observer - The intersection observer instance.\n */\n const handleIntersection = (entries, observer) => {\n const handler = (entry) => {\n if (!entry.isIntersecting) return;\n const { target } = entry;\n\n try {\n loadAsset(target, options);\n onLoaded(target);\n } catch (error) {\n onError(target, error);\n } finally {\n observer.unobserve(target); // bunun tam testini yapmak lazim\n }\n };\n\n entries.forEach(handler);\n };\n\n /**\n * IntersectionObserver used for lazy loading.\n *\n * @type {IntersectionObserver}\n */\n const observer = new IntersectionObserver(\n handleIntersection,\n options.observer\n );\n\n /**\n * NodeList of lazy loadable elements.\n *\n * @type {NodeList}\n */\n const lazyLoadItems = document.querySelectorAll(selector);\n\n lazyLoadItems.forEach((item) => observer.observe(item));\n};\n\nexport default lazyLoad;\n","/**\n * Default options for lazy loading behavior.\n *\n * @type {Object}\n *\n * @param {string} [tag=selector] - The CSS selector for lazy loadable elements.\n * @param {string} [toggleClass=\"-loaded\"] - The class name to toggle on elements after loading.\n * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded.\n * @param {Function} [onError] - Callback function to execute when an error occurs during loading.\n * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading.\n */\nconst options = {\n tag: 'lazy',\n selector: '[lazy]',\n toggleClass: '-loaded',\n onLoaded: () => {},\n onError: (element, error) => {\n console.error('🚀 Error on ~ element, error:', element, error);\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px', // Burayı daha detalı araştırmam gerek\n },\n};\n\nexport default options;\n","/**\n * Loads the asset for the given image element.\n *\n * @private\n *\n * @param {HTMLImageElement} element - The image element to load the asset for.\n * @param {string} src - The asset path attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadImage = (element, src, alt) => {\n element.src = src;\n element.alt = alt;\n};\n\nconst loadBackground = (element, src) => {\n element.style.background = `url(${src})`;\n};\n\n/**\n * Loads the asset for the given picture element.\n *\n * @private\n *\n * @param {HTMLPictureElement} element - The picture element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadPicture = (element, src, alt) => {\n let img = element.querySelector('img');\n\n if (!img) {\n img = document.createElement('img');\n element.append(img);\n }\n\n loadImage(img, src, alt);\n};\n\n/**\n * Loads the asset for the given video element.\n *\n * @private\n *\n * @param {HTMLVideoElement} element - The video element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n */\nconst loadVideo = (element, src) => {\n element.src = src;\n};\n\n/**\n * Loads the asset for the given element based on its type (img, picture, video).\n *\n * @private\n *\n * @param {HTMLElement} element - The element to load the asset for.\n */\nconst loadAsset = (element, options) => {\n const { tag } = options;\n\n const loadFunctions = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n };\n\n const elementType = element.tagName.toLowerCase();\n const loadFunction = loadFunctions[elementType];\n\n const assetAttr = element.getAttribute(`${tag}-src`);\n const assetAlt = element.getAttribute(`${tag}-alt`) || '';\n const backgroundAttr = element.getAttribute(`${tag}-background`);\n\n if (backgroundAttr) return loadBackground(element, backgroundAttr);\n if (loadFunction) return loadFunction(element, assetAttr, assetAlt);\n\n throw new Error(`Invalid element type: ${elementType}`);\n};\n\nexport default loadAsset;\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file diff --git a/src/index.js b/src/index.js index 8823b73..a8add6b 100644 --- a/src/index.js +++ b/src/index.js @@ -24,6 +24,7 @@ const lazyLoad = (settings = {}) => { * @type {Object} */ const options = { ...defaultOptions, ...settings }; + const { onLoaded, onError, selector } = options; /** * Handles the intersection of lazy load elements. @@ -34,8 +35,6 @@ const lazyLoad = (settings = {}) => { * @param {IntersectionObserver} observer - The intersection observer instance. */ const handleIntersection = (entries, observer) => { - const { onLoaded, onError } = options; - const handler = (entry) => { if (!entry.isIntersecting) return; const { target } = entry; @@ -68,7 +67,7 @@ const lazyLoad = (settings = {}) => { * * @type {NodeList} */ - const lazyLoadItems = document.querySelectorAll(options.selector); + const lazyLoadItems = document.querySelectorAll(selector); lazyLoadItems.forEach((item) => observer.observe(item)); }; From 652ffd2e56f7847d7da6c97e265576e47a3bb267 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 20 Sep 2023 19:55:14 +0300 Subject: [PATCH 038/185] Update: Assigment order --- src/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index a8add6b..262c6a6 100644 --- a/src/index.js +++ b/src/index.js @@ -36,8 +36,8 @@ const lazyLoad = (settings = {}) => { */ const handleIntersection = (entries, observer) => { const handler = (entry) => { - if (!entry.isIntersecting) return; - const { target } = entry; + const { target, isIntersecting } = entry; + if (!isIntersecting) return; try { loadAsset(target, options); From 598c27b889bfb5708636d156ca7d30c38711960a Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 20 Sep 2023 20:23:54 +0300 Subject: [PATCH 039/185] Update: Parameter name --- src/index.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/index.js b/src/index.js index 262c6a6..bccbae1 100644 --- a/src/index.js +++ b/src/index.js @@ -15,15 +15,15 @@ import loadAsset from './assetLoader.js'; * Lazy load assets. * * @param {string} [selector="[lazy]"] - The CSS selector for lazy loadable elements. - * @param {Object} [settings={}] - Additional options for configuring the lazy loading behavior. + * @param {Object} [customOptions={}] - Additional options for configuring the lazy loading behavior. */ -const lazyLoad = (settings = {}) => { +const lazyLoad = (customOptions = {}) => { /** * Options object for configuring the lazy loading behavior. * * @type {Object} */ - const options = { ...defaultOptions, ...settings }; + const options = { ...defaultOptions, ...customOptions }; const { onLoaded, onError, selector } = options; /** From fd81cfd56d2a922b108ebd9240bf12953ec89766 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 20 Sep 2023 20:35:24 +0300 Subject: [PATCH 040/185] Add: Dynamic options selector --- src/options.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/options.js b/src/options.js index 3e11abf..3124d65 100644 --- a/src/options.js +++ b/src/options.js @@ -10,8 +10,11 @@ * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. */ const options = { + get selector() { + return `[${this.tag}]`; + }, + tag: 'lazy', - selector: '[lazy]', toggleClass: '-loaded', onLoaded: () => {}, onError: (element, error) => { From 37d85dff0fe5eb6fe59879aabf3df91d58ae250a Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 28 Sep 2023 21:51:03 +0300 Subject: [PATCH 041/185] Update: Order of func --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index bccbae1..c1f9a19 100644 --- a/src/index.js +++ b/src/index.js @@ -40,8 +40,8 @@ const lazyLoad = (customOptions = {}) => { if (!isIntersecting) return; try { - loadAsset(target, options); onLoaded(target); + loadAsset(target, options); } catch (error) { onError(target, error); } finally { From a99eac0388d943e40790caee55f05d7fdb05e558 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 28 Sep 2023 21:53:40 +0300 Subject: [PATCH 042/185] Delete: Unused comment --- src/index.js | 1 - 1 file changed, 1 deletion(-) diff --git a/src/index.js b/src/index.js index c1f9a19..12e9a36 100644 --- a/src/index.js +++ b/src/index.js @@ -14,7 +14,6 @@ import loadAsset from './assetLoader.js'; /** * Lazy load assets. * - * @param {string} [selector="[lazy]"] - The CSS selector for lazy loadable elements. * @param {Object} [customOptions={}] - Additional options for configuring the lazy loading behavior. */ const lazyLoad = (customOptions = {}) => { From 0f52a3c7900ffdc8472933ec777ffbf27590ff18 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 28 Sep 2023 21:54:07 +0300 Subject: [PATCH 043/185] Delete: Comment --- src/options.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/options.js b/src/options.js index 3124d65..71296b0 100644 --- a/src/options.js +++ b/src/options.js @@ -23,7 +23,7 @@ const options = { observer: { root: null, threshold: 1, - rootMargin: '100% 0px', // Burayı daha detalı araştırmam gerek + rootMargin: '100% 0px', }, }; From 50c833a351f3bab7a4de18cc6206b6b86d9dbca7 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 28 Sep 2023 21:55:19 +0300 Subject: [PATCH 044/185] Add: Getter --- src/options.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/options.js b/src/options.js index 71296b0..55ac1e2 100644 --- a/src/options.js +++ b/src/options.js @@ -13,6 +13,9 @@ const options = { get selector() { return `[${this.tag}]`; }, + get altAttribute() { + return `${this.tag}-alt`; + }, tag: 'lazy', toggleClass: '-loaded', From 00b56fd922819266006b0d5cf3da6087aeefcc04 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 28 Sep 2023 21:56:14 +0300 Subject: [PATCH 045/185] Update: Moddifiers --- src/options.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/options.js b/src/options.js index 55ac1e2..23d1100 100644 --- a/src/options.js +++ b/src/options.js @@ -18,7 +18,10 @@ const options = { }, tag: 'lazy', - toggleClass: '-loaded', + modifiers: { + loaded: '-loaded', + loading: '-loading', + }, onLoaded: () => {}, onError: (element, error) => { console.error('🚀 Error on ~ element, error:', element, error); From 86ea13618f635b24bab77d341867c20a7627e79f Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 28 Sep 2023 22:00:23 +0300 Subject: [PATCH 046/185] Add: Null check --- src/assetLoader.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index d8267f7..f767a0a 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -7,9 +7,9 @@ * @param {string} src - The asset path attribute value. * @param {string} alt - The asset alt attribute value. */ -const loadImage = (element, src, alt) => { +const loadImage = (element, src, alt = null) => { element.src = src; - element.alt = alt; + if (alt) element.alt = alt; }; const loadBackground = (element, src) => { From 636ffb426a774fe62c688bc1a43a229bd1a2b61c Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 28 Sep 2023 22:03:22 +0300 Subject: [PATCH 047/185] Delete: Disable background feature --- src/assetLoader.js | 16 ++++++---------- 1 file changed, 6 insertions(+), 10 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index f767a0a..2e7a3d0 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -56,25 +56,21 @@ const loadVideo = (element, src) => { * @param {HTMLElement} element - The element to load the asset for. */ const loadAsset = (element, options) => { - const { tag } = options; + const { tag, altAttr } = options; - const loadFunctions = { + const assetLoaders = { img: loadImage, picture: loadPicture, video: loadVideo, }; const elementType = element.tagName.toLowerCase(); - const loadFunction = loadFunctions[elementType]; + const assetLoader = assetLoaders[elementType]; - const assetAttr = element.getAttribute(`${tag}-src`); - const assetAlt = element.getAttribute(`${tag}-alt`) || ''; - const backgroundAttr = element.getAttribute(`${tag}-background`); + const assetPath = element.getAttribute(tag); + const assetAltValue = element.getAttribute(altAttr); - if (backgroundAttr) return loadBackground(element, backgroundAttr); - if (loadFunction) return loadFunction(element, assetAttr, assetAlt); - - throw new Error(`Invalid element type: ${elementType}`); + assetLoader(element, assetPath, assetAltValue); }; export default loadAsset; From 97fe19c730025d1d42050b7aa47fabe1dc1e9953 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 28 Sep 2023 22:04:03 +0300 Subject: [PATCH 048/185] Update: Test --- test/index.html | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/test/index.html b/test/index.html index e39d64e..0de0fd8 100644 --- a/test/index.html +++ b/test/index.html @@ -9,16 +9,16 @@ - - Random Image - Random Image - Random Image - Random Image - Random Image - Random Image - Random Image - Random Image - Random Image + + Random Image + Random Image + Random Image + Random Image + Random Image + Random Image + Random Image + Random Image + Random Image From d4b7a261d2a8bf008bb7a6e1942fe95ac26ac03f Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 1 Nov 2023 23:23:23 +0300 Subject: [PATCH 049/185] Update: Order of funcs --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 12e9a36..ff335c4 100644 --- a/src/index.js +++ b/src/index.js @@ -39,8 +39,8 @@ const lazyLoad = (customOptions = {}) => { if (!isIntersecting) return; try { + loadAsset(target, options); onLoaded(target); - loadAsset(target, options); } catch (error) { onError(target, error); } finally { From 1bbe81a35573f053f0cfaeb2c2403838809cab9f Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 4 Nov 2023 21:37:22 +0300 Subject: [PATCH 050/185] Refactor: lazyLoad function options --- src/index.js | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/index.js b/src/index.js index ff335c4..35ee068 100644 --- a/src/index.js +++ b/src/index.js @@ -23,7 +23,6 @@ const lazyLoad = (customOptions = {}) => { * @type {Object} */ const options = { ...defaultOptions, ...customOptions }; - const { onLoaded, onError, selector } = options; /** * Handles the intersection of lazy load elements. @@ -39,10 +38,10 @@ const lazyLoad = (customOptions = {}) => { if (!isIntersecting) return; try { - loadAsset(target, options); - onLoaded(target); + loadAsset(target, options); + options.onLoaded(target); } catch (error) { - onError(target, error); + options.onError(target, error); } finally { observer.unobserve(target); // bunun tam testini yapmak lazim } @@ -66,7 +65,7 @@ const lazyLoad = (customOptions = {}) => { * * @type {NodeList} */ - const lazyLoadItems = document.querySelectorAll(selector); + const lazyLoadItems = document.querySelectorAll(options.selector); lazyLoadItems.forEach((item) => observer.observe(item)); }; From cbce41ea2aaa872e16599d7783fd549375de9440 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 4 Nov 2023 21:42:52 +0300 Subject: [PATCH 051/185] Update: lazy loading behavior by allowing custom tag value --- dist/lazy-load.js | 52 +++++++++++++++++++++++-------------------- dist/lazy-load.js.map | 2 +- src/index.js | 4 +++- src/options.js | 2 +- 4 files changed, 33 insertions(+), 27 deletions(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index 6b2705f..06a8ae9 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -17,9 +17,17 @@ * @param {Function} [onError] - Callback function to execute when an error occurs during loading. * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. */ const $50e97065b94a2e88$var$options = { - tag: "lazy", - selector: "[lazy]", - toggleClass: "-loaded", + get selector () { + return `[${this.tag}]`; + }, + get altAttribute () { + return `${this.tag}-alt`; + }, + tag: null, + modifiers: { + loaded: "-loaded", + loading: "-loading" + }, onLoaded: ()=>{}, onError: (element, error)=>{ console.error("\uD83D\uDE80 Error on ~ element, error:", element, error); @@ -41,9 +49,9 @@ var $50e97065b94a2e88$export$2e2bcd8739ae039 = $50e97065b94a2e88$var$options; * @param {HTMLImageElement} element - The image element to load the asset for. * @param {string} src - The asset path attribute value. * @param {string} alt - The asset alt attribute value. - */ const $f85e789b098d4f3c$var$loadImage = (element, src, alt)=>{ + */ const $f85e789b098d4f3c$var$loadImage = (element, src, alt = null)=>{ element.src = src; - element.alt = alt; + if (alt) element.alt = alt; }; const $f85e789b098d4f3c$var$loadBackground = (element, src)=>{ element.style.background = `url(${src})`; @@ -81,20 +89,17 @@ const $f85e789b098d4f3c$var$loadBackground = (element, src)=>{ * * @param {HTMLElement} element - The element to load the asset for. */ const $f85e789b098d4f3c$var$loadAsset = (element, options)=>{ - const { tag: tag } = options; - const loadFunctions = { + const { tag: tag, altAttr: altAttr } = options; + const assetLoaders = { img: $f85e789b098d4f3c$var$loadImage, picture: $f85e789b098d4f3c$var$loadPicture, video: $f85e789b098d4f3c$var$loadVideo }; const elementType = element.tagName.toLowerCase(); - const loadFunction = loadFunctions[elementType]; - const assetAttr = element.getAttribute(`${tag}-src`); - const assetAlt = element.getAttribute(`${tag}-alt`) || ""; - const backgroundAttr = element.getAttribute(`${tag}-background`); - if (backgroundAttr) return $f85e789b098d4f3c$var$loadBackground(element, backgroundAttr); - if (loadFunction) return loadFunction(element, assetAttr, assetAlt); - throw new Error(`Invalid element type: ${elementType}`); + const assetLoader = assetLoaders[elementType]; + const assetPath = element.getAttribute(tag); + const assetAltValue = element.getAttribute(altAttr); + assetLoader(element, assetPath, assetAltValue); }; var $f85e789b098d4f3c$export$2e2bcd8739ae039 = $f85e789b098d4f3c$var$loadAsset; @@ -102,18 +107,17 @@ var $f85e789b098d4f3c$export$2e2bcd8739ae039 = $f85e789b098d4f3c$var$loadAsset; /** * Lazy load assets. * - * @param {string} [selector="[lazy]"] - The CSS selector for lazy loadable elements. - * @param {Object} [settings={}] - Additional options for configuring the lazy loading behavior. - */ const $cf838c15c8b009ba$var$lazyLoad = (settings = {})=>{ + * @param {Object} [customOptions={}] - Additional options for configuring the lazy loading behavior. + */ const $cf838c15c8b009ba$var$lazyLoad = (tag = "lazy", customOptions = {})=>{ + (0, $50e97065b94a2e88$export$2e2bcd8739ae039).tag = tag; /** * Options object for configuring the lazy loading behavior. * * @type {Object} */ const options = { ...(0, $50e97065b94a2e88$export$2e2bcd8739ae039), - ...settings + ...customOptions }; - const { onLoaded: onLoaded, onError: onError, selector: selector } = options; /** * Handles the intersection of lazy load elements. * @@ -123,13 +127,13 @@ var $f85e789b098d4f3c$export$2e2bcd8739ae039 = $f85e789b098d4f3c$var$loadAsset; * @param {IntersectionObserver} observer - The intersection observer instance. */ const handleIntersection = (entries, observer)=>{ const handler = (entry)=>{ - if (!entry.isIntersecting) return; - const { target: target } = entry; + const { target: target, isIntersecting: isIntersecting } = entry; + if (!isIntersecting) return; try { (0, $f85e789b098d4f3c$export$2e2bcd8739ae039)(target, options); - onLoaded(target); + options.onLoaded(target); } catch (error) { - onError(target, error); + options.onError(target, error); } finally{ observer.unobserve(target); // bunun tam testini yapmak lazim } @@ -145,7 +149,7 @@ var $f85e789b098d4f3c$export$2e2bcd8739ae039 = $f85e789b098d4f3c$var$loadAsset; * NodeList of lazy loadable elements. * * @type {NodeList} - */ const lazyLoadItems = document.querySelectorAll(selector); + */ const lazyLoadItems = document.querySelectorAll(options.selector); lazyLoadItems.forEach((item)=>observer.observe(item)); }; var $cf838c15c8b009ba$export$2e2bcd8739ae039 = $cf838c15c8b009ba$var$lazyLoad; diff --git a/dist/lazy-load.js.map b/dist/lazy-load.js.map index f204da5..870f933 100644 --- a/dist/lazy-load.js.map +++ b/dist/lazy-load.js.map @@ -1 +1 @@ -{"mappings":"AAAA;;;;;;;;ACAA;;;;;;;;;;CAUC,GACD,MAAM,gCAAU;IACd,KAAK;IACL,UAAU;IACV,aAAa;IACb,UAAU,KAAO;IACjB,SAAS,CAAC,SAAS;QACjB,QAAQ,MAAM,2CAAiC,SAAS;IAC1D;IACA,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;IAEA,2CAAe;;CDlBd;AERD;;;;;;;;CAQC,GACD,MAAM,kCAAY,CAAC,SAAS,KAAK;IAC/B,QAAQ,MAAM;IACd,QAAQ,MAAM;AAChB;AAEA,MAAM,uCAAiB,CAAC,SAAS;IAC/B,QAAQ,MAAM,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1C;AAEA;;;;;;;;CAQC,GACD,MAAM,oCAAc,CAAC,SAAS,KAAK;IACjC,IAAI,MAAM,QAAQ,cAAc;IAEhC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,OAAO;IACjB;IAEA,gCAAU,KAAK,KAAK;AACtB;AAEA;;;;;;;CAOC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM;AAChB;AAEA;;;;;;CAMC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,MAAM,OAAE,GAAG,EAAE,GAAG;IAEhB,MAAM,gBAAgB;QACpB,KAAK;QACL,SAAS;QACT,OAAO;IACT;IAEA,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,eAAe,aAAa,CAAC,YAAY;IAE/C,MAAM,YAAY,QAAQ,aAAa,CAAC,EAAE,IAAI,IAAI,CAAC;IACnD,MAAM,WAAW,QAAQ,aAAa,CAAC,EAAE,IAAI,IAAI,CAAC,KAAK;IACvD,MAAM,iBAAiB,QAAQ,aAAa,CAAC,EAAE,IAAI,WAAW,CAAC;IAE/D,IAAI,gBAAgB,OAAO,qCAAe,SAAS;IACnD,IAAI,cAAc,OAAO,aAAa,SAAS,WAAW;IAE1D,MAAM,IAAI,MAAM,CAAC,sBAAsB,EAAE,YAAY,CAAC;AACxD;IAEA,2CAAe;;;AFlEf;;;;;CAKC,GACD,MAAM,iCAAW,CAAC,WAAW,CAAC,CAAC;IAC7B;;;;GAIC,GACD,MAAM,UAAU;QAAE,GAAG,CAAA,GAAA,wCAAa,CAAC;QAAE,GAAG,QAAQ;IAAC;IACjD,MAAM,YAAE,QAAQ,WAAE,OAAO,YAAE,QAAQ,EAAE,GAAG;IAExC;;;;;;;GAOC,GACD,MAAM,qBAAqB,CAAC,SAAS;QACnC,MAAM,UAAU,CAAC;YACf,IAAI,CAAC,MAAM,gBAAgB;YAC3B,MAAM,UAAE,MAAM,EAAE,GAAG;YAEnB,IAAI;gBACF,CAAA,GAAA,wCAAQ,EAAE,QAAQ;gBAClB,SAAS;YACX,EAAE,OAAO,OAAO;gBACd,QAAQ,QAAQ;YAClB,SAAU;gBACR,SAAS,UAAU,SAAS,iCAAiC;YAC/D;QACF;QAEA,QAAQ,QAAQ;IAClB;IAEA;;;;GAIC,GACD,MAAM,WAAW,IAAI,qBACnB,oBACA,QAAQ;IAGV;;;;GAIC,GACD,MAAM,gBAAgB,SAAS,iBAAiB;IAEhD,cAAc,QAAQ,CAAC,OAAS,SAAS,QAAQ;AACnD;IAEA,2CAAe","sources":["src/index.js","src/options.js","src/assetLoader.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.6\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './options.js';\nimport loadAsset from './assetLoader.js';\n\n/**\n * Lazy load assets.\n *\n * @param {string} [selector=\"[lazy]\"] - The CSS selector for lazy loadable elements.\n * @param {Object} [settings={}] - Additional options for configuring the lazy loading behavior.\n */\nconst lazyLoad = (settings = {}) => {\n /**\n * Options object for configuring the lazy loading behavior.\n *\n * @type {Object}\n */\n const options = { ...defaultOptions, ...settings };\n const { onLoaded, onError, selector } = options;\n\n /**\n * Handles the intersection of lazy load elements.\n *\n * @private\n *\n * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer.\n * @param {IntersectionObserver} observer - The intersection observer instance.\n */\n const handleIntersection = (entries, observer) => {\n const handler = (entry) => {\n if (!entry.isIntersecting) return;\n const { target } = entry;\n\n try {\n loadAsset(target, options);\n onLoaded(target);\n } catch (error) {\n onError(target, error);\n } finally {\n observer.unobserve(target); // bunun tam testini yapmak lazim\n }\n };\n\n entries.forEach(handler);\n };\n\n /**\n * IntersectionObserver used for lazy loading.\n *\n * @type {IntersectionObserver}\n */\n const observer = new IntersectionObserver(\n handleIntersection,\n options.observer\n );\n\n /**\n * NodeList of lazy loadable elements.\n *\n * @type {NodeList}\n */\n const lazyLoadItems = document.querySelectorAll(selector);\n\n lazyLoadItems.forEach((item) => observer.observe(item));\n};\n\nexport default lazyLoad;\n","/**\n * Default options for lazy loading behavior.\n *\n * @type {Object}\n *\n * @param {string} [tag=selector] - The CSS selector for lazy loadable elements.\n * @param {string} [toggleClass=\"-loaded\"] - The class name to toggle on elements after loading.\n * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded.\n * @param {Function} [onError] - Callback function to execute when an error occurs during loading.\n * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading.\n */\nconst options = {\n tag: 'lazy',\n selector: '[lazy]',\n toggleClass: '-loaded',\n onLoaded: () => {},\n onError: (element, error) => {\n console.error('🚀 Error on ~ element, error:', element, error);\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px', // Burayı daha detalı araştırmam gerek\n },\n};\n\nexport default options;\n","/**\n * Loads the asset for the given image element.\n *\n * @private\n *\n * @param {HTMLImageElement} element - The image element to load the asset for.\n * @param {string} src - The asset path attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadImage = (element, src, alt) => {\n element.src = src;\n element.alt = alt;\n};\n\nconst loadBackground = (element, src) => {\n element.style.background = `url(${src})`;\n};\n\n/**\n * Loads the asset for the given picture element.\n *\n * @private\n *\n * @param {HTMLPictureElement} element - The picture element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadPicture = (element, src, alt) => {\n let img = element.querySelector('img');\n\n if (!img) {\n img = document.createElement('img');\n element.append(img);\n }\n\n loadImage(img, src, alt);\n};\n\n/**\n * Loads the asset for the given video element.\n *\n * @private\n *\n * @param {HTMLVideoElement} element - The video element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n */\nconst loadVideo = (element, src) => {\n element.src = src;\n};\n\n/**\n * Loads the asset for the given element based on its type (img, picture, video).\n *\n * @private\n *\n * @param {HTMLElement} element - The element to load the asset for.\n */\nconst loadAsset = (element, options) => {\n const { tag } = options;\n\n const loadFunctions = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n };\n\n const elementType = element.tagName.toLowerCase();\n const loadFunction = loadFunctions[elementType];\n\n const assetAttr = element.getAttribute(`${tag}-src`);\n const assetAlt = element.getAttribute(`${tag}-alt`) || '';\n const backgroundAttr = element.getAttribute(`${tag}-background`);\n\n if (backgroundAttr) return loadBackground(element, backgroundAttr);\n if (loadFunction) return loadFunction(element, assetAttr, assetAlt);\n\n throw new Error(`Invalid element type: ${elementType}`);\n};\n\nexport default loadAsset;\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file +{"mappings":"AAAA;;;;;;;;ACAA;;;;;;;;;;CAUC,GACD,MAAM,gCAAU;IACd,IAAI,YAAW;QACb,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB;IACA,IAAI,gBAAe;QACjB,OAAO,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC;IAC1B;IAEA,KAAK;IACL,WAAW;QACT,QAAQ;QACR,SAAS;IACX;IACA,UAAU,KAAO;IACjB,SAAS,CAAC,SAAS;QACjB,QAAQ,MAAM,2CAAiC,SAAS;IAC1D;IACA,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;IAEA,2CAAe;;CD3Bd;AERD;;;;;;;;CAQC,GACD,MAAM,kCAAY,CAAC,SAAS,KAAK,MAAM,IAAI;IACzC,QAAQ,MAAM;IACd,IAAI,KAAK,QAAQ,MAAM;AACzB;AAEA,MAAM,uCAAiB,CAAC,SAAS;IAC/B,QAAQ,MAAM,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1C;AAEA;;;;;;;;CAQC,GACD,MAAM,oCAAc,CAAC,SAAS,KAAK;IACjC,IAAI,MAAM,QAAQ,cAAc;IAEhC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,OAAO;IACjB;IAEA,gCAAU,KAAK,KAAK;AACtB;AAEA;;;;;;;CAOC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM;AAChB;AAEA;;;;;;CAMC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,MAAM,OAAE,GAAG,WAAE,OAAO,EAAE,GAAG;IAEzB,MAAM,eAAe;QACnB,KAAK;QACL,SAAS;QACT,OAAO;IACT;IAEA,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,cAAc,YAAY,CAAC,YAAY;IAE7C,MAAM,YAAY,QAAQ,aAAa;IACvC,MAAM,gBAAgB,QAAQ,aAAa;IAE3C,YAAY,SAAS,WAAW;AAClC;IAEA,2CAAe;;;AF9Df;;;;CAIC,GACD,MAAM,iCAAW,CAAC,MAAM,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACjD,CAAA,GAAA,wCAAa,EAAE,MAAM;IACpB;;;;GAIC,GACD,MAAM,UAAU;QAAE,GAAG,CAAA,GAAA,wCAAa,CAAC;QAAE,GAAG,aAAa;IAAC;IAEtD;;;;;;;GAOC,GACD,MAAM,qBAAqB,CAAC,SAAS;QACnC,MAAM,UAAU,CAAC;YACf,MAAM,UAAE,MAAM,kBAAE,cAAc,EAAE,GAAG;YACnC,IAAI,CAAC,gBAAgB;YAErB,IAAI;gBACF,CAAA,GAAA,wCAAQ,EAAE,QAAQ;gBAClB,QAAQ,SAAS;YACnB,EAAE,OAAO,OAAO;gBACd,QAAQ,QAAQ,QAAQ;YAC1B,SAAU;gBACR,SAAS,UAAU,SAAS,iCAAiC;YAC/D;QACF;QAEA,QAAQ,QAAQ;IAClB;IAEA;;;;GAIC,GACD,MAAM,WAAW,IAAI,qBACnB,oBACA,QAAQ;IAGV;;;;GAIC,GACD,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ;IAExD,cAAc,QAAQ,CAAC,OAAS,SAAS,QAAQ;AACnD;IAEA,2CAAe","sources":["src/index.js","src/options.js","src/assetLoader.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.6\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './options.js';\nimport loadAsset from './assetLoader.js';\n\n/**\n * Lazy load assets.\n *\n * @param {Object} [customOptions={}] - Additional options for configuring the lazy loading behavior.\n */\nconst lazyLoad = (tag = 'lazy', customOptions = {}) => {\n\tdefaultOptions.tag = tag;\n /**\n * Options object for configuring the lazy loading behavior.\n *\n * @type {Object}\n */\n const options = { ...defaultOptions, ...customOptions };\n\n /**\n * Handles the intersection of lazy load elements.\n *\n * @private\n *\n * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer.\n * @param {IntersectionObserver} observer - The intersection observer instance.\n */\n const handleIntersection = (entries, observer) => {\n const handler = (entry) => {\n const { target, isIntersecting } = entry;\n if (!isIntersecting) return;\n\n try {\n loadAsset(target, options);\n options.onLoaded(target);\n } catch (error) {\n options.onError(target, error);\n } finally {\n observer.unobserve(target); // bunun tam testini yapmak lazim\n }\n };\n\n entries.forEach(handler);\n };\n\n /**\n * IntersectionObserver used for lazy loading.\n *\n * @type {IntersectionObserver}\n */\n const observer = new IntersectionObserver(\n handleIntersection,\n options.observer\n );\n\n /**\n * NodeList of lazy loadable elements.\n *\n * @type {NodeList}\n */\n const lazyLoadItems = document.querySelectorAll(options.selector);\n\n lazyLoadItems.forEach((item) => observer.observe(item));\n};\n\nexport default lazyLoad;\n","/**\n * Default options for lazy loading behavior.\n *\n * @type {Object}\n *\n * @param {string} [tag=selector] - The CSS selector for lazy loadable elements.\n * @param {string} [toggleClass=\"-loaded\"] - The class name to toggle on elements after loading.\n * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded.\n * @param {Function} [onError] - Callback function to execute when an error occurs during loading.\n * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading.\n */\nconst options = {\n get selector() {\n return `[${this.tag}]`;\n },\n get altAttribute() {\n return `${this.tag}-alt`;\n },\n\n tag: null,\n modifiers: {\n loaded: '-loaded',\n loading: '-loading',\n },\n onLoaded: () => {},\n onError: (element, error) => {\n console.error('🚀 Error on ~ element, error:', element, error);\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n};\n\nexport default options;\n","/**\n * Loads the asset for the given image element.\n *\n * @private\n *\n * @param {HTMLImageElement} element - The image element to load the asset for.\n * @param {string} src - The asset path attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadImage = (element, src, alt = null) => {\n element.src = src;\n if (alt) element.alt = alt;\n};\n\nconst loadBackground = (element, src) => {\n element.style.background = `url(${src})`;\n};\n\n/**\n * Loads the asset for the given picture element.\n *\n * @private\n *\n * @param {HTMLPictureElement} element - The picture element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadPicture = (element, src, alt) => {\n let img = element.querySelector('img');\n\n if (!img) {\n img = document.createElement('img');\n element.append(img);\n }\n\n loadImage(img, src, alt);\n};\n\n/**\n * Loads the asset for the given video element.\n *\n * @private\n *\n * @param {HTMLVideoElement} element - The video element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n */\nconst loadVideo = (element, src) => {\n element.src = src;\n};\n\n/**\n * Loads the asset for the given element based on its type (img, picture, video).\n *\n * @private\n *\n * @param {HTMLElement} element - The element to load the asset for.\n */\nconst loadAsset = (element, options) => {\n const { tag, altAttr } = options;\n\n const assetLoaders = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n };\n\n const elementType = element.tagName.toLowerCase();\n const assetLoader = assetLoaders[elementType];\n\n const assetPath = element.getAttribute(tag);\n const assetAltValue = element.getAttribute(altAttr);\n\n assetLoader(element, assetPath, assetAltValue);\n};\n\nexport default loadAsset;\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file diff --git a/src/index.js b/src/index.js index 35ee068..1b20771 100644 --- a/src/index.js +++ b/src/index.js @@ -16,7 +16,9 @@ import loadAsset from './assetLoader.js'; * * @param {Object} [customOptions={}] - Additional options for configuring the lazy loading behavior. */ -const lazyLoad = (customOptions = {}) => { +const lazyLoad = (tag = 'lazy', customOptions = {}) => { + defaultOptions.tag = tag; + /** * Options object for configuring the lazy loading behavior. * diff --git a/src/options.js b/src/options.js index 23d1100..0bf792b 100644 --- a/src/options.js +++ b/src/options.js @@ -17,7 +17,7 @@ const options = { return `${this.tag}-alt`; }, - tag: 'lazy', + tag: null, modifiers: { loaded: '-loaded', loading: '-loading', From 061c4d07c1d064c5cd18e4986ada2398e110d094 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 4 Nov 2023 21:58:23 +0300 Subject: [PATCH 052/185] Add: error logging to lazyLoad function --- src/index.js | 1 + 1 file changed, 1 insertion(+) diff --git a/src/index.js b/src/index.js index 1b20771..67fce4d 100644 --- a/src/index.js +++ b/src/index.js @@ -44,6 +44,7 @@ const lazyLoad = (tag = 'lazy', customOptions = {}) => { options.onLoaded(target); } catch (error) { options.onError(target, error); + console.error(error); } finally { observer.unobserve(target); // bunun tam testini yapmak lazim } From 074c33f61487ba6ef1fa2158ecf6e8393348ff98 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 4 Nov 2023 21:58:31 +0300 Subject: [PATCH 053/185] Fix lazyLoad function call in index.js --- test/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/index.js b/test/index.js index 8b6e86a..b39ccf1 100644 --- a/test/index.js +++ b/test/index.js @@ -1,5 +1,5 @@ import lazyLoad from '/dist/lazy-load.js'; -lazyLoad({ +lazyLoad('lazy', { onLoaded: (element) => console.log(element), -}); +}); \ No newline at end of file From 962a01599b79c28256d15f20bde2d1565e6a9996 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 4 Nov 2023 21:58:36 +0300 Subject: [PATCH 054/185] Add error logging to lazy-load.js --- dist/lazy-load.js | 1 + dist/lazy-load.js.map | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index 06a8ae9..d2332f0 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -134,6 +134,7 @@ var $f85e789b098d4f3c$export$2e2bcd8739ae039 = $f85e789b098d4f3c$var$loadAsset; options.onLoaded(target); } catch (error) { options.onError(target, error); + console.error(error); } finally{ observer.unobserve(target); // bunun tam testini yapmak lazim } diff --git a/dist/lazy-load.js.map b/dist/lazy-load.js.map index 870f933..9ca6460 100644 --- a/dist/lazy-load.js.map +++ b/dist/lazy-load.js.map @@ -1 +1 @@ -{"mappings":"AAAA;;;;;;;;ACAA;;;;;;;;;;CAUC,GACD,MAAM,gCAAU;IACd,IAAI,YAAW;QACb,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB;IACA,IAAI,gBAAe;QACjB,OAAO,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC;IAC1B;IAEA,KAAK;IACL,WAAW;QACT,QAAQ;QACR,SAAS;IACX;IACA,UAAU,KAAO;IACjB,SAAS,CAAC,SAAS;QACjB,QAAQ,MAAM,2CAAiC,SAAS;IAC1D;IACA,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;IAEA,2CAAe;;CD3Bd;AERD;;;;;;;;CAQC,GACD,MAAM,kCAAY,CAAC,SAAS,KAAK,MAAM,IAAI;IACzC,QAAQ,MAAM;IACd,IAAI,KAAK,QAAQ,MAAM;AACzB;AAEA,MAAM,uCAAiB,CAAC,SAAS;IAC/B,QAAQ,MAAM,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1C;AAEA;;;;;;;;CAQC,GACD,MAAM,oCAAc,CAAC,SAAS,KAAK;IACjC,IAAI,MAAM,QAAQ,cAAc;IAEhC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,OAAO;IACjB;IAEA,gCAAU,KAAK,KAAK;AACtB;AAEA;;;;;;;CAOC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM;AAChB;AAEA;;;;;;CAMC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,MAAM,OAAE,GAAG,WAAE,OAAO,EAAE,GAAG;IAEzB,MAAM,eAAe;QACnB,KAAK;QACL,SAAS;QACT,OAAO;IACT;IAEA,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,cAAc,YAAY,CAAC,YAAY;IAE7C,MAAM,YAAY,QAAQ,aAAa;IACvC,MAAM,gBAAgB,QAAQ,aAAa;IAE3C,YAAY,SAAS,WAAW;AAClC;IAEA,2CAAe;;;AF9Df;;;;CAIC,GACD,MAAM,iCAAW,CAAC,MAAM,MAAM,EAAE,gBAAgB,CAAC,CAAC;IACjD,CAAA,GAAA,wCAAa,EAAE,MAAM;IACpB;;;;GAIC,GACD,MAAM,UAAU;QAAE,GAAG,CAAA,GAAA,wCAAa,CAAC;QAAE,GAAG,aAAa;IAAC;IAEtD;;;;;;;GAOC,GACD,MAAM,qBAAqB,CAAC,SAAS;QACnC,MAAM,UAAU,CAAC;YACf,MAAM,UAAE,MAAM,kBAAE,cAAc,EAAE,GAAG;YACnC,IAAI,CAAC,gBAAgB;YAErB,IAAI;gBACF,CAAA,GAAA,wCAAQ,EAAE,QAAQ;gBAClB,QAAQ,SAAS;YACnB,EAAE,OAAO,OAAO;gBACd,QAAQ,QAAQ,QAAQ;YAC1B,SAAU;gBACR,SAAS,UAAU,SAAS,iCAAiC;YAC/D;QACF;QAEA,QAAQ,QAAQ;IAClB;IAEA;;;;GAIC,GACD,MAAM,WAAW,IAAI,qBACnB,oBACA,QAAQ;IAGV;;;;GAIC,GACD,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ;IAExD,cAAc,QAAQ,CAAC,OAAS,SAAS,QAAQ;AACnD;IAEA,2CAAe","sources":["src/index.js","src/options.js","src/assetLoader.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.6\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './options.js';\nimport loadAsset from './assetLoader.js';\n\n/**\n * Lazy load assets.\n *\n * @param {Object} [customOptions={}] - Additional options for configuring the lazy loading behavior.\n */\nconst lazyLoad = (tag = 'lazy', customOptions = {}) => {\n\tdefaultOptions.tag = tag;\n /**\n * Options object for configuring the lazy loading behavior.\n *\n * @type {Object}\n */\n const options = { ...defaultOptions, ...customOptions };\n\n /**\n * Handles the intersection of lazy load elements.\n *\n * @private\n *\n * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer.\n * @param {IntersectionObserver} observer - The intersection observer instance.\n */\n const handleIntersection = (entries, observer) => {\n const handler = (entry) => {\n const { target, isIntersecting } = entry;\n if (!isIntersecting) return;\n\n try {\n loadAsset(target, options);\n options.onLoaded(target);\n } catch (error) {\n options.onError(target, error);\n } finally {\n observer.unobserve(target); // bunun tam testini yapmak lazim\n }\n };\n\n entries.forEach(handler);\n };\n\n /**\n * IntersectionObserver used for lazy loading.\n *\n * @type {IntersectionObserver}\n */\n const observer = new IntersectionObserver(\n handleIntersection,\n options.observer\n );\n\n /**\n * NodeList of lazy loadable elements.\n *\n * @type {NodeList}\n */\n const lazyLoadItems = document.querySelectorAll(options.selector);\n\n lazyLoadItems.forEach((item) => observer.observe(item));\n};\n\nexport default lazyLoad;\n","/**\n * Default options for lazy loading behavior.\n *\n * @type {Object}\n *\n * @param {string} [tag=selector] - The CSS selector for lazy loadable elements.\n * @param {string} [toggleClass=\"-loaded\"] - The class name to toggle on elements after loading.\n * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded.\n * @param {Function} [onError] - Callback function to execute when an error occurs during loading.\n * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading.\n */\nconst options = {\n get selector() {\n return `[${this.tag}]`;\n },\n get altAttribute() {\n return `${this.tag}-alt`;\n },\n\n tag: null,\n modifiers: {\n loaded: '-loaded',\n loading: '-loading',\n },\n onLoaded: () => {},\n onError: (element, error) => {\n console.error('🚀 Error on ~ element, error:', element, error);\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n};\n\nexport default options;\n","/**\n * Loads the asset for the given image element.\n *\n * @private\n *\n * @param {HTMLImageElement} element - The image element to load the asset for.\n * @param {string} src - The asset path attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadImage = (element, src, alt = null) => {\n element.src = src;\n if (alt) element.alt = alt;\n};\n\nconst loadBackground = (element, src) => {\n element.style.background = `url(${src})`;\n};\n\n/**\n * Loads the asset for the given picture element.\n *\n * @private\n *\n * @param {HTMLPictureElement} element - The picture element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadPicture = (element, src, alt) => {\n let img = element.querySelector('img');\n\n if (!img) {\n img = document.createElement('img');\n element.append(img);\n }\n\n loadImage(img, src, alt);\n};\n\n/**\n * Loads the asset for the given video element.\n *\n * @private\n *\n * @param {HTMLVideoElement} element - The video element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n */\nconst loadVideo = (element, src) => {\n element.src = src;\n};\n\n/**\n * Loads the asset for the given element based on its type (img, picture, video).\n *\n * @private\n *\n * @param {HTMLElement} element - The element to load the asset for.\n */\nconst loadAsset = (element, options) => {\n const { tag, altAttr } = options;\n\n const assetLoaders = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n };\n\n const elementType = element.tagName.toLowerCase();\n const assetLoader = assetLoaders[elementType];\n\n const assetPath = element.getAttribute(tag);\n const assetAltValue = element.getAttribute(altAttr);\n\n assetLoader(element, assetPath, assetAltValue);\n};\n\nexport default loadAsset;\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file +{"mappings":"AAAA;;;;;;;;ACAA;;;;;;;;;;CAUC,GACD,MAAM,gCAAU;IACd,IAAI,YAAW;QACb,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB;IACA,IAAI,gBAAe;QACjB,OAAO,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC;IAC1B;IAEA,KAAK;IACL,WAAW;QACT,QAAQ;QACR,SAAS;IACX;IACA,UAAU,KAAO;IACjB,SAAS,CAAC,SAAS;QACjB,QAAQ,MAAM,2CAAiC,SAAS;IAC1D;IACA,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;IAEA,2CAAe;;CD3Bd;AERD;;;;;;;;CAQC,GACD,MAAM,kCAAY,CAAC,SAAS,KAAK,MAAM,IAAI;IACzC,QAAQ,MAAM;IACd,IAAI,KAAK,QAAQ,MAAM;AACzB;AAEA,MAAM,uCAAiB,CAAC,SAAS;IAC/B,QAAQ,MAAM,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1C;AAEA;;;;;;;;CAQC,GACD,MAAM,oCAAc,CAAC,SAAS,KAAK;IACjC,IAAI,MAAM,QAAQ,cAAc;IAEhC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,OAAO;IACjB;IAEA,gCAAU,KAAK,KAAK;AACtB;AAEA;;;;;;;CAOC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM;AAChB;AAEA;;;;;;CAMC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,MAAM,OAAE,GAAG,WAAE,OAAO,EAAE,GAAG;IAEzB,MAAM,eAAe;QACnB,KAAK;QACL,SAAS;QACT,OAAO;IACT;IAEA,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,cAAc,YAAY,CAAC,YAAY;IAE7C,MAAM,YAAY,QAAQ,aAAa;IACvC,MAAM,gBAAgB,QAAQ,aAAa;IAE3C,YAAY,SAAS,WAAW;AAClC;IAEA,2CAAe;;;AF9Df;;;;CAIC,GACD,MAAM,iCAAW,CAAC,MAAM,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAChD,CAAA,GAAA,wCAAa,EAAE,MAAM;IAErB;;;;GAIC,GACD,MAAM,UAAU;QAAE,GAAG,CAAA,GAAA,wCAAa,CAAC;QAAE,GAAG,aAAa;IAAC;IAEtD;;;;;;;GAOC,GACD,MAAM,qBAAqB,CAAC,SAAS;QACnC,MAAM,UAAU,CAAC;YACf,MAAM,UAAE,MAAM,kBAAE,cAAc,EAAE,GAAG;YACnC,IAAI,CAAC,gBAAgB;YAErB,IAAI;gBACF,CAAA,GAAA,wCAAQ,EAAE,QAAQ;gBAClB,QAAQ,SAAS;YACnB,EAAE,OAAO,OAAO;gBACd,QAAQ,QAAQ,QAAQ;gBACxB,QAAQ,MAAM;YAChB,SAAU;gBACR,SAAS,UAAU,SAAS,iCAAiC;YAC/D;QACF;QAEA,QAAQ,QAAQ;IAClB;IAEA;;;;GAIC,GACD,MAAM,WAAW,IAAI,qBACnB,oBACA,QAAQ;IAGV;;;;GAIC,GACD,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ;IAExD,cAAc,QAAQ,CAAC,OAAS,SAAS,QAAQ;AACnD;IAEA,2CAAe","sources":["src/index.js","src/options.js","src/assetLoader.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.6\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './options.js';\nimport loadAsset from './assetLoader.js';\n\n/**\n * Lazy load assets.\n *\n * @param {Object} [customOptions={}] - Additional options for configuring the lazy loading behavior.\n */\nconst lazyLoad = (tag = 'lazy', customOptions = {}) => {\n defaultOptions.tag = tag;\n\n /**\n * Options object for configuring the lazy loading behavior.\n *\n * @type {Object}\n */\n const options = { ...defaultOptions, ...customOptions };\n\n /**\n * Handles the intersection of lazy load elements.\n *\n * @private\n *\n * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer.\n * @param {IntersectionObserver} observer - The intersection observer instance.\n */\n const handleIntersection = (entries, observer) => {\n const handler = (entry) => {\n const { target, isIntersecting } = entry;\n if (!isIntersecting) return;\n\n try {\n loadAsset(target, options);\n options.onLoaded(target);\n } catch (error) {\n options.onError(target, error);\n console.error(error);\n } finally {\n observer.unobserve(target); // bunun tam testini yapmak lazim\n }\n };\n\n entries.forEach(handler);\n };\n\n /**\n * IntersectionObserver used for lazy loading.\n *\n * @type {IntersectionObserver}\n */\n const observer = new IntersectionObserver(\n handleIntersection,\n options.observer\n );\n\n /**\n * NodeList of lazy loadable elements.\n *\n * @type {NodeList}\n */\n const lazyLoadItems = document.querySelectorAll(options.selector);\n\n lazyLoadItems.forEach((item) => observer.observe(item));\n};\n\nexport default lazyLoad;\n","/**\n * Default options for lazy loading behavior.\n *\n * @type {Object}\n *\n * @param {string} [tag=selector] - The CSS selector for lazy loadable elements.\n * @param {string} [toggleClass=\"-loaded\"] - The class name to toggle on elements after loading.\n * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded.\n * @param {Function} [onError] - Callback function to execute when an error occurs during loading.\n * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading.\n */\nconst options = {\n get selector() {\n return `[${this.tag}]`;\n },\n get altAttribute() {\n return `${this.tag}-alt`;\n },\n\n tag: null,\n modifiers: {\n loaded: '-loaded',\n loading: '-loading',\n },\n onLoaded: () => {},\n onError: (element, error) => {\n console.error('🚀 Error on ~ element, error:', element, error);\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n};\n\nexport default options;\n","/**\n * Loads the asset for the given image element.\n *\n * @private\n *\n * @param {HTMLImageElement} element - The image element to load the asset for.\n * @param {string} src - The asset path attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadImage = (element, src, alt = null) => {\n element.src = src;\n if (alt) element.alt = alt;\n};\n\nconst loadBackground = (element, src) => {\n element.style.background = `url(${src})`;\n};\n\n/**\n * Loads the asset for the given picture element.\n *\n * @private\n *\n * @param {HTMLPictureElement} element - The picture element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadPicture = (element, src, alt) => {\n let img = element.querySelector('img');\n\n if (!img) {\n img = document.createElement('img');\n element.append(img);\n }\n\n loadImage(img, src, alt);\n};\n\n/**\n * Loads the asset for the given video element.\n *\n * @private\n *\n * @param {HTMLVideoElement} element - The video element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n */\nconst loadVideo = (element, src) => {\n element.src = src;\n};\n\n/**\n * Loads the asset for the given element based on its type (img, picture, video).\n *\n * @private\n *\n * @param {HTMLElement} element - The element to load the asset for.\n */\nconst loadAsset = (element, options) => {\n const { tag, altAttr } = options;\n\n const assetLoaders = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n };\n\n const elementType = element.tagName.toLowerCase();\n const assetLoader = assetLoaders[elementType];\n\n const assetPath = element.getAttribute(tag);\n const assetAltValue = element.getAttribute(altAttr);\n\n assetLoader(element, assetPath, assetAltValue);\n};\n\nexport default loadAsset;\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file From a89f6ef3dd3722b8572557e8fb8b81f41dcb1b2b Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 4 Nov 2023 22:31:11 +0300 Subject: [PATCH 055/185] Delete: unused function --- src/assetLoader.js | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index 2e7a3d0..2b9f9d9 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -12,10 +12,6 @@ const loadImage = (element, src, alt = null) => { if (alt) element.alt = alt; }; -const loadBackground = (element, src) => { - element.style.background = `url(${src})`; -}; - /** * Loads the asset for the given picture element. * From 659c5d3e932dd9ea45a231e3148fde3c6efe8d9c Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 4 Nov 2023 22:51:33 +0300 Subject: [PATCH 056/185] Fix: lazy loading bug and add console warning for --- src/index.js | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index 67fce4d..d95308d 100644 --- a/src/index.js +++ b/src/index.js @@ -41,7 +41,7 @@ const lazyLoad = (tag = 'lazy', customOptions = {}) => { try { loadAsset(target, options); - options.onLoaded(target); + options.onLoaded(target); } catch (error) { options.onError(target, error); console.error(error); @@ -70,6 +70,12 @@ const lazyLoad = (tag = 'lazy', customOptions = {}) => { */ const lazyLoadItems = document.querySelectorAll(options.selector); + + if (!lazyLoadItems.length) { + console.warn('🚀 No lazy loadable element found.'); + return; + } + lazyLoadItems.forEach((item) => observer.observe(item)); }; From 30dc872610e2b3b23586fdc97aba49ac5c124e13 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 4 Nov 2023 22:52:55 +0300 Subject: [PATCH 057/185] Delete: unnecessary code and console error --- src/index.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/index.js b/src/index.js index d95308d..7b503ad 100644 --- a/src/index.js +++ b/src/index.js @@ -41,10 +41,8 @@ const lazyLoad = (tag = 'lazy', customOptions = {}) => { try { loadAsset(target, options); - options.onLoaded(target); } catch (error) { options.onError(target, error); - console.error(error); } finally { observer.unobserve(target); // bunun tam testini yapmak lazim } From cf192824c58c212fd6a8545d5bf05cb87de9072c Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 4 Nov 2023 22:53:33 +0300 Subject: [PATCH 058/185] Add: onLoaded function to accept an element param --- src/options.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/options.js b/src/options.js index 0bf792b..cbe41f1 100644 --- a/src/options.js +++ b/src/options.js @@ -22,7 +22,7 @@ const options = { loaded: '-loaded', loading: '-loading', }, - onLoaded: () => {}, + onLoaded: (element) => {}, onError: (element, error) => { console.error('🚀 Error on ~ element, error:', element, error); }, From d07097ff1ec592815ffcf6154fd01d0072892cee Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 4 Nov 2023 22:56:31 +0300 Subject: [PATCH 059/185] Feature: loading state to assetLoader and handle load event --- src/assetLoader.js | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/assetLoader.js b/src/assetLoader.js index 2b9f9d9..86a833a 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -60,6 +60,13 @@ const loadAsset = (element, options) => { video: loadVideo, }; + const handleLoadEvent = () => { + element.classList.remove(options.modifiers.loading); + element.removeAttribute(options.tag); + element.classList.add(options.modifiers.loaded); + options.onLoaded(element); + }; + const elementType = element.tagName.toLowerCase(); const assetLoader = assetLoaders[elementType]; @@ -67,6 +74,8 @@ const loadAsset = (element, options) => { const assetAltValue = element.getAttribute(altAttr); assetLoader(element, assetPath, assetAltValue); + element.classList.add(options.modifiers.loading); + element.addEventListener('load', handleLoadEvent); }; export default loadAsset; From 5ad08c190b1599336cae2ed61dd1ad814c552bd5 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 4 Nov 2023 23:12:18 +0300 Subject: [PATCH 060/185] Update: Remove event listener for load event --- src/assetLoader.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/assetLoader.js b/src/assetLoader.js index 86a833a..bb8e4d1 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -65,6 +65,8 @@ const loadAsset = (element, options) => { element.removeAttribute(options.tag); element.classList.add(options.modifiers.loaded); options.onLoaded(element); + + element.removeEventListener('load', handleLoadEvent); }; const elementType = element.tagName.toLowerCase(); From cebd9765b56b598dc535d9a343e6ae91be05a477 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 4 Nov 2023 23:12:48 +0300 Subject: [PATCH 061/185] Update: lazy loading image size for observe load event --- test/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/index.html b/test/index.html index 0de0fd8..936bcae 100644 --- a/test/index.html +++ b/test/index.html @@ -10,7 +10,7 @@ - Random Image + Random Image Random Image Random Image Random Image From 7814c48bc0e1a39bc9d3ce9564e8ab6c1d722206 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 4 Nov 2023 23:13:54 +0300 Subject: [PATCH 062/185] Production --- dist/lazy-load.js | 55 ++++++++++++++++++++++++------------------- dist/lazy-load.js.map | 2 +- 2 files changed, 32 insertions(+), 25 deletions(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index d2332f0..f24bfb5 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -16,7 +16,7 @@ * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded. * @param {Function} [onError] - Callback function to execute when an error occurs during loading. * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. - */ const $50e97065b94a2e88$var$options = { + */ const $db127449446b8099$var$options = { get selector () { return `[${this.tag}]`; }, @@ -28,7 +28,7 @@ loaded: "-loaded", loading: "-loading" }, - onLoaded: ()=>{}, + onLoaded: (element)=>{}, onError: (element, error)=>{ console.error("\uD83D\uDE80 Error on ~ element, error:", element, error); }, @@ -38,7 +38,7 @@ rootMargin: "100% 0px" } }; -var $50e97065b94a2e88$export$2e2bcd8739ae039 = $50e97065b94a2e88$var$options; +var $db127449446b8099$export$2e2bcd8739ae039 = $db127449446b8099$var$options; /** @@ -49,13 +49,10 @@ var $50e97065b94a2e88$export$2e2bcd8739ae039 = $50e97065b94a2e88$var$options; * @param {HTMLImageElement} element - The image element to load the asset for. * @param {string} src - The asset path attribute value. * @param {string} alt - The asset alt attribute value. - */ const $f85e789b098d4f3c$var$loadImage = (element, src, alt = null)=>{ + */ const $fa423858cf60d4ae$var$loadImage = (element, src, alt = null)=>{ element.src = src; if (alt) element.alt = alt; }; -const $f85e789b098d4f3c$var$loadBackground = (element, src)=>{ - element.style.background = `url(${src})`; -}; /** * Loads the asset for the given picture element. * @@ -64,13 +61,13 @@ const $f85e789b098d4f3c$var$loadBackground = (element, src)=>{ * @param {HTMLPictureElement} element - The picture element to load the asset for. * @param {string} src - The asset URL attribute value. * @param {string} alt - The asset alt attribute value. - */ const $f85e789b098d4f3c$var$loadPicture = (element, src, alt)=>{ + */ const $fa423858cf60d4ae$var$loadPicture = (element, src, alt)=>{ let img = element.querySelector("img"); if (!img) { img = document.createElement("img"); element.append(img); } - $f85e789b098d4f3c$var$loadImage(img, src, alt); + $fa423858cf60d4ae$var$loadImage(img, src, alt); }; /** * Loads the asset for the given video element. @@ -79,7 +76,7 @@ const $f85e789b098d4f3c$var$loadBackground = (element, src)=>{ * * @param {HTMLVideoElement} element - The video element to load the asset for. * @param {string} src - The asset URL attribute value. - */ const $f85e789b098d4f3c$var$loadVideo = (element, src)=>{ + */ const $fa423858cf60d4ae$var$loadVideo = (element, src)=>{ element.src = src; }; /** @@ -88,34 +85,43 @@ const $f85e789b098d4f3c$var$loadBackground = (element, src)=>{ * @private * * @param {HTMLElement} element - The element to load the asset for. - */ const $f85e789b098d4f3c$var$loadAsset = (element, options)=>{ + */ const $fa423858cf60d4ae$var$loadAsset = (element, options)=>{ const { tag: tag, altAttr: altAttr } = options; const assetLoaders = { - img: $f85e789b098d4f3c$var$loadImage, - picture: $f85e789b098d4f3c$var$loadPicture, - video: $f85e789b098d4f3c$var$loadVideo + img: $fa423858cf60d4ae$var$loadImage, + picture: $fa423858cf60d4ae$var$loadPicture, + video: $fa423858cf60d4ae$var$loadVideo + }; + const handleLoadEvent = ()=>{ + element.classList.remove(options.modifiers.loading); + element.removeAttribute(options.tag); + element.classList.add(options.modifiers.loaded); + options.onLoaded(element); + element.removeEventListener("load", handleLoadEvent); }; const elementType = element.tagName.toLowerCase(); const assetLoader = assetLoaders[elementType]; const assetPath = element.getAttribute(tag); const assetAltValue = element.getAttribute(altAttr); assetLoader(element, assetPath, assetAltValue); + element.classList.add(options.modifiers.loading); + element.addEventListener("load", handleLoadEvent); }; -var $f85e789b098d4f3c$export$2e2bcd8739ae039 = $f85e789b098d4f3c$var$loadAsset; +var $fa423858cf60d4ae$export$2e2bcd8739ae039 = $fa423858cf60d4ae$var$loadAsset; /** * Lazy load assets. * * @param {Object} [customOptions={}] - Additional options for configuring the lazy loading behavior. - */ const $cf838c15c8b009ba$var$lazyLoad = (tag = "lazy", customOptions = {})=>{ - (0, $50e97065b94a2e88$export$2e2bcd8739ae039).tag = tag; + */ const $82cbb5a2f3a1bcd0$var$lazyLoad = (tag = "lazy", customOptions = {})=>{ + (0, $db127449446b8099$export$2e2bcd8739ae039).tag = tag; /** * Options object for configuring the lazy loading behavior. * * @type {Object} */ const options = { - ...(0, $50e97065b94a2e88$export$2e2bcd8739ae039), + ...(0, $db127449446b8099$export$2e2bcd8739ae039), ...customOptions }; /** @@ -130,11 +136,9 @@ var $f85e789b098d4f3c$export$2e2bcd8739ae039 = $f85e789b098d4f3c$var$loadAsset; const { target: target, isIntersecting: isIntersecting } = entry; if (!isIntersecting) return; try { - (0, $f85e789b098d4f3c$export$2e2bcd8739ae039)(target, options); - options.onLoaded(target); + (0, $fa423858cf60d4ae$export$2e2bcd8739ae039)(target, options); } catch (error) { options.onError(target, error); - console.error(error); } finally{ observer.unobserve(target); // bunun tam testini yapmak lazim } @@ -151,10 +155,13 @@ var $f85e789b098d4f3c$export$2e2bcd8739ae039 = $f85e789b098d4f3c$var$loadAsset; * * @type {NodeList} */ const lazyLoadItems = document.querySelectorAll(options.selector); + if (!lazyLoadItems.length) { + console.warn("\uD83D\uDE80 No lazy loadable element found."); + return; + } lazyLoadItems.forEach((item)=>observer.observe(item)); }; -var $cf838c15c8b009ba$export$2e2bcd8739ae039 = $cf838c15c8b009ba$var$lazyLoad; +var $82cbb5a2f3a1bcd0$export$2e2bcd8739ae039 = $82cbb5a2f3a1bcd0$var$lazyLoad; -export {$cf838c15c8b009ba$export$2e2bcd8739ae039 as default}; -//# sourceMappingURL=lazy-load.js.map +export {$82cbb5a2f3a1bcd0$export$2e2bcd8739ae039 as default}; diff --git a/dist/lazy-load.js.map b/dist/lazy-load.js.map index 9ca6460..4facd93 100644 --- a/dist/lazy-load.js.map +++ b/dist/lazy-load.js.map @@ -1 +1 @@ -{"mappings":"AAAA;;;;;;;;ACAA;;;;;;;;;;CAUC,GACD,MAAM,gCAAU;IACd,IAAI,YAAW;QACb,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB;IACA,IAAI,gBAAe;QACjB,OAAO,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC;IAC1B;IAEA,KAAK;IACL,WAAW;QACT,QAAQ;QACR,SAAS;IACX;IACA,UAAU,KAAO;IACjB,SAAS,CAAC,SAAS;QACjB,QAAQ,MAAM,2CAAiC,SAAS;IAC1D;IACA,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;IAEA,2CAAe;;CD3Bd;AERD;;;;;;;;CAQC,GACD,MAAM,kCAAY,CAAC,SAAS,KAAK,MAAM,IAAI;IACzC,QAAQ,MAAM;IACd,IAAI,KAAK,QAAQ,MAAM;AACzB;AAEA,MAAM,uCAAiB,CAAC,SAAS;IAC/B,QAAQ,MAAM,aAAa,CAAC,IAAI,EAAE,IAAI,CAAC,CAAC;AAC1C;AAEA;;;;;;;;CAQC,GACD,MAAM,oCAAc,CAAC,SAAS,KAAK;IACjC,IAAI,MAAM,QAAQ,cAAc;IAEhC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,OAAO;IACjB;IAEA,gCAAU,KAAK,KAAK;AACtB;AAEA;;;;;;;CAOC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM;AAChB;AAEA;;;;;;CAMC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,MAAM,OAAE,GAAG,WAAE,OAAO,EAAE,GAAG;IAEzB,MAAM,eAAe;QACnB,KAAK;QACL,SAAS;QACT,OAAO;IACT;IAEA,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,cAAc,YAAY,CAAC,YAAY;IAE7C,MAAM,YAAY,QAAQ,aAAa;IACvC,MAAM,gBAAgB,QAAQ,aAAa;IAE3C,YAAY,SAAS,WAAW;AAClC;IAEA,2CAAe;;;AF9Df;;;;CAIC,GACD,MAAM,iCAAW,CAAC,MAAM,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAChD,CAAA,GAAA,wCAAa,EAAE,MAAM;IAErB;;;;GAIC,GACD,MAAM,UAAU;QAAE,GAAG,CAAA,GAAA,wCAAa,CAAC;QAAE,GAAG,aAAa;IAAC;IAEtD;;;;;;;GAOC,GACD,MAAM,qBAAqB,CAAC,SAAS;QACnC,MAAM,UAAU,CAAC;YACf,MAAM,UAAE,MAAM,kBAAE,cAAc,EAAE,GAAG;YACnC,IAAI,CAAC,gBAAgB;YAErB,IAAI;gBACF,CAAA,GAAA,wCAAQ,EAAE,QAAQ;gBAClB,QAAQ,SAAS;YACnB,EAAE,OAAO,OAAO;gBACd,QAAQ,QAAQ,QAAQ;gBACxB,QAAQ,MAAM;YAChB,SAAU;gBACR,SAAS,UAAU,SAAS,iCAAiC;YAC/D;QACF;QAEA,QAAQ,QAAQ;IAClB;IAEA;;;;GAIC,GACD,MAAM,WAAW,IAAI,qBACnB,oBACA,QAAQ;IAGV;;;;GAIC,GACD,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ;IAExD,cAAc,QAAQ,CAAC,OAAS,SAAS,QAAQ;AACnD;IAEA,2CAAe","sources":["src/index.js","src/options.js","src/assetLoader.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.6\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './options.js';\nimport loadAsset from './assetLoader.js';\n\n/**\n * Lazy load assets.\n *\n * @param {Object} [customOptions={}] - Additional options for configuring the lazy loading behavior.\n */\nconst lazyLoad = (tag = 'lazy', customOptions = {}) => {\n defaultOptions.tag = tag;\n\n /**\n * Options object for configuring the lazy loading behavior.\n *\n * @type {Object}\n */\n const options = { ...defaultOptions, ...customOptions };\n\n /**\n * Handles the intersection of lazy load elements.\n *\n * @private\n *\n * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer.\n * @param {IntersectionObserver} observer - The intersection observer instance.\n */\n const handleIntersection = (entries, observer) => {\n const handler = (entry) => {\n const { target, isIntersecting } = entry;\n if (!isIntersecting) return;\n\n try {\n loadAsset(target, options);\n options.onLoaded(target);\n } catch (error) {\n options.onError(target, error);\n console.error(error);\n } finally {\n observer.unobserve(target); // bunun tam testini yapmak lazim\n }\n };\n\n entries.forEach(handler);\n };\n\n /**\n * IntersectionObserver used for lazy loading.\n *\n * @type {IntersectionObserver}\n */\n const observer = new IntersectionObserver(\n handleIntersection,\n options.observer\n );\n\n /**\n * NodeList of lazy loadable elements.\n *\n * @type {NodeList}\n */\n const lazyLoadItems = document.querySelectorAll(options.selector);\n\n lazyLoadItems.forEach((item) => observer.observe(item));\n};\n\nexport default lazyLoad;\n","/**\n * Default options for lazy loading behavior.\n *\n * @type {Object}\n *\n * @param {string} [tag=selector] - The CSS selector for lazy loadable elements.\n * @param {string} [toggleClass=\"-loaded\"] - The class name to toggle on elements after loading.\n * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded.\n * @param {Function} [onError] - Callback function to execute when an error occurs during loading.\n * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading.\n */\nconst options = {\n get selector() {\n return `[${this.tag}]`;\n },\n get altAttribute() {\n return `${this.tag}-alt`;\n },\n\n tag: null,\n modifiers: {\n loaded: '-loaded',\n loading: '-loading',\n },\n onLoaded: () => {},\n onError: (element, error) => {\n console.error('🚀 Error on ~ element, error:', element, error);\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n};\n\nexport default options;\n","/**\n * Loads the asset for the given image element.\n *\n * @private\n *\n * @param {HTMLImageElement} element - The image element to load the asset for.\n * @param {string} src - The asset path attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadImage = (element, src, alt = null) => {\n element.src = src;\n if (alt) element.alt = alt;\n};\n\nconst loadBackground = (element, src) => {\n element.style.background = `url(${src})`;\n};\n\n/**\n * Loads the asset for the given picture element.\n *\n * @private\n *\n * @param {HTMLPictureElement} element - The picture element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadPicture = (element, src, alt) => {\n let img = element.querySelector('img');\n\n if (!img) {\n img = document.createElement('img');\n element.append(img);\n }\n\n loadImage(img, src, alt);\n};\n\n/**\n * Loads the asset for the given video element.\n *\n * @private\n *\n * @param {HTMLVideoElement} element - The video element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n */\nconst loadVideo = (element, src) => {\n element.src = src;\n};\n\n/**\n * Loads the asset for the given element based on its type (img, picture, video).\n *\n * @private\n *\n * @param {HTMLElement} element - The element to load the asset for.\n */\nconst loadAsset = (element, options) => {\n const { tag, altAttr } = options;\n\n const assetLoaders = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n };\n\n const elementType = element.tagName.toLowerCase();\n const assetLoader = assetLoaders[elementType];\n\n const assetPath = element.getAttribute(tag);\n const assetAltValue = element.getAttribute(altAttr);\n\n assetLoader(element, assetPath, assetAltValue);\n};\n\nexport default loadAsset;\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file +{"mappings":"AAAA;;;;;;;;ACAA;;;;;;;;;;CAUC,GACD,MAAM,gCAAU;IACd,IAAI,YAAW;QACb,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB;IACA,IAAI,gBAAe;QACjB,OAAO,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC;IAC1B;IAEA,KAAK;IACL,WAAW;QACT,QAAQ;QACR,SAAS;IACX;IACA,UAAU,CAAC,WAAa;IACxB,SAAS,CAAC,SAAS;QACjB,QAAQ,MAAM,2CAAiC,SAAS;IAC1D;IACA,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;IAEA,2CAAe;;CD3Bd;AERD;;;;;;;;CAQC,GACD,MAAM,kCAAY,CAAC,SAAS,KAAK,MAAM,IAAI;IACzC,QAAQ,MAAM;IACd,IAAI,KAAK,QAAQ,MAAM;AACzB;AAEA;;;;;;;;CAQC,GACD,MAAM,oCAAc,CAAC,SAAS,KAAK;IACjC,IAAI,MAAM,QAAQ,cAAc;IAEhC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,OAAO;IACjB;IAEA,gCAAU,KAAK,KAAK;AACtB;AAEA;;;;;;;CAOC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM;AAChB;AAEA;;;;;;CAMC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,MAAM,OAAE,GAAG,WAAE,OAAO,EAAE,GAAG;IAEzB,MAAM,eAAe;QACnB,KAAK;QACL,SAAS;QACT,OAAO;IACT;IAEA,MAAM,kBAAkB;QACtB,QAAQ,UAAU,OAAO,QAAQ,UAAU;QAC3C,QAAQ,gBAAgB,QAAQ;QAChC,QAAQ,UAAU,IAAI,QAAQ,UAAU;QACxC,QAAQ,SAAS;QAEjB,QAAQ,oBAAoB,QAAQ;IACtC;IAEA,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,cAAc,YAAY,CAAC,YAAY;IAE7C,MAAM,YAAY,QAAQ,aAAa;IACvC,MAAM,gBAAgB,QAAQ,aAAa;IAE3C,YAAY,SAAS,WAAW;IAChC,QAAQ,UAAU,IAAI,QAAQ,UAAU;IACxC,QAAQ,iBAAiB,QAAQ;AACnC;IAEA,2CAAe;;;AFrEf;;;;CAIC,GACD,MAAM,iCAAW,CAAC,MAAM,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAChD,CAAA,GAAA,wCAAa,EAAE,MAAM;IAErB;;;;GAIC,GACD,MAAM,UAAU;QAAE,GAAG,CAAA,GAAA,wCAAa,CAAC;QAAE,GAAG,aAAa;IAAC;IAEtD;;;;;;;GAOC,GACD,MAAM,qBAAqB,CAAC,SAAS;QACnC,MAAM,UAAU,CAAC;YACf,MAAM,UAAE,MAAM,kBAAE,cAAc,EAAE,GAAG;YACnC,IAAI,CAAC,gBAAgB;YAErB,IAAI;gBACF,CAAA,GAAA,wCAAQ,EAAE,QAAQ;YACpB,EAAE,OAAO,OAAO;gBACd,QAAQ,QAAQ,QAAQ;YAC1B,SAAU;gBACR,SAAS,UAAU,SAAS,iCAAiC;YAC/D;QACF;QAEA,QAAQ,QAAQ;IAClB;IAEA;;;;GAIC,GACD,MAAM,WAAW,IAAI,qBACnB,oBACA,QAAQ;IAGV;;;;GAIC,GACD,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ;IAGxD,IAAI,CAAC,cAAc,QAAQ;QACzB,QAAQ,KAAK;QACb;IACF;IAEA,cAAc,QAAQ,CAAC,OAAS,SAAS,QAAQ;AACnD;IAEA,2CAAe","sources":["src/index.js","src/options.js","src/assetLoader.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.6\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './options.js';\nimport loadAsset from './assetLoader.js';\n\n/**\n * Lazy load assets.\n *\n * @param {Object} [customOptions={}] - Additional options for configuring the lazy loading behavior.\n */\nconst lazyLoad = (tag = 'lazy', customOptions = {}) => {\n defaultOptions.tag = tag;\n\n /**\n * Options object for configuring the lazy loading behavior.\n *\n * @type {Object}\n */\n const options = { ...defaultOptions, ...customOptions };\n\n /**\n * Handles the intersection of lazy load elements.\n *\n * @private\n *\n * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer.\n * @param {IntersectionObserver} observer - The intersection observer instance.\n */\n const handleIntersection = (entries, observer) => {\n const handler = (entry) => {\n const { target, isIntersecting } = entry;\n if (!isIntersecting) return;\n\n try {\n loadAsset(target, options);\n } catch (error) {\n options.onError(target, error);\n } finally {\n observer.unobserve(target); // bunun tam testini yapmak lazim\n }\n };\n\n entries.forEach(handler);\n };\n\n /**\n * IntersectionObserver used for lazy loading.\n *\n * @type {IntersectionObserver}\n */\n const observer = new IntersectionObserver(\n handleIntersection,\n options.observer\n );\n\n /**\n * NodeList of lazy loadable elements.\n *\n * @type {NodeList}\n */\n const lazyLoadItems = document.querySelectorAll(options.selector);\n\n\n if (!lazyLoadItems.length) {\n console.warn('🚀 No lazy loadable element found.');\n return;\n }\n\n lazyLoadItems.forEach((item) => observer.observe(item));\n};\n\nexport default lazyLoad;\n","/**\n * Default options for lazy loading behavior.\n *\n * @type {Object}\n *\n * @param {string} [tag=selector] - The CSS selector for lazy loadable elements.\n * @param {string} [toggleClass=\"-loaded\"] - The class name to toggle on elements after loading.\n * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded.\n * @param {Function} [onError] - Callback function to execute when an error occurs during loading.\n * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading.\n */\nconst options = {\n get selector() {\n return `[${this.tag}]`;\n },\n get altAttribute() {\n return `${this.tag}-alt`;\n },\n\n tag: null,\n modifiers: {\n loaded: '-loaded',\n loading: '-loading',\n },\n onLoaded: (element) => {},\n onError: (element, error) => {\n console.error('🚀 Error on ~ element, error:', element, error);\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n};\n\nexport default options;\n","/**\n * Loads the asset for the given image element.\n *\n * @private\n *\n * @param {HTMLImageElement} element - The image element to load the asset for.\n * @param {string} src - The asset path attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadImage = (element, src, alt = null) => {\n element.src = src;\n if (alt) element.alt = alt;\n};\n\n/**\n * Loads the asset for the given picture element.\n *\n * @private\n *\n * @param {HTMLPictureElement} element - The picture element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadPicture = (element, src, alt) => {\n let img = element.querySelector('img');\n\n if (!img) {\n img = document.createElement('img');\n element.append(img);\n }\n\n loadImage(img, src, alt);\n};\n\n/**\n * Loads the asset for the given video element.\n *\n * @private\n *\n * @param {HTMLVideoElement} element - The video element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n */\nconst loadVideo = (element, src) => {\n element.src = src;\n};\n\n/**\n * Loads the asset for the given element based on its type (img, picture, video).\n *\n * @private\n *\n * @param {HTMLElement} element - The element to load the asset for.\n */\nconst loadAsset = (element, options) => {\n const { tag, altAttr } = options;\n\n const assetLoaders = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n };\n\n const handleLoadEvent = () => {\n element.classList.remove(options.modifiers.loading);\n element.removeAttribute(options.tag);\n element.classList.add(options.modifiers.loaded);\n options.onLoaded(element);\n\n element.removeEventListener('load', handleLoadEvent);\n };\n\n const elementType = element.tagName.toLowerCase();\n const assetLoader = assetLoaders[elementType];\n\n const assetPath = element.getAttribute(tag);\n const assetAltValue = element.getAttribute(altAttr);\n\n assetLoader(element, assetPath, assetAltValue);\n element.classList.add(options.modifiers.loading);\n element.addEventListener('load', handleLoadEvent);\n};\n\nexport default loadAsset;\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file From ad9eb7815f6e427772f8ec7cc48074a6403d7314 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 4 Nov 2023 23:24:08 +0300 Subject: [PATCH 063/185] Refactor: assetLoader.js to use a map of asset loaders by element type. --- src/assetLoader.js | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index bb8e4d1..3e88d14 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -44,6 +44,22 @@ const loadVideo = (element, src) => { element.src = src; }; +/** + * A map of asset loaders by element type. + * + * @private + * + * @type {Object} + * @property {function} img - To load an image. + * @property {function} picture - To load a picture. + * @property {function} video - To load a video. + */ +const assetLoaders = { + img: loadImage, + picture: loadPicture, + video: loadVideo, +}; + /** * Loads the asset for the given element based on its type (img, picture, video). * @@ -54,12 +70,6 @@ const loadVideo = (element, src) => { const loadAsset = (element, options) => { const { tag, altAttr } = options; - const assetLoaders = { - img: loadImage, - picture: loadPicture, - video: loadVideo, - }; - const handleLoadEvent = () => { element.classList.remove(options.modifiers.loading); element.removeAttribute(options.tag); From cf711e7867780cc0eb08b2759248e6b4bb558550 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 4 Nov 2023 23:24:19 +0300 Subject: [PATCH 064/185] Refactor: lazy loading options in options.js. --- src/options.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/options.js b/src/options.js index cbe41f1..9bb904b 100644 --- a/src/options.js +++ b/src/options.js @@ -3,16 +3,21 @@ * * @type {Object} * - * @param {string} [tag=selector] - The CSS selector for lazy loadable elements. - * @param {string} [toggleClass="-loaded"] - The class name to toggle on elements after loading. - * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded. - * @param {Function} [onError] - Callback function to execute when an error occurs during loading. - * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. + * @property {Function} selector - Get the CSS selector for lazy loadable elements. + * @property {Function} altAttribute - Get the alternative attribute for lazy loadable elements. + * @property {string} [tag] - The CSS selector for lazy loadable elements. + * @property {Object} modifiers - The class names to toggle on elements. + * @property {string} modifiers.loaded - The class name to toggle on elements after loading. + * @property {string} modifiers.loading - The class name to toggle on elements while loading. + * @property {Function} [onLoaded] - Callback function to execute when an element is successfully loaded. + * @property {Function} [onError] - Callback function to execute when an error occurs during loading. + * @property {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. */ const options = { get selector() { return `[${this.tag}]`; }, + get altAttribute() { return `${this.tag}-alt`; }, From 9017d8b63316af66d4714c10ff3cfb28dbb28685 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 4 Nov 2023 23:31:53 +0300 Subject: [PATCH 065/185] Update: Options to settings --- src/assetLoader.js | 14 +++++++------- src/index.js | 20 ++++++++++---------- src/{options.js => settings.js} | 6 +++--- 3 files changed, 20 insertions(+), 20 deletions(-) rename src/{options.js => settings.js} (93%) diff --git a/src/assetLoader.js b/src/assetLoader.js index 3e88d14..3f2171a 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -67,14 +67,14 @@ const assetLoaders = { * * @param {HTMLElement} element - The element to load the asset for. */ -const loadAsset = (element, options) => { - const { tag, altAttr } = options; +const loadAsset = (element, settings) => { + const { tag, altAttr } = settings; const handleLoadEvent = () => { - element.classList.remove(options.modifiers.loading); - element.removeAttribute(options.tag); - element.classList.add(options.modifiers.loaded); - options.onLoaded(element); + element.classList.remove(settings.modifiers.loading); + element.removeAttribute(settings.tag); + element.classList.add(settings.modifiers.loaded); + settings.onLoaded(element); element.removeEventListener('load', handleLoadEvent); }; @@ -86,7 +86,7 @@ const loadAsset = (element, options) => { const assetAltValue = element.getAttribute(altAttr); assetLoader(element, assetPath, assetAltValue); - element.classList.add(options.modifiers.loading); + element.classList.add(settings.modifiers.loading); element.addEventListener('load', handleLoadEvent); }; diff --git a/src/index.js b/src/index.js index 7b503ad..e9e8229 100644 --- a/src/index.js +++ b/src/index.js @@ -8,23 +8,23 @@ * @see {@link https://github.com/drementer/lazy-load.js} */ -import defaultOptions from './options.js'; +import defaultSettings from './settings.js'; import loadAsset from './assetLoader.js'; /** * Lazy load assets. * - * @param {Object} [customOptions={}] - Additional options for configuring the lazy loading behavior. + * @param {Object} [customSettings={}] - Additional options for configuring the lazy loading behavior. */ -const lazyLoad = (tag = 'lazy', customOptions = {}) => { - defaultOptions.tag = tag; +const lazyLoad = (tag = 'lazy', customSettings = {}) => { + defaultSettings.tag = tag; /** - * Options object for configuring the lazy loading behavior. + * Settings object for configuring the lazy loading behavior. * * @type {Object} */ - const options = { ...defaultOptions, ...customOptions }; + const settings = { ...defaultSettings, ...customSettings }; /** * Handles the intersection of lazy load elements. @@ -40,9 +40,9 @@ const lazyLoad = (tag = 'lazy', customOptions = {}) => { if (!isIntersecting) return; try { - loadAsset(target, options); + loadAsset(target, settings); } catch (error) { - options.onError(target, error); + settings.onError(target, error); } finally { observer.unobserve(target); // bunun tam testini yapmak lazim } @@ -58,7 +58,7 @@ const lazyLoad = (tag = 'lazy', customOptions = {}) => { */ const observer = new IntersectionObserver( handleIntersection, - options.observer + settings.observer ); /** @@ -66,7 +66,7 @@ const lazyLoad = (tag = 'lazy', customOptions = {}) => { * * @type {NodeList} */ - const lazyLoadItems = document.querySelectorAll(options.selector); + const lazyLoadItems = document.querySelectorAll(settings.selector); if (!lazyLoadItems.length) { diff --git a/src/options.js b/src/settings.js similarity index 93% rename from src/options.js rename to src/settings.js index 9bb904b..bc4e565 100644 --- a/src/options.js +++ b/src/settings.js @@ -1,5 +1,5 @@ /** - * Default options for lazy loading behavior. + * Default settings for lazy loading behavior. * * @type {Object} * @@ -13,7 +13,7 @@ * @property {Function} [onError] - Callback function to execute when an error occurs during loading. * @property {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. */ -const options = { +const settings = { get selector() { return `[${this.tag}]`; }, @@ -38,4 +38,4 @@ const options = { }, }; -export default options; +export default settings; From c903ecf55f18189a404389ef5093fe0276311c06 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 5 Nov 2023 00:35:40 +0300 Subject: [PATCH 066/185] Fix: console error message in settings.js --- src/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings.js b/src/settings.js index bc4e565..714c398 100644 --- a/src/settings.js +++ b/src/settings.js @@ -29,7 +29,7 @@ const settings = { }, onLoaded: (element) => {}, onError: (element, error) => { - console.error('🚀 Error on ~ element, error:', element, error); + console.warn('Error on ~ element, error:', element, error); }, observer: { root: null, From 0af9b1ba44e37f3f1928c22624e11a182de3b5fc Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 5 Nov 2023 00:36:20 +0300 Subject: [PATCH 067/185] Add: Errorhandling --- src/assetLoader.js | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index 3f2171a..90f9e6a 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -55,9 +55,9 @@ const loadVideo = (element, src) => { * @property {function} video - To load a video. */ const assetLoaders = { - img: loadImage, - picture: loadPicture, - video: loadVideo, + img: loadImage, + picture: loadPicture, + video: loadVideo, }; /** @@ -79,11 +79,13 @@ const loadAsset = (element, settings) => { element.removeEventListener('load', handleLoadEvent); }; + const assetPath = element.getAttribute(tag); + const assetAltValue = element.getAttribute(altAttr); + const elementType = element.tagName.toLowerCase(); const assetLoader = assetLoaders[elementType]; - const assetPath = element.getAttribute(tag); - const assetAltValue = element.getAttribute(altAttr); + if (!assetLoader) throw new Error(`Element type '${elementType}' is not supported!`); assetLoader(element, assetPath, assetAltValue); element.classList.add(settings.modifiers.loading); From 019f17f0d20f64def661fd820f4e9ffe99537613 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 5 Nov 2023 00:37:05 +0300 Subject: [PATCH 068/185] Add: observer for lazy loading --- src/index.js | 46 +++++++++++++--------------------------------- src/observer.js | 21 +++++++++++++++++++++ 2 files changed, 34 insertions(+), 33 deletions(-) create mode 100644 src/observer.js diff --git a/src/index.js b/src/index.js index e9e8229..29bb574 100644 --- a/src/index.js +++ b/src/index.js @@ -10,6 +10,7 @@ import defaultSettings from './settings.js'; import loadAsset from './assetLoader.js'; +import observer from './observer.js'; /** * Lazy load assets. @@ -27,40 +28,18 @@ const lazyLoad = (tag = 'lazy', customSettings = {}) => { const settings = { ...defaultSettings, ...customSettings }; /** - * Handles the intersection of lazy load elements. + * Callback function for the observer. Tries to load the asset and handles any errors. * - * @private - * - * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer. - * @param {IntersectionObserver} observer - The intersection observer instance. + * @param {HTMLElement} target - The HTML element to load the asset for. */ - const handleIntersection = (entries, observer) => { - const handler = (entry) => { - const { target, isIntersecting } = entry; - if (!isIntersecting) return; - - try { - loadAsset(target, settings); - } catch (error) { - settings.onError(target, error); - } finally { - observer.unobserve(target); // bunun tam testini yapmak lazim - } - }; - - entries.forEach(handler); + const observeCallback = (target) => { + try { + loadAsset(target, settings); + } catch (error) { + settings.onError(target, error.message); + } }; - /** - * IntersectionObserver used for lazy loading. - * - * @type {IntersectionObserver} - */ - const observer = new IntersectionObserver( - handleIntersection, - settings.observer - ); - /** * NodeList of lazy loadable elements. * @@ -68,13 +47,14 @@ const lazyLoad = (tag = 'lazy', customSettings = {}) => { */ const lazyLoadItems = document.querySelectorAll(settings.selector); - if (!lazyLoadItems.length) { - console.warn('🚀 No lazy loadable element found.'); + console.warn('No lazy loadable element found!'); return; } - lazyLoadItems.forEach((item) => observer.observe(item)); + lazyLoadItems.forEach((item) => + observer(item, settings.observer, observeCallback) + ); }; export default lazyLoad; diff --git a/src/observer.js b/src/observer.js new file mode 100644 index 0000000..b7c298e --- /dev/null +++ b/src/observer.js @@ -0,0 +1,21 @@ +/** + * Creates an IntersectionObserver for a given item and triggers a callback when the item is intersecting. + * + * @param {HTMLElement} item - The HTML element to observe. + * @param {Object} settings - The settings for the IntersectionObserver. + * @param {Function} callback - The callback function to execute when the item is intersecting. + */ +const observer = (item, settings, callback) => { + const observer = new IntersectionObserver((entries) => { + entries.forEach((entry) => { + if (!entry.isIntersecting) return; + + callback(entry.target); + observer.unobserve(entry.target); + }); + }, settings); + + observer.observe(item); +}; + +export default observer; From 773b701182cef5a1a03f2959d5532399307240d5 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 5 Nov 2023 00:37:35 +0300 Subject: [PATCH 069/185] Add: Test for wrong element loading --- test/index.html | 1 + 1 file changed, 1 insertion(+) diff --git a/test/index.html b/test/index.html index 936bcae..4ef6ad6 100644 --- a/test/index.html +++ b/test/index.html @@ -11,6 +11,7 @@ Random Image +
Random Image Random Image Random Image From 62827b1e85c7f34c7872e3497de6ff84046efbe7 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 5 Nov 2023 00:41:58 +0300 Subject: [PATCH 070/185] Delete: unnecessary comment in loadAsset function --- src/assetLoader.js | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index 90f9e6a..1b17df3 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -63,8 +63,6 @@ const assetLoaders = { /** * Loads the asset for the given element based on its type (img, picture, video). * - * @private - * * @param {HTMLElement} element - The element to load the asset for. */ const loadAsset = (element, settings) => { From bd78ea2df30ec637885c66003464b7f1e64bc0b4 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 5 Nov 2023 00:45:21 +0300 Subject: [PATCH 071/185] Update: version --- package.json | 2 +- src/index.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a2df7d9..e8d726a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lazy-load.js", - "version": "1.0.6", + "version": "1.0.7", "homepage": "https://github.com/drementer/lazy-load.js", "description": "Loads visual content when it approaches the visible area of ​​the screen to increase page loading speed.", "source": "src/index.js", diff --git a/src/index.js b/src/index.js index 29bb574..478cfe1 100644 --- a/src/index.js +++ b/src/index.js @@ -3,7 +3,7 @@ * * @author drementer * @module lazyLoad - * @version 1.0.6 + * @version 1.0.7 * @license MIT * @see {@link https://github.com/drementer/lazy-load.js} */ From fb278dbd898a7322c3dadf9c58570f80282cb8e8 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 5 Nov 2023 00:54:28 +0300 Subject: [PATCH 072/185] Delete: Alt attr updating --- src/assetLoader.js | 17 +++++------------ src/settings.js | 4 ---- 2 files changed, 5 insertions(+), 16 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index 1b17df3..2b415bf 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -5,11 +5,9 @@ * * @param {HTMLImageElement} element - The image element to load the asset for. * @param {string} src - The asset path attribute value. - * @param {string} alt - The asset alt attribute value. */ -const loadImage = (element, src, alt = null) => { +const loadImage = (element, src) => { element.src = src; - if (alt) element.alt = alt; }; /** @@ -19,9 +17,8 @@ const loadImage = (element, src, alt = null) => { * * @param {HTMLPictureElement} element - The picture element to load the asset for. * @param {string} src - The asset URL attribute value. - * @param {string} alt - The asset alt attribute value. */ -const loadPicture = (element, src, alt) => { +const loadPicture = (element, src) => { let img = element.querySelector('img'); if (!img) { @@ -29,7 +26,7 @@ const loadPicture = (element, src, alt) => { element.append(img); } - loadImage(img, src, alt); + loadImage(img, src); }; /** @@ -66,8 +63,6 @@ const assetLoaders = { * @param {HTMLElement} element - The element to load the asset for. */ const loadAsset = (element, settings) => { - const { tag, altAttr } = settings; - const handleLoadEvent = () => { element.classList.remove(settings.modifiers.loading); element.removeAttribute(settings.tag); @@ -77,15 +72,13 @@ const loadAsset = (element, settings) => { element.removeEventListener('load', handleLoadEvent); }; - const assetPath = element.getAttribute(tag); - const assetAltValue = element.getAttribute(altAttr); - + const assetPath = element.getAttribute(settings.tag); const elementType = element.tagName.toLowerCase(); const assetLoader = assetLoaders[elementType]; if (!assetLoader) throw new Error(`Element type '${elementType}' is not supported!`); - assetLoader(element, assetPath, assetAltValue); + assetLoader(element, assetPath); element.classList.add(settings.modifiers.loading); element.addEventListener('load', handleLoadEvent); }; diff --git a/src/settings.js b/src/settings.js index 714c398..df3f262 100644 --- a/src/settings.js +++ b/src/settings.js @@ -18,10 +18,6 @@ const settings = { return `[${this.tag}]`; }, - get altAttribute() { - return `${this.tag}-alt`; - }, - tag: null, modifiers: { loaded: '-loaded', From 57992d1605014bb4138264df7dd5b163dc2cd1c2 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 14:55:01 +0300 Subject: [PATCH 073/185] Fix: observer callback function name. --- src/index.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/index.js b/src/index.js index 478cfe1..0cd1cd3 100644 --- a/src/index.js +++ b/src/index.js @@ -32,7 +32,7 @@ const lazyLoad = (tag = 'lazy', customSettings = {}) => { * * @param {HTMLElement} target - The HTML element to load the asset for. */ - const observeCallback = (target) => { + const observerCallback = (target) => { try { loadAsset(target, settings); } catch (error) { @@ -53,7 +53,7 @@ const lazyLoad = (tag = 'lazy', customSettings = {}) => { } lazyLoadItems.forEach((item) => - observer(item, settings.observer, observeCallback) + observer(item, settings.observer, observerCallback) ); }; From f31c65cfb21ec23b122025602fdd1db1d952225d Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 18:33:10 +0300 Subject: [PATCH 074/185] Add: lazy loading functionality with helper function --- src/helpers.js | 9 +++++++++ src/index.js | 26 +++++++++++--------------- src/settings.js | 6 +----- 3 files changed, 21 insertions(+), 20 deletions(-) create mode 100644 src/helpers.js diff --git a/src/helpers.js b/src/helpers.js new file mode 100644 index 0000000..558fec6 --- /dev/null +++ b/src/helpers.js @@ -0,0 +1,9 @@ +const getElements = (selector, root = document) => { + if (selector instanceof Element) return [selector]; + if (selector instanceof NodeList) return selector; + if (selector instanceof Array) return selector; + + return root.querySelectorAll(selector); +}; + +export { getElements }; diff --git a/src/index.js b/src/index.js index 0cd1cd3..a2837cb 100644 --- a/src/index.js +++ b/src/index.js @@ -11,15 +11,14 @@ import defaultSettings from './settings.js'; import loadAsset from './assetLoader.js'; import observer from './observer.js'; +import { getElements } from './helpers.js'; /** * Lazy load assets. * * @param {Object} [customSettings={}] - Additional options for configuring the lazy loading behavior. */ -const lazyLoad = (tag = 'lazy', customSettings = {}) => { - defaultSettings.tag = tag; - +const lazyLoad = (selector = 'lazy', customSettings = {}) => { /** * Settings object for configuring the lazy loading behavior. * @@ -27,6 +26,13 @@ const lazyLoad = (tag = 'lazy', customSettings = {}) => { */ const settings = { ...defaultSettings, ...customSettings }; + /** + * NodeList of lazy loadable elements. + * + * @type {NodeList | Array} + */ + const lazyItems = getElements(selector); + /** * Callback function for the observer. Tries to load the asset and handles any errors. * @@ -40,19 +46,9 @@ const lazyLoad = (tag = 'lazy', customSettings = {}) => { } }; - /** - * NodeList of lazy loadable elements. - * - * @type {NodeList} - */ - const lazyLoadItems = document.querySelectorAll(settings.selector); - - if (!lazyLoadItems.length) { - console.warn('No lazy loadable element found!'); - return; - } + if (!lazyItems.length) return console.warn('No lazy loadable element found!'); - lazyLoadItems.forEach((item) => + lazyItems.forEach((item) => observer(item, settings.observer, observerCallback) ); }; diff --git a/src/settings.js b/src/settings.js index df3f262..cd37779 100644 --- a/src/settings.js +++ b/src/settings.js @@ -14,11 +14,7 @@ * @property {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. */ const settings = { - get selector() { - return `[${this.tag}]`; - }, - - tag: null, + tag: 'lazy', modifiers: { loaded: '-loaded', loading: '-loading', From 3b7e1d685f0fb472b4fe8c056e256fbbac17dfb1 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 18:33:23 +0300 Subject: [PATCH 075/185] Add: support for iframe, embed, and object assets --- src/assetLoader.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/assetLoader.js b/src/assetLoader.js index 2b415bf..47577b2 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -55,6 +55,9 @@ const assetLoaders = { img: loadImage, picture: loadPicture, video: loadVideo, + iframe: loadImage, + embed: loadImage, + object: loadImage, }; /** From 48e1b2465209665b7dc1ed688785e37061b4510c Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 18:33:55 +0300 Subject: [PATCH 076/185] Update: lazyLoad function to accept an array of elements --- test/index.js | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/test/index.js b/test/index.js index b39ccf1..97d5320 100644 --- a/test/index.js +++ b/test/index.js @@ -1,5 +1,7 @@ import lazyLoad from '/dist/lazy-load.js'; -lazyLoad('lazy', { +const lazyLoadItems = document.querySelectorAll('[lazy]'); + +lazyLoad(lazyLoadItems, { onLoaded: (element) => console.log(element), -}); \ No newline at end of file +}); From afc4ec66096e7e3faf4f5ee72ebbcca10faccdb3 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 18:50:01 +0300 Subject: [PATCH 077/185] Feature: Support to srcset and poster --- src/assetLoader.js | 33 +++++++++++++++++++++------------ src/settings.js | 6 +++++- 2 files changed, 26 insertions(+), 13 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index 47577b2..88b2c9c 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -6,8 +6,10 @@ * @param {HTMLImageElement} element - The image element to load the asset for. * @param {string} src - The asset path attribute value. */ -const loadImage = (element, src) => { - element.src = src; +const loadImage = (element, assets) => { + element.src = assets.src; + + if (assets.srcset) element.srcset = assets.srcset; }; /** @@ -18,7 +20,7 @@ const loadImage = (element, src) => { * @param {HTMLPictureElement} element - The picture element to load the asset for. * @param {string} src - The asset URL attribute value. */ -const loadPicture = (element, src) => { +const loadPicture = (element, assets) => { let img = element.querySelector('img'); if (!img) { @@ -26,7 +28,7 @@ const loadPicture = (element, src) => { element.append(img); } - loadImage(img, src); + loadImage(img, assets); }; /** @@ -37,8 +39,10 @@ const loadPicture = (element, src) => { * @param {HTMLVideoElement} element - The video element to load the asset for. * @param {string} src - The asset URL attribute value. */ -const loadVideo = (element, src) => { - element.src = src; +const loadVideo = (element, assets) => { + element.src = assets.src; + + if (assets.poster) element.poster = assets.poster; }; /** @@ -55,9 +59,9 @@ const assetLoaders = { img: loadImage, picture: loadPicture, video: loadVideo, - iframe: loadImage, - embed: loadImage, - object: loadImage, + iframe: loadImage, + embed: loadImage, + object: loadImage, }; /** @@ -75,13 +79,18 @@ const loadAsset = (element, settings) => { element.removeEventListener('load', handleLoadEvent); }; - const assetPath = element.getAttribute(settings.tag); const elementType = element.tagName.toLowerCase(); const assetLoader = assetLoaders[elementType]; - if (!assetLoader) throw new Error(`Element type '${elementType}' is not supported!`); + if (!assetLoader) throw new Error(`Element type '${elementType}' is not supported!`); + + const assets = { + src: element.getAttribute(settings.attrs.src), + srcset: element.getAttribute(settings.attrs.srcset), + poster: element.getAttribute(settings.attrs.poster), + }; - assetLoader(element, assetPath); + assetLoader(element, assets); element.classList.add(settings.modifiers.loading); element.addEventListener('load', handleLoadEvent); }; diff --git a/src/settings.js b/src/settings.js index cd37779..9538e8e 100644 --- a/src/settings.js +++ b/src/settings.js @@ -14,7 +14,11 @@ * @property {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. */ const settings = { - tag: 'lazy', + attrs: { + src: 'lazy', + srcset: 'lazy-srcset', + poster: 'lazy-poster', + }, modifiers: { loaded: '-loaded', loading: '-loading', From a2a8c5a4a916aaf4a8ef5f80775dc9a22e82e14d Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 18:50:13 +0300 Subject: [PATCH 078/185] Refactor: lazyLoad function signature --- src/index.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/index.js b/src/index.js index a2837cb..bac8686 100644 --- a/src/index.js +++ b/src/index.js @@ -18,7 +18,7 @@ import { getElements } from './helpers.js'; * * @param {Object} [customSettings={}] - Additional options for configuring the lazy loading behavior. */ -const lazyLoad = (selector = 'lazy', customSettings = {}) => { +const lazyLoad = (selector, customSettings = {}) => { /** * Settings object for configuring the lazy loading behavior. * From 7643f1b7c04bece365403b2aaa62d3135f808d7e Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 19:02:02 +0300 Subject: [PATCH 079/185] Delete: Unused parameter --- src/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/settings.js b/src/settings.js index 9538e8e..a98a07e 100644 --- a/src/settings.js +++ b/src/settings.js @@ -23,7 +23,7 @@ const settings = { loaded: '-loaded', loading: '-loading', }, - onLoaded: (element) => {}, + onLoaded: () => {}, onError: (element, error) => { console.warn('Error on ~ element, error:', element, error); }, From b196fc95dff6db66989b3891420cc0941f8fbfcf Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 19:19:24 +0300 Subject: [PATCH 080/185] Refactor: assetLoader.js to improve code structure and readability. --- src/assetLoader.js | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index 88b2c9c..5b22023 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -4,11 +4,10 @@ * @private * * @param {HTMLImageElement} element - The image element to load the asset for. - * @param {string} src - The asset path attribute value. + * @param {Object} assets - The asset data. */ const loadImage = (element, assets) => { element.src = assets.src; - if (assets.srcset) element.srcset = assets.srcset; }; @@ -18,14 +17,14 @@ const loadImage = (element, assets) => { * @private * * @param {HTMLPictureElement} element - The picture element to load the asset for. - * @param {string} src - The asset URL attribute value. + * @param {Object} assets - The asset data. */ const loadPicture = (element, assets) => { let img = element.querySelector('img'); if (!img) { img = document.createElement('img'); - element.append(img); + element.appendChild(img); } loadImage(img, assets); @@ -37,7 +36,7 @@ const loadPicture = (element, assets) => { * @private * * @param {HTMLVideoElement} element - The video element to load the asset for. - * @param {string} src - The asset URL attribute value. + * @param {Object} assets - The asset data. */ const loadVideo = (element, assets) => { element.src = assets.src; @@ -51,9 +50,6 @@ const loadVideo = (element, assets) => { * @private * * @type {Object} - * @property {function} img - To load an image. - * @property {function} picture - To load a picture. - * @property {function} video - To load a video. */ const assetLoaders = { img: loadImage, @@ -68,21 +64,15 @@ const assetLoaders = { * Loads the asset for the given element based on its type (img, picture, video). * * @param {HTMLElement} element - The element to load the asset for. + * @param {Object} settings - The configuration settings. */ const loadAsset = (element, settings) => { - const handleLoadEvent = () => { - element.classList.remove(settings.modifiers.loading); - element.removeAttribute(settings.tag); - element.classList.add(settings.modifiers.loaded); - settings.onLoaded(element); - - element.removeEventListener('load', handleLoadEvent); - }; - const elementType = element.tagName.toLowerCase(); const assetLoader = assetLoaders[elementType]; - if (!assetLoader) throw new Error(`Element type '${elementType}' is not supported!`); + if (!assetLoader) { + throw new Error(`Element type '${elementType}' is not supported!`); + } const assets = { src: element.getAttribute(settings.attrs.src), @@ -90,7 +80,19 @@ const loadAsset = (element, settings) => { poster: element.getAttribute(settings.attrs.poster), }; + // Callback to handle the load event + const handleLoadEvent = () => { + element.classList.remove(settings.modifiers.loading); + element.removeAttribute(settings.tag); + element.classList.add(settings.modifiers.loaded); + settings.onLoaded(element); + element.removeEventListener('load', handleLoadEvent); + }; + + // Execute the appropriate asset loader assetLoader(element, assets); + + // Set the loading state and add the load event listener element.classList.add(settings.modifiers.loading); element.addEventListener('load', handleLoadEvent); }; From a66e4a11e4a906c475cbb6fca4c02a60cda103fb Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 20:03:28 +0300 Subject: [PATCH 081/185] Remove unnecessary attributes and change event listener to onload --- src/assetLoader.js | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index 5b22023..55021ab 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -83,10 +83,13 @@ const loadAsset = (element, settings) => { // Callback to handle the load event const handleLoadEvent = () => { element.classList.remove(settings.modifiers.loading); - element.removeAttribute(settings.tag); + + element.removeAttribute(settings.attrs.src); + element.removeAttribute(settings.attrs.srcset); + element.removeAttribute(settings.attrs.poster); + element.classList.add(settings.modifiers.loaded); settings.onLoaded(element); - element.removeEventListener('load', handleLoadEvent); }; // Execute the appropriate asset loader @@ -94,7 +97,7 @@ const loadAsset = (element, settings) => { // Set the loading state and add the load event listener element.classList.add(settings.modifiers.loading); - element.addEventListener('load', handleLoadEvent); + element.onload = handleLoadEvent; }; export default loadAsset; From 34694c98b4f180b79deeeee589084260a35c277a Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 20:38:22 +0300 Subject: [PATCH 082/185] Update: Once event listener --- src/assetLoader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index 55021ab..609e984 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -97,7 +97,7 @@ const loadAsset = (element, settings) => { // Set the loading state and add the load event listener element.classList.add(settings.modifiers.loading); - element.onload = handleLoadEvent; + element.addEventListener('load', handleLoadEvent, { once: true }); }; export default loadAsset; From b4899266f66463a42c637c10ac44e7c7ca7d2147 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 20:46:28 +0300 Subject: [PATCH 083/185] Delete: Unneeded comment blocks --- src/assetLoader.js | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index 609e984..8a0d766 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -80,22 +80,19 @@ const loadAsset = (element, settings) => { poster: element.getAttribute(settings.attrs.poster), }; - // Callback to handle the load event const handleLoadEvent = () => { element.classList.remove(settings.modifiers.loading); + element.classList.add(settings.modifiers.loaded); element.removeAttribute(settings.attrs.src); element.removeAttribute(settings.attrs.srcset); element.removeAttribute(settings.attrs.poster); - element.classList.add(settings.modifiers.loaded); settings.onLoaded(element); }; - // Execute the appropriate asset loader assetLoader(element, assets); - // Set the loading state and add the load event listener element.classList.add(settings.modifiers.loading); element.addEventListener('load', handleLoadEvent, { once: true }); }; From 36a4ba13d493395d623ffe62443d5270542c78db Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 20:48:42 +0300 Subject: [PATCH 084/185] Update: Rename file name --- src/{index.js => main.js} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename src/{index.js => main.js} (100%) diff --git a/src/index.js b/src/main.js similarity index 100% rename from src/index.js rename to src/main.js From 160eeb5e6bcbef483b131ee027121290331b658c Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:00:32 +0300 Subject: [PATCH 085/185] Refactor: lazyLoad function to handle errors more efficiently --- src/main.js | 23 +++++++---------------- 1 file changed, 7 insertions(+), 16 deletions(-) diff --git a/src/main.js b/src/main.js index bac8686..0484da4 100644 --- a/src/main.js +++ b/src/main.js @@ -33,24 +33,15 @@ const lazyLoad = (selector, customSettings = {}) => { */ const lazyItems = getElements(selector); - /** - * Callback function for the observer. Tries to load the asset and handles any errors. - * - * @param {HTMLElement} target - The HTML element to load the asset for. - */ - const observerCallback = (target) => { - try { - loadAsset(target, settings); - } catch (error) { - settings.onError(target, error.message); - } - }; - if (!lazyItems.length) return console.warn('No lazy loadable element found!'); - lazyItems.forEach((item) => - observer(item, settings.observer, observerCallback) - ); + try { + lazyItems.forEach((item) => + observer(item, settings.observer, loadAsset(target, settings)) + ); + } catch (error) { + settings.onError(target, error.message); + } }; export default lazyLoad; From c2e6f3c2b24cab1d1a8432c7574c7d83db10a874 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:02:20 +0300 Subject: [PATCH 086/185] Fix: observer callback order --- src/main.js | 2 +- src/observer.js | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.js b/src/main.js index 0484da4..67f8da1 100644 --- a/src/main.js +++ b/src/main.js @@ -37,7 +37,7 @@ const lazyLoad = (selector, customSettings = {}) => { try { lazyItems.forEach((item) => - observer(item, settings.observer, loadAsset(target, settings)) + observer(item, loadAsset(target, settings), settings.observer) ); } catch (error) { settings.onError(target, error.message); diff --git a/src/observer.js b/src/observer.js index b7c298e..0326067 100644 --- a/src/observer.js +++ b/src/observer.js @@ -2,10 +2,10 @@ * Creates an IntersectionObserver for a given item and triggers a callback when the item is intersecting. * * @param {HTMLElement} item - The HTML element to observe. - * @param {Object} settings - The settings for the IntersectionObserver. * @param {Function} callback - The callback function to execute when the item is intersecting. + * @param {Object} settings - The settings for the IntersectionObserver. */ -const observer = (item, settings, callback) => { +const observer = (item, callback, settings) => { const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (!entry.isIntersecting) return; From df7831e1c1ec8e04f5166698a611c8b1abe8cddc Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:18:29 +0300 Subject: [PATCH 087/185] Revert "Refactor: lazyLoad function to handle errors more efficiently" This reverts commit 160eeb5e6bcbef483b131ee027121290331b658c. --- src/main.js | 23 ++++++++++++++++------- 1 file changed, 16 insertions(+), 7 deletions(-) diff --git a/src/main.js b/src/main.js index 67f8da1..bac8686 100644 --- a/src/main.js +++ b/src/main.js @@ -33,15 +33,24 @@ const lazyLoad = (selector, customSettings = {}) => { */ const lazyItems = getElements(selector); + /** + * Callback function for the observer. Tries to load the asset and handles any errors. + * + * @param {HTMLElement} target - The HTML element to load the asset for. + */ + const observerCallback = (target) => { + try { + loadAsset(target, settings); + } catch (error) { + settings.onError(target, error.message); + } + }; + if (!lazyItems.length) return console.warn('No lazy loadable element found!'); - try { - lazyItems.forEach((item) => - observer(item, loadAsset(target, settings), settings.observer) - ); - } catch (error) { - settings.onError(target, error.message); - } + lazyItems.forEach((item) => + observer(item, settings.observer, observerCallback) + ); }; export default lazyLoad; From 4a988f54957764e4a8f5a2aecc1d90410b9ad524 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:18:37 +0300 Subject: [PATCH 088/185] Fix observer settings order in lazyLoad function. --- src/main.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main.js b/src/main.js index bac8686..6a27862 100644 --- a/src/main.js +++ b/src/main.js @@ -49,7 +49,7 @@ const lazyLoad = (selector, customSettings = {}) => { if (!lazyItems.length) return console.warn('No lazy loadable element found!'); lazyItems.forEach((item) => - observer(item, settings.observer, observerCallback) + observer(item, observerCallback, settings.observer) ); }; From 5942d123240a81d84a28aa5cabc0474c3516c435 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 21:19:31 +0300 Subject: [PATCH 089/185] Update: source file path in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e8d726a..436df70 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "1.0.7", "homepage": "https://github.com/drementer/lazy-load.js", "description": "Loads visual content when it approaches the visible area of ​​the screen to increase page loading speed.", - "source": "src/index.js", + "source": "src/main.js", "module": "dist/lazy-load.js", "scripts": { "watch": "parcel watch", From 783d1d794d02f9516d0a8c09ba5d55028305a072 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 23:38:38 +0300 Subject: [PATCH 090/185] Update: Rename file --- src/{settings.js => defaultSettings.js} | 4 ++-- src/main.js | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) rename src/{settings.js => defaultSettings.js} (95%) diff --git a/src/settings.js b/src/defaultSettings.js similarity index 95% rename from src/settings.js rename to src/defaultSettings.js index a98a07e..f0bbbb5 100644 --- a/src/settings.js +++ b/src/defaultSettings.js @@ -13,7 +13,7 @@ * @property {Function} [onError] - Callback function to execute when an error occurs during loading. * @property {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. */ -const settings = { +const defaultSettings = { attrs: { src: 'lazy', srcset: 'lazy-srcset', @@ -34,4 +34,4 @@ const settings = { }, }; -export default settings; +export default defaultSettings; diff --git a/src/main.js b/src/main.js index 6a27862..8040c2c 100644 --- a/src/main.js +++ b/src/main.js @@ -8,7 +8,7 @@ * @see {@link https://github.com/drementer/lazy-load.js} */ -import defaultSettings from './settings.js'; +import defaultSettings from './defaultSettings.js'; import loadAsset from './assetLoader.js'; import observer from './observer.js'; import { getElements } from './helpers.js'; From 526f24270ccc481561686545fb4885f643249ddd Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 23:46:03 +0300 Subject: [PATCH 091/185] Delete: JSDoc --- src/assetLoader.js | 37 ------------------------------------- src/defaultSettings.js | 15 --------------- src/main.js | 21 --------------------- src/observer.js | 7 ------- 4 files changed, 80 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index 8a0d766..80034eb 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -1,24 +1,8 @@ -/** - * Loads the asset for the given image element. - * - * @private - * - * @param {HTMLImageElement} element - The image element to load the asset for. - * @param {Object} assets - The asset data. - */ const loadImage = (element, assets) => { element.src = assets.src; if (assets.srcset) element.srcset = assets.srcset; }; -/** - * Loads the asset for the given picture element. - * - * @private - * - * @param {HTMLPictureElement} element - The picture element to load the asset for. - * @param {Object} assets - The asset data. - */ const loadPicture = (element, assets) => { let img = element.querySelector('img'); @@ -30,27 +14,12 @@ const loadPicture = (element, assets) => { loadImage(img, assets); }; -/** - * Loads the asset for the given video element. - * - * @private - * - * @param {HTMLVideoElement} element - The video element to load the asset for. - * @param {Object} assets - The asset data. - */ const loadVideo = (element, assets) => { element.src = assets.src; if (assets.poster) element.poster = assets.poster; }; -/** - * A map of asset loaders by element type. - * - * @private - * - * @type {Object} - */ const assetLoaders = { img: loadImage, picture: loadPicture, @@ -60,12 +29,6 @@ const assetLoaders = { object: loadImage, }; -/** - * Loads the asset for the given element based on its type (img, picture, video). - * - * @param {HTMLElement} element - The element to load the asset for. - * @param {Object} settings - The configuration settings. - */ const loadAsset = (element, settings) => { const elementType = element.tagName.toLowerCase(); const assetLoader = assetLoaders[elementType]; diff --git a/src/defaultSettings.js b/src/defaultSettings.js index f0bbbb5..d82b61b 100644 --- a/src/defaultSettings.js +++ b/src/defaultSettings.js @@ -1,18 +1,3 @@ -/** - * Default settings for lazy loading behavior. - * - * @type {Object} - * - * @property {Function} selector - Get the CSS selector for lazy loadable elements. - * @property {Function} altAttribute - Get the alternative attribute for lazy loadable elements. - * @property {string} [tag] - The CSS selector for lazy loadable elements. - * @property {Object} modifiers - The class names to toggle on elements. - * @property {string} modifiers.loaded - The class name to toggle on elements after loading. - * @property {string} modifiers.loading - The class name to toggle on elements while loading. - * @property {Function} [onLoaded] - Callback function to execute when an element is successfully loaded. - * @property {Function} [onError] - Callback function to execute when an error occurs during loading. - * @property {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. - */ const defaultSettings = { attrs: { src: 'lazy', diff --git a/src/main.js b/src/main.js index 8040c2c..84fd2dc 100644 --- a/src/main.js +++ b/src/main.js @@ -13,31 +13,10 @@ import loadAsset from './assetLoader.js'; import observer from './observer.js'; import { getElements } from './helpers.js'; -/** - * Lazy load assets. - * - * @param {Object} [customSettings={}] - Additional options for configuring the lazy loading behavior. - */ const lazyLoad = (selector, customSettings = {}) => { - /** - * Settings object for configuring the lazy loading behavior. - * - * @type {Object} - */ const settings = { ...defaultSettings, ...customSettings }; - - /** - * NodeList of lazy loadable elements. - * - * @type {NodeList | Array} - */ const lazyItems = getElements(selector); - /** - * Callback function for the observer. Tries to load the asset and handles any errors. - * - * @param {HTMLElement} target - The HTML element to load the asset for. - */ const observerCallback = (target) => { try { loadAsset(target, settings); diff --git a/src/observer.js b/src/observer.js index 0326067..3658f8c 100644 --- a/src/observer.js +++ b/src/observer.js @@ -1,10 +1,3 @@ -/** - * Creates an IntersectionObserver for a given item and triggers a callback when the item is intersecting. - * - * @param {HTMLElement} item - The HTML element to observe. - * @param {Function} callback - The callback function to execute when the item is intersecting. - * @param {Object} settings - The settings for the IntersectionObserver. - */ const observer = (item, callback, settings) => { const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { From a6ecd49c777d8fe19b55a0fb14adc227be2bdb3f Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 6 Nov 2023 23:54:00 +0300 Subject: [PATCH 092/185] Update: File name --- src/{helpers.js => getElements.js} | 0 src/main.js | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{helpers.js => getElements.js} (100%) diff --git a/src/helpers.js b/src/getElements.js similarity index 100% rename from src/helpers.js rename to src/getElements.js diff --git a/src/main.js b/src/main.js index 84fd2dc..682c953 100644 --- a/src/main.js +++ b/src/main.js @@ -11,7 +11,7 @@ import defaultSettings from './defaultSettings.js'; import loadAsset from './assetLoader.js'; import observer from './observer.js'; -import { getElements } from './helpers.js'; +import { getElements } from './getElements.js'; const lazyLoad = (selector, customSettings = {}) => { const settings = { ...defaultSettings, ...customSettings }; From b9954c3422af8c57f9db9743b59fa263aa28b229 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Tue, 7 Nov 2023 00:26:08 +0300 Subject: [PATCH 093/185] Add: asset loader regular elements --- src/assetLoader.js | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index 80034eb..d622b73 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -1,8 +1,18 @@ +const regularLoad = (element, assets) => { + element.src = assets.src; +}; + const loadImage = (element, assets) => { element.src = assets.src; if (assets.srcset) element.srcset = assets.srcset; }; +const loadVideo = (element, assets) => { + element.src = assets.src; + + if (assets.poster) element.poster = assets.poster; +}; + const loadPicture = (element, assets) => { let img = element.querySelector('img'); @@ -14,19 +24,13 @@ const loadPicture = (element, assets) => { loadImage(img, assets); }; -const loadVideo = (element, assets) => { - element.src = assets.src; - - if (assets.poster) element.poster = assets.poster; -}; - const assetLoaders = { img: loadImage, picture: loadPicture, video: loadVideo, - iframe: loadImage, - embed: loadImage, - object: loadImage, + iframe: regularLoad, + embed: regularLoad, + object: regularLoad, }; const loadAsset = (element, settings) => { From 0b84f8dcacb2e69624b4ca2aa755a3632a8f21c8 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Tue, 7 Nov 2023 00:30:18 +0300 Subject: [PATCH 094/185] Add: onLoading callback to lazyLoad function --- src/defaultSettings.js | 1 + src/main.js | 1 + 2 files changed, 2 insertions(+) diff --git a/src/defaultSettings.js b/src/defaultSettings.js index d82b61b..00bd8ae 100644 --- a/src/defaultSettings.js +++ b/src/defaultSettings.js @@ -9,6 +9,7 @@ const defaultSettings = { loading: '-loading', }, onLoaded: () => {}, + onLoading: () => {}, onError: (element, error) => { console.warn('Error on ~ element, error:', element, error); }, diff --git a/src/main.js b/src/main.js index 682c953..87d8405 100644 --- a/src/main.js +++ b/src/main.js @@ -19,6 +19,7 @@ const lazyLoad = (selector, customSettings = {}) => { const observerCallback = (target) => { try { + settings.onLoading(target); loadAsset(target, settings); } catch (error) { settings.onError(target, error.message); From 1bed66cfe50b26c225a5cdddea1a991b8c8e8e75 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Tue, 7 Nov 2023 00:39:34 +0300 Subject: [PATCH 095/185] Refactor: onError function in defaultSettings.js --- src/defaultSettings.js | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/defaultSettings.js b/src/defaultSettings.js index 00bd8ae..498090d 100644 --- a/src/defaultSettings.js +++ b/src/defaultSettings.js @@ -10,9 +10,7 @@ const defaultSettings = { }, onLoaded: () => {}, onLoading: () => {}, - onError: (element, error) => { - console.warn('Error on ~ element, error:', element, error); - }, + onError: (element, error) => console.warn('Error on:', element, error), observer: { root: null, threshold: 1, From 2d7ebba75b3e5f8f69d328400d820b13a76d5bc9 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Tue, 7 Nov 2023 00:49:36 +0300 Subject: [PATCH 096/185] Refactor: Code quality --- src/main.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main.js b/src/main.js index 87d8405..33b44f9 100644 --- a/src/main.js +++ b/src/main.js @@ -17,6 +17,8 @@ const lazyLoad = (selector, customSettings = {}) => { const settings = { ...defaultSettings, ...customSettings }; const lazyItems = getElements(selector); + if (!lazyItems.length) return console.warn('No lazy loadable element found!'); + const observerCallback = (target) => { try { settings.onLoading(target); @@ -26,8 +28,6 @@ const lazyLoad = (selector, customSettings = {}) => { } }; - if (!lazyItems.length) return console.warn('No lazy loadable element found!'); - lazyItems.forEach((item) => observer(item, observerCallback, settings.observer) ); From 4609e14bba3316b6073f07d9ba12171c160f259a Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Tue, 7 Nov 2023 00:56:08 +0300 Subject: [PATCH 097/185] Build --- dist/lazy-load.js | 216 +++++++++++++++++------------------------- dist/lazy-load.js.map | 2 +- 2 files changed, 89 insertions(+), 129 deletions(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index f24bfb5..bbb05e5 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -3,165 +3,125 @@ * * @author drementer * @module lazyLoad - * @version 1.0.6 + * @version 1.0.7 * @license MIT * @see {@link https://github.com/drementer/lazy-load.js} - */ /** - * Default options for lazy loading behavior. - * - * @type {Object} - * - * @param {string} [tag=selector] - The CSS selector for lazy loadable elements. - * @param {string} [toggleClass="-loaded"] - The class name to toggle on elements after loading. - * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded. - * @param {Function} [onError] - Callback function to execute when an error occurs during loading. - * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading. - */ const $db127449446b8099$var$options = { - get selector () { - return `[${this.tag}]`; + */ const $eca09eba1a2796e9$var$defaultSettings = { + attrs: { + src: "lazy", + srcset: "lazy-srcset", + poster: "lazy-poster" }, - get altAttribute () { - return `${this.tag}-alt`; - }, - tag: null, modifiers: { loaded: "-loaded", loading: "-loading" }, - onLoaded: (element)=>{}, - onError: (element, error)=>{ - console.error("\uD83D\uDE80 Error on ~ element, error:", element, error); - }, + onLoaded: ()=>{}, + onLoading: ()=>{}, + onError: (element, error)=>console.warn("Error on:", element, error), observer: { root: null, threshold: 1, rootMargin: "100% 0px" } }; -var $db127449446b8099$export$2e2bcd8739ae039 = $db127449446b8099$var$options; +var $eca09eba1a2796e9$export$2e2bcd8739ae039 = $eca09eba1a2796e9$var$defaultSettings; -/** - * Loads the asset for the given image element. - * - * @private - * - * @param {HTMLImageElement} element - The image element to load the asset for. - * @param {string} src - The asset path attribute value. - * @param {string} alt - The asset alt attribute value. - */ const $fa423858cf60d4ae$var$loadImage = (element, src, alt = null)=>{ - element.src = src; - if (alt) element.alt = alt; +const $fa423858cf60d4ae$var$regularLoad = (element, assets)=>{ + element.src = assets.src; }; -/** - * Loads the asset for the given picture element. - * - * @private - * - * @param {HTMLPictureElement} element - The picture element to load the asset for. - * @param {string} src - The asset URL attribute value. - * @param {string} alt - The asset alt attribute value. - */ const $fa423858cf60d4ae$var$loadPicture = (element, src, alt)=>{ +const $fa423858cf60d4ae$var$loadImage = (element, assets)=>{ + element.src = assets.src; + if (assets.srcset) element.srcset = assets.srcset; +}; +const $fa423858cf60d4ae$var$loadVideo = (element, assets)=>{ + element.src = assets.src; + if (assets.poster) element.poster = assets.poster; +}; +const $fa423858cf60d4ae$var$loadPicture = (element, assets)=>{ let img = element.querySelector("img"); if (!img) { img = document.createElement("img"); - element.append(img); + element.appendChild(img); } - $fa423858cf60d4ae$var$loadImage(img, src, alt); + $fa423858cf60d4ae$var$loadImage(img, assets); }; -/** - * Loads the asset for the given video element. - * - * @private - * - * @param {HTMLVideoElement} element - The video element to load the asset for. - * @param {string} src - The asset URL attribute value. - */ const $fa423858cf60d4ae$var$loadVideo = (element, src)=>{ - element.src = src; +const $fa423858cf60d4ae$var$assetLoaders = { + img: $fa423858cf60d4ae$var$loadImage, + picture: $fa423858cf60d4ae$var$loadPicture, + video: $fa423858cf60d4ae$var$loadVideo, + iframe: $fa423858cf60d4ae$var$regularLoad, + embed: $fa423858cf60d4ae$var$regularLoad, + object: $fa423858cf60d4ae$var$regularLoad }; -/** - * Loads the asset for the given element based on its type (img, picture, video). - * - * @private - * - * @param {HTMLElement} element - The element to load the asset for. - */ const $fa423858cf60d4ae$var$loadAsset = (element, options)=>{ - const { tag: tag, altAttr: altAttr } = options; - const assetLoaders = { - img: $fa423858cf60d4ae$var$loadImage, - picture: $fa423858cf60d4ae$var$loadPicture, - video: $fa423858cf60d4ae$var$loadVideo +const $fa423858cf60d4ae$var$loadAsset = (element, settings)=>{ + const elementType = element.tagName.toLowerCase(); + const assetLoader = $fa423858cf60d4ae$var$assetLoaders[elementType]; + if (!assetLoader) throw new Error(`Element type '${elementType}' is not supported!`); + const assets = { + src: element.getAttribute(settings.attrs.src), + srcset: element.getAttribute(settings.attrs.srcset), + poster: element.getAttribute(settings.attrs.poster) }; const handleLoadEvent = ()=>{ - element.classList.remove(options.modifiers.loading); - element.removeAttribute(options.tag); - element.classList.add(options.modifiers.loaded); - options.onLoaded(element); - element.removeEventListener("load", handleLoadEvent); + element.classList.remove(settings.modifiers.loading); + element.classList.add(settings.modifiers.loaded); + element.removeAttribute(settings.attrs.src); + element.removeAttribute(settings.attrs.srcset); + element.removeAttribute(settings.attrs.poster); + settings.onLoaded(element); }; - const elementType = element.tagName.toLowerCase(); - const assetLoader = assetLoaders[elementType]; - const assetPath = element.getAttribute(tag); - const assetAltValue = element.getAttribute(altAttr); - assetLoader(element, assetPath, assetAltValue); - element.classList.add(options.modifiers.loading); - element.addEventListener("load", handleLoadEvent); + assetLoader(element, assets); + element.classList.add(settings.modifiers.loading); + element.addEventListener("load", handleLoadEvent, { + once: true + }); }; var $fa423858cf60d4ae$export$2e2bcd8739ae039 = $fa423858cf60d4ae$var$loadAsset; -/** - * Lazy load assets. - * - * @param {Object} [customOptions={}] - Additional options for configuring the lazy loading behavior. - */ const $82cbb5a2f3a1bcd0$var$lazyLoad = (tag = "lazy", customOptions = {})=>{ - (0, $db127449446b8099$export$2e2bcd8739ae039).tag = tag; - /** - * Options object for configuring the lazy loading behavior. - * - * @type {Object} - */ const options = { - ...(0, $db127449446b8099$export$2e2bcd8739ae039), - ...customOptions +const $5aa3f28da5200ea6$var$observer = (item, callback, settings)=>{ + const observer = new IntersectionObserver((entries)=>{ + entries.forEach((entry)=>{ + if (!entry.isIntersecting) return; + callback(entry.target); + observer.unobserve(entry.target); + }); + }, settings); + observer.observe(item); +}; +var $5aa3f28da5200ea6$export$2e2bcd8739ae039 = $5aa3f28da5200ea6$var$observer; + + +const $e5a64a9b43e3c02c$export$73eac51a39d6b0eb = (selector, root = document)=>{ + if (selector instanceof Element) return [ + selector + ]; + if (selector instanceof NodeList) return selector; + if (selector instanceof Array) return selector; + return root.querySelectorAll(selector); +}; + + +const $d582dd6eaccab18d$var$lazyLoad = (selector, customSettings = {})=>{ + const settings = { + ...(0, $eca09eba1a2796e9$export$2e2bcd8739ae039), + ...customSettings }; - /** - * Handles the intersection of lazy load elements. - * - * @private - * - * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer. - * @param {IntersectionObserver} observer - The intersection observer instance. - */ const handleIntersection = (entries, observer)=>{ - const handler = (entry)=>{ - const { target: target, isIntersecting: isIntersecting } = entry; - if (!isIntersecting) return; - try { - (0, $fa423858cf60d4ae$export$2e2bcd8739ae039)(target, options); - } catch (error) { - options.onError(target, error); - } finally{ - observer.unobserve(target); // bunun tam testini yapmak lazim - } - }; - entries.forEach(handler); + const lazyItems = (0, $e5a64a9b43e3c02c$export$73eac51a39d6b0eb)(selector); + if (!lazyItems.length) return console.warn("No lazy loadable element found!"); + const observerCallback = (target)=>{ + try { + settings.onLoading(target); + (0, $fa423858cf60d4ae$export$2e2bcd8739ae039)(target, settings); + } catch (error) { + settings.onError(target, error.message); + } }; - /** - * IntersectionObserver used for lazy loading. - * - * @type {IntersectionObserver} - */ const observer = new IntersectionObserver(handleIntersection, options.observer); - /** - * NodeList of lazy loadable elements. - * - * @type {NodeList} - */ const lazyLoadItems = document.querySelectorAll(options.selector); - if (!lazyLoadItems.length) { - console.warn("\uD83D\uDE80 No lazy loadable element found."); - return; - } - lazyLoadItems.forEach((item)=>observer.observe(item)); + lazyItems.forEach((item)=>(0, $5aa3f28da5200ea6$export$2e2bcd8739ae039)(item, observerCallback, settings.observer)); }; -var $82cbb5a2f3a1bcd0$export$2e2bcd8739ae039 = $82cbb5a2f3a1bcd0$var$lazyLoad; +var $d582dd6eaccab18d$export$2e2bcd8739ae039 = $d582dd6eaccab18d$var$lazyLoad; -export {$82cbb5a2f3a1bcd0$export$2e2bcd8739ae039 as default}; +export {$d582dd6eaccab18d$export$2e2bcd8739ae039 as default}; diff --git a/dist/lazy-load.js.map b/dist/lazy-load.js.map index 4facd93..4866e4e 100644 --- a/dist/lazy-load.js.map +++ b/dist/lazy-load.js.map @@ -1 +1 @@ -{"mappings":"AAAA;;;;;;;;ACAA;;;;;;;;;;CAUC,GACD,MAAM,gCAAU;IACd,IAAI,YAAW;QACb,OAAO,CAAC,CAAC,EAAE,IAAI,CAAC,IAAI,CAAC,CAAC;IACxB;IACA,IAAI,gBAAe;QACjB,OAAO,CAAC,EAAE,IAAI,CAAC,IAAI,IAAI,CAAC;IAC1B;IAEA,KAAK;IACL,WAAW;QACT,QAAQ;QACR,SAAS;IACX;IACA,UAAU,CAAC,WAAa;IACxB,SAAS,CAAC,SAAS;QACjB,QAAQ,MAAM,2CAAiC,SAAS;IAC1D;IACA,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;IAEA,2CAAe;;CD3Bd;AERD;;;;;;;;CAQC,GACD,MAAM,kCAAY,CAAC,SAAS,KAAK,MAAM,IAAI;IACzC,QAAQ,MAAM;IACd,IAAI,KAAK,QAAQ,MAAM;AACzB;AAEA;;;;;;;;CAQC,GACD,MAAM,oCAAc,CAAC,SAAS,KAAK;IACjC,IAAI,MAAM,QAAQ,cAAc;IAEhC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,OAAO;IACjB;IAEA,gCAAU,KAAK,KAAK;AACtB;AAEA;;;;;;;CAOC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM;AAChB;AAEA;;;;;;CAMC,GACD,MAAM,kCAAY,CAAC,SAAS;IAC1B,MAAM,OAAE,GAAG,WAAE,OAAO,EAAE,GAAG;IAEzB,MAAM,eAAe;QACnB,KAAK;QACL,SAAS;QACT,OAAO;IACT;IAEA,MAAM,kBAAkB;QACtB,QAAQ,UAAU,OAAO,QAAQ,UAAU;QAC3C,QAAQ,gBAAgB,QAAQ;QAChC,QAAQ,UAAU,IAAI,QAAQ,UAAU;QACxC,QAAQ,SAAS;QAEjB,QAAQ,oBAAoB,QAAQ;IACtC;IAEA,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,cAAc,YAAY,CAAC,YAAY;IAE7C,MAAM,YAAY,QAAQ,aAAa;IACvC,MAAM,gBAAgB,QAAQ,aAAa;IAE3C,YAAY,SAAS,WAAW;IAChC,QAAQ,UAAU,IAAI,QAAQ,UAAU;IACxC,QAAQ,iBAAiB,QAAQ;AACnC;IAEA,2CAAe;;;AFrEf;;;;CAIC,GACD,MAAM,iCAAW,CAAC,MAAM,MAAM,EAAE,gBAAgB,CAAC,CAAC;IAChD,CAAA,GAAA,wCAAa,EAAE,MAAM;IAErB;;;;GAIC,GACD,MAAM,UAAU;QAAE,GAAG,CAAA,GAAA,wCAAa,CAAC;QAAE,GAAG,aAAa;IAAC;IAEtD;;;;;;;GAOC,GACD,MAAM,qBAAqB,CAAC,SAAS;QACnC,MAAM,UAAU,CAAC;YACf,MAAM,UAAE,MAAM,kBAAE,cAAc,EAAE,GAAG;YACnC,IAAI,CAAC,gBAAgB;YAErB,IAAI;gBACF,CAAA,GAAA,wCAAQ,EAAE,QAAQ;YACpB,EAAE,OAAO,OAAO;gBACd,QAAQ,QAAQ,QAAQ;YAC1B,SAAU;gBACR,SAAS,UAAU,SAAS,iCAAiC;YAC/D;QACF;QAEA,QAAQ,QAAQ;IAClB;IAEA;;;;GAIC,GACD,MAAM,WAAW,IAAI,qBACnB,oBACA,QAAQ;IAGV;;;;GAIC,GACD,MAAM,gBAAgB,SAAS,iBAAiB,QAAQ;IAGxD,IAAI,CAAC,cAAc,QAAQ;QACzB,QAAQ,KAAK;QACb;IACF;IAEA,cAAc,QAAQ,CAAC,OAAS,SAAS,QAAQ;AACnD;IAEA,2CAAe","sources":["src/index.js","src/options.js","src/assetLoader.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.6\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './options.js';\nimport loadAsset from './assetLoader.js';\n\n/**\n * Lazy load assets.\n *\n * @param {Object} [customOptions={}] - Additional options for configuring the lazy loading behavior.\n */\nconst lazyLoad = (tag = 'lazy', customOptions = {}) => {\n defaultOptions.tag = tag;\n\n /**\n * Options object for configuring the lazy loading behavior.\n *\n * @type {Object}\n */\n const options = { ...defaultOptions, ...customOptions };\n\n /**\n * Handles the intersection of lazy load elements.\n *\n * @private\n *\n * @param {IntersectionObserverEntry[]} entries - The entries for the intersection observer.\n * @param {IntersectionObserver} observer - The intersection observer instance.\n */\n const handleIntersection = (entries, observer) => {\n const handler = (entry) => {\n const { target, isIntersecting } = entry;\n if (!isIntersecting) return;\n\n try {\n loadAsset(target, options);\n } catch (error) {\n options.onError(target, error);\n } finally {\n observer.unobserve(target); // bunun tam testini yapmak lazim\n }\n };\n\n entries.forEach(handler);\n };\n\n /**\n * IntersectionObserver used for lazy loading.\n *\n * @type {IntersectionObserver}\n */\n const observer = new IntersectionObserver(\n handleIntersection,\n options.observer\n );\n\n /**\n * NodeList of lazy loadable elements.\n *\n * @type {NodeList}\n */\n const lazyLoadItems = document.querySelectorAll(options.selector);\n\n\n if (!lazyLoadItems.length) {\n console.warn('🚀 No lazy loadable element found.');\n return;\n }\n\n lazyLoadItems.forEach((item) => observer.observe(item));\n};\n\nexport default lazyLoad;\n","/**\n * Default options for lazy loading behavior.\n *\n * @type {Object}\n *\n * @param {string} [tag=selector] - The CSS selector for lazy loadable elements.\n * @param {string} [toggleClass=\"-loaded\"] - The class name to toggle on elements after loading.\n * @param {Function} [onLoaded] - Callback function to execute when an element is successfully loaded.\n * @param {Function} [onError] - Callback function to execute when an error occurs during loading.\n * @param {Object} [observer={ root: null, threshold: 1, rootMargin: '300px 0px' }] - Configuration for IntersectionObserver used for lazy loading.\n */\nconst options = {\n get selector() {\n return `[${this.tag}]`;\n },\n get altAttribute() {\n return `${this.tag}-alt`;\n },\n\n tag: null,\n modifiers: {\n loaded: '-loaded',\n loading: '-loading',\n },\n onLoaded: (element) => {},\n onError: (element, error) => {\n console.error('🚀 Error on ~ element, error:', element, error);\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n};\n\nexport default options;\n","/**\n * Loads the asset for the given image element.\n *\n * @private\n *\n * @param {HTMLImageElement} element - The image element to load the asset for.\n * @param {string} src - The asset path attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadImage = (element, src, alt = null) => {\n element.src = src;\n if (alt) element.alt = alt;\n};\n\n/**\n * Loads the asset for the given picture element.\n *\n * @private\n *\n * @param {HTMLPictureElement} element - The picture element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n * @param {string} alt - The asset alt attribute value.\n */\nconst loadPicture = (element, src, alt) => {\n let img = element.querySelector('img');\n\n if (!img) {\n img = document.createElement('img');\n element.append(img);\n }\n\n loadImage(img, src, alt);\n};\n\n/**\n * Loads the asset for the given video element.\n *\n * @private\n *\n * @param {HTMLVideoElement} element - The video element to load the asset for.\n * @param {string} src - The asset URL attribute value.\n */\nconst loadVideo = (element, src) => {\n element.src = src;\n};\n\n/**\n * Loads the asset for the given element based on its type (img, picture, video).\n *\n * @private\n *\n * @param {HTMLElement} element - The element to load the asset for.\n */\nconst loadAsset = (element, options) => {\n const { tag, altAttr } = options;\n\n const assetLoaders = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n };\n\n const handleLoadEvent = () => {\n element.classList.remove(options.modifiers.loading);\n element.removeAttribute(options.tag);\n element.classList.add(options.modifiers.loaded);\n options.onLoaded(element);\n\n element.removeEventListener('load', handleLoadEvent);\n };\n\n const elementType = element.tagName.toLowerCase();\n const assetLoader = assetLoaders[elementType];\n\n const assetPath = element.getAttribute(tag);\n const assetAltValue = element.getAttribute(altAttr);\n\n assetLoader(element, assetPath, assetAltValue);\n element.classList.add(options.modifiers.loading);\n element.addEventListener('load', handleLoadEvent);\n};\n\nexport default loadAsset;\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file +{"mappings":"AAAA;;;;;;;;ACAA,MAAM,wCAAkB;IACtB,OAAO;QACL,KAAK;QACL,QAAQ;QACR,QAAQ;IACV;IACA,WAAW;QACT,QAAQ;QACR,SAAS;IACX;IACA,UAAU,KAAO;IACjB,WAAW,KAAO;IAClB,SAAS,CAAC,SAAS,QAAU,QAAQ,KAAK,aAAa,SAAS;IAChE,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;IAEA,2CAAe;;CDZd;AERD,MAAM,oCAAc,CAAC,SAAS;IAC5B,QAAQ,MAAM,OAAO;AACvB;AAEA,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM,OAAO;IACrB,IAAI,OAAO,QAAQ,QAAQ,SAAS,OAAO;AAC7C;AAEA,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM,OAAO;IAErB,IAAI,OAAO,QAAQ,QAAQ,SAAS,OAAO;AAC7C;AAEA,MAAM,oCAAc,CAAC,SAAS;IAC5B,IAAI,MAAM,QAAQ,cAAc;IAEhC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,YAAY;IACtB;IAEA,gCAAU,KAAK;AACjB;AAEA,MAAM,qCAAe;IACnB,KAAK;IACL,SAAS;IACT,OAAO;IACP,QAAQ;IACR,OAAO;IACP,QAAQ;AACV;AAEA,MAAM,kCAAY,CAAC,SAAS;IAC1B,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,cAAc,kCAAY,CAAC,YAAY;IAE7C,IAAI,CAAC,aACH,MAAM,IAAI,MAAM,CAAC,cAAc,EAAE,YAAY,mBAAmB,CAAC;IAGnE,MAAM,SAAS;QACb,KAAK,QAAQ,aAAa,SAAS,MAAM;QACzC,QAAQ,QAAQ,aAAa,SAAS,MAAM;QAC5C,QAAQ,QAAQ,aAAa,SAAS,MAAM;IAC9C;IAEA,MAAM,kBAAkB;QACtB,QAAQ,UAAU,OAAO,SAAS,UAAU;QAC5C,QAAQ,UAAU,IAAI,SAAS,UAAU;QAEzC,QAAQ,gBAAgB,SAAS,MAAM;QACvC,QAAQ,gBAAgB,SAAS,MAAM;QACvC,QAAQ,gBAAgB,SAAS,MAAM;QAEvC,SAAS,SAAS;IACpB;IAEA,YAAY,SAAS;IAErB,QAAQ,UAAU,IAAI,SAAS,UAAU;IACzC,QAAQ,iBAAiB,QAAQ,iBAAiB;QAAE,MAAM;IAAK;AACjE;IAEA,2CAAe;;;AClEf,MAAM,iCAAW,CAAC,MAAM,UAAU;IAChC,MAAM,WAAW,IAAI,qBAAqB,CAAC;QACzC,QAAQ,QAAQ,CAAC;YACf,IAAI,CAAC,MAAM,gBAAgB;YAE3B,SAAS,MAAM;YACf,SAAS,UAAU,MAAM;QAC3B;IACF,GAAG;IAEH,SAAS,QAAQ;AACnB;IAEA,2CAAe;;;ACbf,MAAM,4CAAc,CAAC,UAAU,OAAO,QAAQ;IAC5C,IAAI,oBAAoB,SAAS,OAAO;QAAC;KAAS;IAClD,IAAI,oBAAoB,UAAU,OAAO;IACzC,IAAI,oBAAoB,OAAO,OAAO;IAEtC,OAAO,KAAK,iBAAiB;AAC/B;;;AJSA,MAAM,iCAAW,CAAC,UAAU,iBAAiB,CAAC,CAAC;IAC7C,MAAM,WAAW;QAAE,GAAG,CAAA,GAAA,wCAAc,CAAC;QAAE,GAAG,cAAc;IAAC;IACzD,MAAM,YAAY,CAAA,GAAA,yCAAU,EAAE;IAE9B,IAAI,CAAC,UAAU,QAAQ,OAAO,QAAQ,KAAK;IAE3C,MAAM,mBAAmB,CAAC;QACxB,IAAI;YACF,SAAS,UAAU;YACnB,CAAA,GAAA,wCAAQ,EAAE,QAAQ;QACpB,EAAE,OAAO,OAAO;YACd,SAAS,QAAQ,QAAQ,MAAM;QACjC;IACF;IAEA,UAAU,QAAQ,CAAC,OACjB,CAAA,GAAA,wCAAO,EAAE,MAAM,kBAAkB,SAAS;AAE9C;IAEA,2CAAe","sources":["src/main.js","src/defaultSettings.js","src/assetLoader.js","src/observer.js","src/getElements.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.7\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultSettings from './defaultSettings.js';\nimport loadAsset from './assetLoader.js';\nimport observer from './observer.js';\nimport { getElements } from './getElements.js';\n\nconst lazyLoad = (selector, customSettings = {}) => {\n const settings = { ...defaultSettings, ...customSettings };\n const lazyItems = getElements(selector);\n\n if (!lazyItems.length) return console.warn('No lazy loadable element found!');\n\n const observerCallback = (target) => {\n try {\n settings.onLoading(target);\n loadAsset(target, settings);\n } catch (error) {\n settings.onError(target, error.message);\n }\n };\n\n lazyItems.forEach((item) =>\n observer(item, observerCallback, settings.observer)\n );\n};\n\nexport default lazyLoad;\n","const defaultSettings = {\n attrs: {\n src: 'lazy',\n srcset: 'lazy-srcset',\n poster: 'lazy-poster',\n },\n modifiers: {\n loaded: '-loaded',\n loading: '-loading',\n },\n onLoaded: () => {},\n onLoading: () => {},\n onError: (element, error) => console.warn('Error on:', element, error),\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n};\n\nexport default defaultSettings;\n","const regularLoad = (element, assets) => {\n element.src = assets.src;\n};\n\nconst loadImage = (element, assets) => {\n element.src = assets.src;\n if (assets.srcset) element.srcset = assets.srcset;\n};\n\nconst loadVideo = (element, assets) => {\n element.src = assets.src;\n\n if (assets.poster) element.poster = assets.poster;\n};\n\nconst loadPicture = (element, assets) => {\n let img = element.querySelector('img');\n\n if (!img) {\n img = document.createElement('img');\n element.appendChild(img);\n }\n\n loadImage(img, assets);\n};\n\nconst assetLoaders = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n iframe: regularLoad,\n embed: regularLoad,\n object: regularLoad,\n};\n\nconst loadAsset = (element, settings) => {\n const elementType = element.tagName.toLowerCase();\n const assetLoader = assetLoaders[elementType];\n\n if (!assetLoader) {\n throw new Error(`Element type '${elementType}' is not supported!`);\n }\n\n const assets = {\n src: element.getAttribute(settings.attrs.src),\n srcset: element.getAttribute(settings.attrs.srcset),\n poster: element.getAttribute(settings.attrs.poster),\n };\n\n const handleLoadEvent = () => {\n element.classList.remove(settings.modifiers.loading);\n element.classList.add(settings.modifiers.loaded);\n\n element.removeAttribute(settings.attrs.src);\n element.removeAttribute(settings.attrs.srcset);\n element.removeAttribute(settings.attrs.poster);\n\n settings.onLoaded(element);\n };\n\n assetLoader(element, assets);\n\n element.classList.add(settings.modifiers.loading);\n element.addEventListener('load', handleLoadEvent, { once: true });\n};\n\nexport default loadAsset;\n","const observer = (item, callback, settings) => {\n const observer = new IntersectionObserver((entries) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n\n callback(entry.target);\n observer.unobserve(entry.target);\n });\n }, settings);\n\n observer.observe(item);\n};\n\nexport default observer;\n","const getElements = (selector, root = document) => {\n if (selector instanceof Element) return [selector];\n if (selector instanceof NodeList) return selector;\n if (selector instanceof Array) return selector;\n\n return root.querySelectorAll(selector);\n};\n\nexport { getElements };\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file From f002f5b85c2b78832d3a8ecff94c025002b4e1f4 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 8 Nov 2023 22:24:43 +0300 Subject: [PATCH 098/185] Update: Use default export --- src/getElements.js | 2 +- src/main.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/getElements.js b/src/getElements.js index 558fec6..ca6f9c9 100644 --- a/src/getElements.js +++ b/src/getElements.js @@ -6,4 +6,4 @@ const getElements = (selector, root = document) => { return root.querySelectorAll(selector); }; -export { getElements }; +export default getElements; diff --git a/src/main.js b/src/main.js index 33b44f9..6df64cc 100644 --- a/src/main.js +++ b/src/main.js @@ -11,7 +11,7 @@ import defaultSettings from './defaultSettings.js'; import loadAsset from './assetLoader.js'; import observer from './observer.js'; -import { getElements } from './getElements.js'; +import getElements from './getElements.js'; const lazyLoad = (selector, customSettings = {}) => { const settings = { ...defaultSettings, ...customSettings }; From 3335c18f415b2af14ce129d2611d8beec2809bdb Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Fri, 24 Nov 2023 23:32:58 +0300 Subject: [PATCH 099/185] Refactor lazy loading implementation --- dist/lazy-load.js | 52 +++++++++++++++++++----------------------- dist/lazy-load.js.map | 2 +- src/assetLoader.js | 9 +------- src/defaultSettings.js | 4 +--- src/getElements.js | 4 +--- src/main.js | 4 +--- src/observer.js | 4 +--- 7 files changed, 30 insertions(+), 49 deletions(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index bbb05e5..0801a58 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -6,7 +6,7 @@ * @version 1.0.7 * @license MIT * @see {@link https://github.com/drementer/lazy-load.js} - */ const $eca09eba1a2796e9$var$defaultSettings = { + */ var $9be491445886d637$export$2e2bcd8739ae039 = { attrs: { src: "lazy", srcset: "lazy-srcset", @@ -25,40 +25,38 @@ rootMargin: "100% 0px" } }; -var $eca09eba1a2796e9$export$2e2bcd8739ae039 = $eca09eba1a2796e9$var$defaultSettings; -const $fa423858cf60d4ae$var$regularLoad = (element, assets)=>{ +const $f85e789b098d4f3c$var$regularLoad = (element, assets)=>{ element.src = assets.src; }; -const $fa423858cf60d4ae$var$loadImage = (element, assets)=>{ +const $f85e789b098d4f3c$var$loadImage = (element, assets)=>{ element.src = assets.src; if (assets.srcset) element.srcset = assets.srcset; }; -const $fa423858cf60d4ae$var$loadVideo = (element, assets)=>{ +const $f85e789b098d4f3c$var$loadVideo = (element, assets)=>{ element.src = assets.src; if (assets.poster) element.poster = assets.poster; }; -const $fa423858cf60d4ae$var$loadPicture = (element, assets)=>{ +const $f85e789b098d4f3c$var$loadPicture = (element, assets)=>{ let img = element.querySelector("img"); if (!img) { img = document.createElement("img"); element.appendChild(img); } - $fa423858cf60d4ae$var$loadImage(img, assets); + $f85e789b098d4f3c$var$loadImage(img, assets); }; -const $fa423858cf60d4ae$var$assetLoaders = { - img: $fa423858cf60d4ae$var$loadImage, - picture: $fa423858cf60d4ae$var$loadPicture, - video: $fa423858cf60d4ae$var$loadVideo, - iframe: $fa423858cf60d4ae$var$regularLoad, - embed: $fa423858cf60d4ae$var$regularLoad, - object: $fa423858cf60d4ae$var$regularLoad +const $f85e789b098d4f3c$var$assetLoaders = { + img: $f85e789b098d4f3c$var$loadImage, + picture: $f85e789b098d4f3c$var$loadPicture, + video: $f85e789b098d4f3c$var$loadVideo, + iframe: $f85e789b098d4f3c$var$regularLoad, + embed: $f85e789b098d4f3c$var$regularLoad, + object: $f85e789b098d4f3c$var$regularLoad }; -const $fa423858cf60d4ae$var$loadAsset = (element, settings)=>{ +var $f85e789b098d4f3c$export$2e2bcd8739ae039 = (element, settings)=>{ const elementType = element.tagName.toLowerCase(); - const assetLoader = $fa423858cf60d4ae$var$assetLoaders[elementType]; - if (!assetLoader) throw new Error(`Element type '${elementType}' is not supported!`); + const assetLoader = $f85e789b098d4f3c$var$assetLoaders[elementType]; const assets = { src: element.getAttribute(settings.attrs.src), srcset: element.getAttribute(settings.attrs.srcset), @@ -78,10 +76,9 @@ const $fa423858cf60d4ae$var$loadAsset = (element, settings)=>{ once: true }); }; -var $fa423858cf60d4ae$export$2e2bcd8739ae039 = $fa423858cf60d4ae$var$loadAsset; -const $5aa3f28da5200ea6$var$observer = (item, callback, settings)=>{ +var $726175a518dac223$export$2e2bcd8739ae039 = (item, callback, settings)=>{ const observer = new IntersectionObserver((entries)=>{ entries.forEach((entry)=>{ if (!entry.isIntersecting) return; @@ -91,10 +88,9 @@ const $5aa3f28da5200ea6$var$observer = (item, callback, settings)=>{ }, settings); observer.observe(item); }; -var $5aa3f28da5200ea6$export$2e2bcd8739ae039 = $5aa3f28da5200ea6$var$observer; -const $e5a64a9b43e3c02c$export$73eac51a39d6b0eb = (selector, root = document)=>{ +var $c64ba146cb242d62$export$2e2bcd8739ae039 = (selector, root = document)=>{ if (selector instanceof Element) return [ selector ]; @@ -104,24 +100,24 @@ const $e5a64a9b43e3c02c$export$73eac51a39d6b0eb = (selector, root = document)=>{ }; -const $d582dd6eaccab18d$var$lazyLoad = (selector, customSettings = {})=>{ +var $a118670bf7476f3e$export$2e2bcd8739ae039 = (selector, customSettings = {})=>{ const settings = { - ...(0, $eca09eba1a2796e9$export$2e2bcd8739ae039), + ...(0, $9be491445886d637$export$2e2bcd8739ae039), ...customSettings }; - const lazyItems = (0, $e5a64a9b43e3c02c$export$73eac51a39d6b0eb)(selector); + const lazyItems = (0, $c64ba146cb242d62$export$2e2bcd8739ae039)(selector); if (!lazyItems.length) return console.warn("No lazy loadable element found!"); const observerCallback = (target)=>{ try { settings.onLoading(target); - (0, $fa423858cf60d4ae$export$2e2bcd8739ae039)(target, settings); + (0, $f85e789b098d4f3c$export$2e2bcd8739ae039)(target, settings); } catch (error) { settings.onError(target, error.message); } }; - lazyItems.forEach((item)=>(0, $5aa3f28da5200ea6$export$2e2bcd8739ae039)(item, observerCallback, settings.observer)); + lazyItems.forEach((item)=>(0, $726175a518dac223$export$2e2bcd8739ae039)(item, observerCallback, settings.observer)); }; -var $d582dd6eaccab18d$export$2e2bcd8739ae039 = $d582dd6eaccab18d$var$lazyLoad; -export {$d582dd6eaccab18d$export$2e2bcd8739ae039 as default}; +export {$a118670bf7476f3e$export$2e2bcd8739ae039 as default}; +//# sourceMappingURL=lazy-load.js.map diff --git a/dist/lazy-load.js.map b/dist/lazy-load.js.map index 4866e4e..2dff4e5 100644 --- a/dist/lazy-load.js.map +++ b/dist/lazy-load.js.map @@ -1 +1 @@ -{"mappings":"AAAA;;;;;;;;ACAA,MAAM,wCAAkB;IACtB,OAAO;QACL,KAAK;QACL,QAAQ;QACR,QAAQ;IACV;IACA,WAAW;QACT,QAAQ;QACR,SAAS;IACX;IACA,UAAU,KAAO;IACjB,WAAW,KAAO;IAClB,SAAS,CAAC,SAAS,QAAU,QAAQ,KAAK,aAAa,SAAS;IAChE,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;IAEA,2CAAe;;CDZd;AERD,MAAM,oCAAc,CAAC,SAAS;IAC5B,QAAQ,MAAM,OAAO;AACvB;AAEA,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM,OAAO;IACrB,IAAI,OAAO,QAAQ,QAAQ,SAAS,OAAO;AAC7C;AAEA,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM,OAAO;IAErB,IAAI,OAAO,QAAQ,QAAQ,SAAS,OAAO;AAC7C;AAEA,MAAM,oCAAc,CAAC,SAAS;IAC5B,IAAI,MAAM,QAAQ,cAAc;IAEhC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,YAAY;IACtB;IAEA,gCAAU,KAAK;AACjB;AAEA,MAAM,qCAAe;IACnB,KAAK;IACL,SAAS;IACT,OAAO;IACP,QAAQ;IACR,OAAO;IACP,QAAQ;AACV;AAEA,MAAM,kCAAY,CAAC,SAAS;IAC1B,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,cAAc,kCAAY,CAAC,YAAY;IAE7C,IAAI,CAAC,aACH,MAAM,IAAI,MAAM,CAAC,cAAc,EAAE,YAAY,mBAAmB,CAAC;IAGnE,MAAM,SAAS;QACb,KAAK,QAAQ,aAAa,SAAS,MAAM;QACzC,QAAQ,QAAQ,aAAa,SAAS,MAAM;QAC5C,QAAQ,QAAQ,aAAa,SAAS,MAAM;IAC9C;IAEA,MAAM,kBAAkB;QACtB,QAAQ,UAAU,OAAO,SAAS,UAAU;QAC5C,QAAQ,UAAU,IAAI,SAAS,UAAU;QAEzC,QAAQ,gBAAgB,SAAS,MAAM;QACvC,QAAQ,gBAAgB,SAAS,MAAM;QACvC,QAAQ,gBAAgB,SAAS,MAAM;QAEvC,SAAS,SAAS;IACpB;IAEA,YAAY,SAAS;IAErB,QAAQ,UAAU,IAAI,SAAS,UAAU;IACzC,QAAQ,iBAAiB,QAAQ,iBAAiB;QAAE,MAAM;IAAK;AACjE;IAEA,2CAAe;;;AClEf,MAAM,iCAAW,CAAC,MAAM,UAAU;IAChC,MAAM,WAAW,IAAI,qBAAqB,CAAC;QACzC,QAAQ,QAAQ,CAAC;YACf,IAAI,CAAC,MAAM,gBAAgB;YAE3B,SAAS,MAAM;YACf,SAAS,UAAU,MAAM;QAC3B;IACF,GAAG;IAEH,SAAS,QAAQ;AACnB;IAEA,2CAAe;;;ACbf,MAAM,4CAAc,CAAC,UAAU,OAAO,QAAQ;IAC5C,IAAI,oBAAoB,SAAS,OAAO;QAAC;KAAS;IAClD,IAAI,oBAAoB,UAAU,OAAO;IACzC,IAAI,oBAAoB,OAAO,OAAO;IAEtC,OAAO,KAAK,iBAAiB;AAC/B;;;AJSA,MAAM,iCAAW,CAAC,UAAU,iBAAiB,CAAC,CAAC;IAC7C,MAAM,WAAW;QAAE,GAAG,CAAA,GAAA,wCAAc,CAAC;QAAE,GAAG,cAAc;IAAC;IACzD,MAAM,YAAY,CAAA,GAAA,yCAAU,EAAE;IAE9B,IAAI,CAAC,UAAU,QAAQ,OAAO,QAAQ,KAAK;IAE3C,MAAM,mBAAmB,CAAC;QACxB,IAAI;YACF,SAAS,UAAU;YACnB,CAAA,GAAA,wCAAQ,EAAE,QAAQ;QACpB,EAAE,OAAO,OAAO;YACd,SAAS,QAAQ,QAAQ,MAAM;QACjC;IACF;IAEA,UAAU,QAAQ,CAAC,OACjB,CAAA,GAAA,wCAAO,EAAE,MAAM,kBAAkB,SAAS;AAE9C;IAEA,2CAAe","sources":["src/main.js","src/defaultSettings.js","src/assetLoader.js","src/observer.js","src/getElements.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.7\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultSettings from './defaultSettings.js';\nimport loadAsset from './assetLoader.js';\nimport observer from './observer.js';\nimport { getElements } from './getElements.js';\n\nconst lazyLoad = (selector, customSettings = {}) => {\n const settings = { ...defaultSettings, ...customSettings };\n const lazyItems = getElements(selector);\n\n if (!lazyItems.length) return console.warn('No lazy loadable element found!');\n\n const observerCallback = (target) => {\n try {\n settings.onLoading(target);\n loadAsset(target, settings);\n } catch (error) {\n settings.onError(target, error.message);\n }\n };\n\n lazyItems.forEach((item) =>\n observer(item, observerCallback, settings.observer)\n );\n};\n\nexport default lazyLoad;\n","const defaultSettings = {\n attrs: {\n src: 'lazy',\n srcset: 'lazy-srcset',\n poster: 'lazy-poster',\n },\n modifiers: {\n loaded: '-loaded',\n loading: '-loading',\n },\n onLoaded: () => {},\n onLoading: () => {},\n onError: (element, error) => console.warn('Error on:', element, error),\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n};\n\nexport default defaultSettings;\n","const regularLoad = (element, assets) => {\n element.src = assets.src;\n};\n\nconst loadImage = (element, assets) => {\n element.src = assets.src;\n if (assets.srcset) element.srcset = assets.srcset;\n};\n\nconst loadVideo = (element, assets) => {\n element.src = assets.src;\n\n if (assets.poster) element.poster = assets.poster;\n};\n\nconst loadPicture = (element, assets) => {\n let img = element.querySelector('img');\n\n if (!img) {\n img = document.createElement('img');\n element.appendChild(img);\n }\n\n loadImage(img, assets);\n};\n\nconst assetLoaders = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n iframe: regularLoad,\n embed: regularLoad,\n object: regularLoad,\n};\n\nconst loadAsset = (element, settings) => {\n const elementType = element.tagName.toLowerCase();\n const assetLoader = assetLoaders[elementType];\n\n if (!assetLoader) {\n throw new Error(`Element type '${elementType}' is not supported!`);\n }\n\n const assets = {\n src: element.getAttribute(settings.attrs.src),\n srcset: element.getAttribute(settings.attrs.srcset),\n poster: element.getAttribute(settings.attrs.poster),\n };\n\n const handleLoadEvent = () => {\n element.classList.remove(settings.modifiers.loading);\n element.classList.add(settings.modifiers.loaded);\n\n element.removeAttribute(settings.attrs.src);\n element.removeAttribute(settings.attrs.srcset);\n element.removeAttribute(settings.attrs.poster);\n\n settings.onLoaded(element);\n };\n\n assetLoader(element, assets);\n\n element.classList.add(settings.modifiers.loading);\n element.addEventListener('load', handleLoadEvent, { once: true });\n};\n\nexport default loadAsset;\n","const observer = (item, callback, settings) => {\n const observer = new IntersectionObserver((entries) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n\n callback(entry.target);\n observer.unobserve(entry.target);\n });\n }, settings);\n\n observer.observe(item);\n};\n\nexport default observer;\n","const getElements = (selector, root = document) => {\n if (selector instanceof Element) return [selector];\n if (selector instanceof NodeList) return selector;\n if (selector instanceof Array) return selector;\n\n return root.querySelectorAll(selector);\n};\n\nexport { getElements };\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file +{"mappings":"AAAA;;;;;;;;ICAA,2CAAe;IACb,OAAO;QACL,KAAK;QACL,QAAQ;QACR,QAAQ;IACV;IACA,WAAW;QACT,QAAQ;QACR,SAAS;IACX;IACA,UAAU,KAAO;IACjB,WAAW,KAAO;IAClB,SAAS,CAAC,SAAS,QAAU,QAAQ,KAAK,aAAa,SAAS;IAChE,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;;CDVC;AERD,MAAM,oCAAc,CAAC,SAAS;IAC5B,QAAQ,MAAM,OAAO;AACvB;AAEA,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM,OAAO;IACrB,IAAI,OAAO,QAAQ,QAAQ,SAAS,OAAO;AAC7C;AAEA,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM,OAAO;IACrB,IAAI,OAAO,QAAQ,QAAQ,SAAS,OAAO;AAC7C;AAEA,MAAM,oCAAc,CAAC,SAAS;IAC5B,IAAI,MAAM,QAAQ,cAAc;IAEhC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,YAAY;IACtB;IAEA,gCAAU,KAAK;AACjB;AAEA,MAAM,qCAAe;IACnB,KAAK;IACL,SAAS;IACT,OAAO;IACP,QAAQ;IACR,OAAO;IACP,QAAQ;AACV;IAEA,2CAAe,CAAC,SAAS;IACvB,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,cAAc,kCAAY,CAAC,YAAY;IAE7C,MAAM,SAAS;QACb,KAAK,QAAQ,aAAa,SAAS,MAAM;QACzC,QAAQ,QAAQ,aAAa,SAAS,MAAM;QAC5C,QAAQ,QAAQ,aAAa,SAAS,MAAM;IAC9C;IAEA,MAAM,kBAAkB;QACtB,QAAQ,UAAU,OAAO,SAAS,UAAU;QAC5C,QAAQ,UAAU,IAAI,SAAS,UAAU;QAEzC,QAAQ,gBAAgB,SAAS,MAAM;QACvC,QAAQ,gBAAgB,SAAS,MAAM;QACvC,QAAQ,gBAAgB,SAAS,MAAM;QAEvC,SAAS,SAAS;IACpB;IAEA,YAAY,SAAS;IAErB,QAAQ,UAAU,IAAI,SAAS,UAAU;IACzC,QAAQ,iBAAiB,QAAQ,iBAAiB;QAAE,MAAM;IAAK;AACjE;;;IC3DA,2CAAe,CAAC,MAAM,UAAU;IAC9B,MAAM,WAAW,IAAI,qBAAqB,CAAC;QACzC,QAAQ,QAAQ,CAAC;YACf,IAAI,CAAC,MAAM,gBAAgB;YAE3B,SAAS,MAAM;YACf,SAAS,UAAU,MAAM;QAC3B;IACF,GAAG;IAEH,SAAS,QAAQ;AACnB;;;ICXA,2CAAe,CAAC,UAAU,OAAO,QAAQ;IACvC,IAAI,oBAAoB,SAAS,OAAO;QAAC;KAAS;IAClD,IAAI,oBAAoB,UAAU,OAAO;IACzC,IAAI,oBAAoB,OAAO,OAAO;IAEtC,OAAO,KAAK,iBAAiB;AAC/B;;;IJSA,2CAAe,CAAC,UAAU,iBAAiB,CAAC,CAAC;IAC3C,MAAM,WAAW;QAAE,GAAG,CAAA,GAAA,wCAAc,CAAC;QAAE,GAAG,cAAc;IAAC;IACzD,MAAM,YAAY,CAAA,GAAA,wCAAU,EAAE;IAE9B,IAAI,CAAC,UAAU,QAAQ,OAAO,QAAQ,KAAK;IAE3C,MAAM,mBAAmB,CAAC;QACxB,IAAI;YACF,SAAS,UAAU;YACnB,CAAA,GAAA,wCAAQ,EAAE,QAAQ;QACpB,EAAE,OAAO,OAAO;YACd,SAAS,QAAQ,QAAQ,MAAM;QACjC;IACF;IAEA,UAAU,QAAQ,CAAC,OACjB,CAAA,GAAA,wCAAO,EAAE,MAAM,kBAAkB,SAAS;AAE9C","sources":["src/main.js","src/defaultSettings.js","src/assetLoader.js","src/observer.js","src/getElements.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.7\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultSettings from './defaultSettings.js';\nimport loadAsset from './assetLoader.js';\nimport observer from './observer.js';\nimport getElements from './getElements.js';\n\nexport default (selector, customSettings = {}) => {\n const settings = { ...defaultSettings, ...customSettings };\n const lazyItems = getElements(selector);\n\n if (!lazyItems.length) return console.warn('No lazy loadable element found!');\n\n const observerCallback = (target) => {\n try {\n settings.onLoading(target);\n loadAsset(target, settings);\n } catch (error) {\n settings.onError(target, error.message);\n }\n };\n\n lazyItems.forEach((item) =>\n observer(item, observerCallback, settings.observer)\n );\n};\n","export default {\n attrs: {\n src: 'lazy',\n srcset: 'lazy-srcset',\n poster: 'lazy-poster',\n },\n modifiers: {\n loaded: '-loaded',\n loading: '-loading',\n },\n onLoaded: () => {},\n onLoading: () => {},\n onError: (element, error) => console.warn('Error on:', element, error),\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n};\n","const regularLoad = (element, assets) => {\n element.src = assets.src;\n};\n\nconst loadImage = (element, assets) => {\n element.src = assets.src;\n if (assets.srcset) element.srcset = assets.srcset;\n};\n\nconst loadVideo = (element, assets) => {\n element.src = assets.src;\n if (assets.poster) element.poster = assets.poster;\n};\n\nconst loadPicture = (element, assets) => {\n let img = element.querySelector('img');\n\n if (!img) {\n img = document.createElement('img');\n element.appendChild(img);\n }\n\n loadImage(img, assets);\n};\n\nconst assetLoaders = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n iframe: regularLoad,\n embed: regularLoad,\n object: regularLoad,\n};\n\nexport default (element, settings) => {\n const elementType = element.tagName.toLowerCase();\n const assetLoader = assetLoaders[elementType];\n\n const assets = {\n src: element.getAttribute(settings.attrs.src),\n srcset: element.getAttribute(settings.attrs.srcset),\n poster: element.getAttribute(settings.attrs.poster),\n };\n\n const handleLoadEvent = () => {\n element.classList.remove(settings.modifiers.loading);\n element.classList.add(settings.modifiers.loaded);\n\n element.removeAttribute(settings.attrs.src);\n element.removeAttribute(settings.attrs.srcset);\n element.removeAttribute(settings.attrs.poster);\n\n settings.onLoaded(element);\n };\n\n assetLoader(element, assets);\n\n element.classList.add(settings.modifiers.loading);\n element.addEventListener('load', handleLoadEvent, { once: true });\n};\n","export default (item, callback, settings) => {\n const observer = new IntersectionObserver((entries) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n\n callback(entry.target);\n observer.unobserve(entry.target);\n });\n }, settings);\n\n observer.observe(item);\n};\n","export default (selector, root = document) => {\n if (selector instanceof Element) return [selector];\n if (selector instanceof NodeList) return selector;\n if (selector instanceof Array) return selector;\n\n return root.querySelectorAll(selector);\n};\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file diff --git a/src/assetLoader.js b/src/assetLoader.js index d622b73..f012de7 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -9,7 +9,6 @@ const loadImage = (element, assets) => { const loadVideo = (element, assets) => { element.src = assets.src; - if (assets.poster) element.poster = assets.poster; }; @@ -33,14 +32,10 @@ const assetLoaders = { object: regularLoad, }; -const loadAsset = (element, settings) => { +export default (element, settings) => { const elementType = element.tagName.toLowerCase(); const assetLoader = assetLoaders[elementType]; - if (!assetLoader) { - throw new Error(`Element type '${elementType}' is not supported!`); - } - const assets = { src: element.getAttribute(settings.attrs.src), srcset: element.getAttribute(settings.attrs.srcset), @@ -63,5 +58,3 @@ const loadAsset = (element, settings) => { element.classList.add(settings.modifiers.loading); element.addEventListener('load', handleLoadEvent, { once: true }); }; - -export default loadAsset; diff --git a/src/defaultSettings.js b/src/defaultSettings.js index 498090d..d917609 100644 --- a/src/defaultSettings.js +++ b/src/defaultSettings.js @@ -1,4 +1,4 @@ -const defaultSettings = { +export default { attrs: { src: 'lazy', srcset: 'lazy-srcset', @@ -17,5 +17,3 @@ const defaultSettings = { rootMargin: '100% 0px', }, }; - -export default defaultSettings; diff --git a/src/getElements.js b/src/getElements.js index ca6f9c9..bea12dc 100644 --- a/src/getElements.js +++ b/src/getElements.js @@ -1,9 +1,7 @@ -const getElements = (selector, root = document) => { +export default (selector, root = document) => { if (selector instanceof Element) return [selector]; if (selector instanceof NodeList) return selector; if (selector instanceof Array) return selector; return root.querySelectorAll(selector); }; - -export default getElements; diff --git a/src/main.js b/src/main.js index 6df64cc..ee61320 100644 --- a/src/main.js +++ b/src/main.js @@ -13,7 +13,7 @@ import loadAsset from './assetLoader.js'; import observer from './observer.js'; import getElements from './getElements.js'; -const lazyLoad = (selector, customSettings = {}) => { +export default (selector, customSettings = {}) => { const settings = { ...defaultSettings, ...customSettings }; const lazyItems = getElements(selector); @@ -32,5 +32,3 @@ const lazyLoad = (selector, customSettings = {}) => { observer(item, observerCallback, settings.observer) ); }; - -export default lazyLoad; diff --git a/src/observer.js b/src/observer.js index 3658f8c..eda21e0 100644 --- a/src/observer.js +++ b/src/observer.js @@ -1,4 +1,4 @@ -const observer = (item, callback, settings) => { +export default (item, callback, settings) => { const observer = new IntersectionObserver((entries) => { entries.forEach((entry) => { if (!entry.isIntersecting) return; @@ -10,5 +10,3 @@ const observer = (item, callback, settings) => { observer.observe(item); }; - -export default observer; From e6fadfb533c210f83921251e49a0dab915825902 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 15 Jan 2024 21:07:13 +0300 Subject: [PATCH 100/185] Update: Order of class updating --- src/assetLoader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index f012de7..5c4ba5a 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -43,8 +43,8 @@ export default (element, settings) => { }; const handleLoadEvent = () => { - element.classList.remove(settings.modifiers.loading); element.classList.add(settings.modifiers.loaded); + element.classList.remove(settings.modifiers.loading); element.removeAttribute(settings.attrs.src); element.removeAttribute(settings.attrs.srcset); From 2591513b063858d77d2ce5108272d70fedd336e5 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 15 Jan 2024 21:07:40 +0300 Subject: [PATCH 101/185] Refactor: Callback func for readable --- src/main.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.js b/src/main.js index ee61320..d11a201 100644 --- a/src/main.js +++ b/src/main.js @@ -28,7 +28,7 @@ export default (selector, customSettings = {}) => { } }; - lazyItems.forEach((item) => - observer(item, observerCallback, settings.observer) - ); + const observeItems = observer(item, observerCallback, settings.observer); + + lazyItems.forEach(observeItems); }; From 97f97917875580b1721c0a375aa770d823f101d1 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 15 Jan 2024 21:07:59 +0300 Subject: [PATCH 102/185] Refactor observer.js to use named function for handleIntersection --- src/observer.js | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/observer.js b/src/observer.js index eda21e0..0f6e36e 100644 --- a/src/observer.js +++ b/src/observer.js @@ -1,12 +1,14 @@ -export default (item, callback, settings) => { - const observer = new IntersectionObserver((entries) => { +export default function observeIntersection(item, callback, settings) { + const handleIntersection = (entries, observer) => { entries.forEach((entry) => { if (!entry.isIntersecting) return; callback(entry.target); observer.unobserve(entry.target); }); - }, settings); + }; + + const observer = new IntersectionObserver(handleIntersection, settings); observer.observe(item); -}; +} From 274f60d0ec496c32e2dd839533ae58843061d030 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 15 Jan 2024 23:30:39 +0300 Subject: [PATCH 103/185] Fix: Cant pass params --- src/main.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main.js b/src/main.js index d11a201..71cd2bd 100644 --- a/src/main.js +++ b/src/main.js @@ -28,7 +28,7 @@ export default (selector, customSettings = {}) => { } }; - const observeItems = observer(item, observerCallback, settings.observer); - - lazyItems.forEach(observeItems); + lazyItems.forEach((item) => { + observer(item, observerCallback, settings.observer); + }); }; From c3f5233142ca8a934431dac52f341e5179e29210 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 15 Jan 2024 23:31:35 +0300 Subject: [PATCH 104/185] Rename: Main file --- package.json | 2 +- src/{main.js => app.js} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename src/{main.js => app.js} (100%) diff --git a/package.json b/package.json index 436df70..e2d3e04 100644 --- a/package.json +++ b/package.json @@ -3,7 +3,7 @@ "version": "1.0.7", "homepage": "https://github.com/drementer/lazy-load.js", "description": "Loads visual content when it approaches the visible area of ​​the screen to increase page loading speed.", - "source": "src/main.js", + "source": "src/app.js", "module": "dist/lazy-load.js", "scripts": { "watch": "parcel watch", diff --git a/src/main.js b/src/app.js similarity index 100% rename from src/main.js rename to src/app.js From c2b31eefadbd638f53277594faa09bfcddb0f2e4 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 15 Jan 2024 23:32:35 +0300 Subject: [PATCH 105/185] Refactor assetLoader.js to improve code structure and readability --- src/assetLoader.js | 75 ++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 43 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index 5c4ba5a..febb9c1 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -1,59 +1,48 @@ -const regularLoad = (element, assets) => { - element.src = assets.src; +const supportedElements = [ + 'img', + 'picture', + 'video', + 'embed', + 'object', +]; + +const getAssets = (element, settings) => { + const assets = {}; + + Object.entries(settings.attrs).forEach(([key, value]) => { + assets[key] = element.getAttribute(value); + }); + + return assets; }; -const loadImage = (element, assets) => { - element.src = assets.src; - if (assets.srcset) element.srcset = assets.srcset; +const loadAssets = (element, assets) => { + Object.entries(assets).forEach(([key, value]) => { + if (value) element.setAttribute(key, value); + }); }; -const loadVideo = (element, assets) => { - element.src = assets.src; - if (assets.poster) element.poster = assets.poster; -}; - -const loadPicture = (element, assets) => { - let img = element.querySelector('img'); - - if (!img) { - img = document.createElement('img'); - element.appendChild(img); - } +const elementLoaded = (element, settings) => { + element.classList.add(settings.modifiers.loaded); + element.classList.remove(settings.modifiers.loading); - loadImage(img, assets); -}; + Object.entries(settings.attrs).forEach(([key, value]) => { + element.removeAttribute(value); + }); -const assetLoaders = { - img: loadImage, - picture: loadPicture, - video: loadVideo, - iframe: regularLoad, - embed: regularLoad, - object: regularLoad, + settings.onLoaded(element); }; export default (element, settings) => { const elementType = element.tagName.toLowerCase(); - const assetLoader = assetLoaders[elementType]; - - const assets = { - src: element.getAttribute(settings.attrs.src), - srcset: element.getAttribute(settings.attrs.srcset), - poster: element.getAttribute(settings.attrs.poster), - }; - - const handleLoadEvent = () => { - element.classList.add(settings.modifiers.loaded); - element.classList.remove(settings.modifiers.loading); + const isSupported = supportedElements.includes(elementType); - element.removeAttribute(settings.attrs.src); - element.removeAttribute(settings.attrs.srcset); - element.removeAttribute(settings.attrs.poster); + if (!isSupported) return console.log('Element not supported!', element); - settings.onLoaded(element); - }; + const assets = getAssets(element, settings); + const handleLoadEvent = () => elementLoaded(element, settings); - assetLoader(element, assets); + loadAssets(element, assets); element.classList.add(settings.modifiers.loading); element.addEventListener('load', handleLoadEvent, { once: true }); From d8fdfb3fec9437bbc93319a92ce670ac01b6110e Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 15 Jan 2024 23:33:26 +0300 Subject: [PATCH 106/185] Update: Test file --- test/index.html | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/test/index.html b/test/index.html index 4ef6ad6..dc9026c 100644 --- a/test/index.html +++ b/test/index.html @@ -10,8 +10,10 @@ - Random Image +
+ + Random Image Random Image Random Image Random Image From 5dbc347ef2fbd7382e9aa49339886306a237c717 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 15 Jan 2024 23:34:33 +0300 Subject: [PATCH 107/185] Add z-index to img::after element --- test/style.css | 1 + 1 file changed, 1 insertion(+) diff --git a/test/style.css b/test/style.css index e6ce6a0..1be855d 100644 --- a/test/style.css +++ b/test/style.css @@ -11,6 +11,7 @@ img { border-radius: 10px; } img::after { + z-index: -1; content: ''; position: absolute; From 3662ea3294cb5f4fd6983b2f208d5ae9ed20101f Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 15 Jan 2024 23:57:38 +0300 Subject: [PATCH 108/185] Refactor assetLoader.js to improve code readability and remove unnecessary code --- src/assetLoader.js | 38 +++++++++++++------------------------- 1 file changed, 13 insertions(+), 25 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index febb9c1..896d1b0 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -1,34 +1,18 @@ -const supportedElements = [ - 'img', - 'picture', - 'video', - 'embed', - 'object', -]; - -const getAssets = (element, settings) => { - const assets = {}; - - Object.entries(settings.attrs).forEach(([key, value]) => { - assets[key] = element.getAttribute(value); - }); - - return assets; -}; +const supportedElements = ['img', 'picture', 'video', 'embed', 'object']; const loadAssets = (element, assets) => { - Object.entries(assets).forEach(([key, value]) => { - if (value) element.setAttribute(key, value); - }); + if (assets.src) element.setAttribute('src', assets.src); + if (assets.srcset) element.setAttribute('srcset', assets.srcset); + if (assets.poster) element.setAttribute('poster', assets.poster); }; const elementLoaded = (element, settings) => { element.classList.add(settings.modifiers.loaded); element.classList.remove(settings.modifiers.loading); - Object.entries(settings.attrs).forEach(([key, value]) => { - element.removeAttribute(value); - }); + element.removeAttribute(settings.attrs.src); + element.removeAttribute(settings.attrs.srcset); + element.removeAttribute(settings.attrs.poster); settings.onLoaded(element); }; @@ -37,9 +21,13 @@ export default (element, settings) => { const elementType = element.tagName.toLowerCase(); const isSupported = supportedElements.includes(elementType); - if (!isSupported) return console.log('Element not supported!', element); + if (!isSupported) return console.warn('Element not supported!', element); - const assets = getAssets(element, settings); + const assets = { + src: element.getAttribute(settings.attrs.src), + srcset: element.getAttribute(settings.attrs.srcset), + poster: element.getAttribute(settings.attrs.poster), + }; const handleLoadEvent = () => elementLoaded(element, settings); loadAssets(element, assets); From a114470fca034b22c794591772d125ac9f3d2914 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 15 Jan 2024 23:58:06 +0300 Subject: [PATCH 109/185] Production --- dist/lazy-load.js | 87 +++++++++++++++++++------------------------ dist/lazy-load.js.map | 2 +- 2 files changed, 39 insertions(+), 50 deletions(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index 0801a58..745213d 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -6,7 +6,7 @@ * @version 1.0.7 * @license MIT * @see {@link https://github.com/drementer/lazy-load.js} - */ var $9be491445886d637$export$2e2bcd8739ae039 = { + */ var $eca09eba1a2796e9$export$2e2bcd8739ae039 = { attrs: { src: "lazy", srcset: "lazy-srcset", @@ -27,50 +27,37 @@ }; -const $f85e789b098d4f3c$var$regularLoad = (element, assets)=>{ - element.src = assets.src; +const $fa423858cf60d4ae$var$supportedElements = [ + "img", + "picture", + "video", + "embed", + "object" +]; +const $fa423858cf60d4ae$var$loadAssets = (element, assets)=>{ + if (assets.src) element.setAttribute("src", assets.src); + if (assets.srcset) element.setAttribute("srcset", assets.srcset); + if (assets.poster) element.setAttribute("poster", assets.poster); }; -const $f85e789b098d4f3c$var$loadImage = (element, assets)=>{ - element.src = assets.src; - if (assets.srcset) element.srcset = assets.srcset; +const $fa423858cf60d4ae$var$elementLoaded = (element, settings)=>{ + element.classList.add(settings.modifiers.loaded); + element.classList.remove(settings.modifiers.loading); + element.removeAttribute(settings.attrs.src); + element.removeAttribute(settings.attrs.srcset); + element.removeAttribute(settings.attrs.poster); + settings.onLoaded(element); }; -const $f85e789b098d4f3c$var$loadVideo = (element, assets)=>{ - element.src = assets.src; - if (assets.poster) element.poster = assets.poster; -}; -const $f85e789b098d4f3c$var$loadPicture = (element, assets)=>{ - let img = element.querySelector("img"); - if (!img) { - img = document.createElement("img"); - element.appendChild(img); - } - $f85e789b098d4f3c$var$loadImage(img, assets); -}; -const $f85e789b098d4f3c$var$assetLoaders = { - img: $f85e789b098d4f3c$var$loadImage, - picture: $f85e789b098d4f3c$var$loadPicture, - video: $f85e789b098d4f3c$var$loadVideo, - iframe: $f85e789b098d4f3c$var$regularLoad, - embed: $f85e789b098d4f3c$var$regularLoad, - object: $f85e789b098d4f3c$var$regularLoad -}; -var $f85e789b098d4f3c$export$2e2bcd8739ae039 = (element, settings)=>{ +var $fa423858cf60d4ae$export$2e2bcd8739ae039 = (element, settings)=>{ const elementType = element.tagName.toLowerCase(); - const assetLoader = $f85e789b098d4f3c$var$assetLoaders[elementType]; + const isSupported = $fa423858cf60d4ae$var$supportedElements.includes(elementType); + if (!isSupported) return console.warn("Element not supported!", element); const assets = { src: element.getAttribute(settings.attrs.src), srcset: element.getAttribute(settings.attrs.srcset), poster: element.getAttribute(settings.attrs.poster) }; - const handleLoadEvent = ()=>{ - element.classList.remove(settings.modifiers.loading); - element.classList.add(settings.modifiers.loaded); - element.removeAttribute(settings.attrs.src); - element.removeAttribute(settings.attrs.srcset); - element.removeAttribute(settings.attrs.poster); - settings.onLoaded(element); - }; - assetLoader(element, assets); + const handleLoadEvent = ()=>$fa423858cf60d4ae$var$elementLoaded(element, settings); + $fa423858cf60d4ae$var$loadAssets(element, assets); element.classList.add(settings.modifiers.loading); element.addEventListener("load", handleLoadEvent, { once: true @@ -78,19 +65,20 @@ var $f85e789b098d4f3c$export$2e2bcd8739ae039 = (element, settings)=>{ }; -var $726175a518dac223$export$2e2bcd8739ae039 = (item, callback, settings)=>{ - const observer = new IntersectionObserver((entries)=>{ +function $5aa3f28da5200ea6$export$2e2bcd8739ae039(item, callback, settings) { + const handleIntersection = (entries, observer)=>{ entries.forEach((entry)=>{ if (!entry.isIntersecting) return; callback(entry.target); observer.unobserve(entry.target); }); - }, settings); + }; + const observer = new IntersectionObserver(handleIntersection, settings); observer.observe(item); -}; +} -var $c64ba146cb242d62$export$2e2bcd8739ae039 = (selector, root = document)=>{ +var $e5a64a9b43e3c02c$export$2e2bcd8739ae039 = (selector, root = document)=>{ if (selector instanceof Element) return [ selector ]; @@ -100,24 +88,25 @@ var $c64ba146cb242d62$export$2e2bcd8739ae039 = (selector, root = document)=>{ }; -var $a118670bf7476f3e$export$2e2bcd8739ae039 = (selector, customSettings = {})=>{ +var $3e2aed16982f049f$export$2e2bcd8739ae039 = (selector, customSettings = {})=>{ const settings = { - ...(0, $9be491445886d637$export$2e2bcd8739ae039), + ...(0, $eca09eba1a2796e9$export$2e2bcd8739ae039), ...customSettings }; - const lazyItems = (0, $c64ba146cb242d62$export$2e2bcd8739ae039)(selector); + const lazyItems = (0, $e5a64a9b43e3c02c$export$2e2bcd8739ae039)(selector); if (!lazyItems.length) return console.warn("No lazy loadable element found!"); const observerCallback = (target)=>{ try { settings.onLoading(target); - (0, $f85e789b098d4f3c$export$2e2bcd8739ae039)(target, settings); + (0, $fa423858cf60d4ae$export$2e2bcd8739ae039)(target, settings); } catch (error) { settings.onError(target, error.message); } }; - lazyItems.forEach((item)=>(0, $726175a518dac223$export$2e2bcd8739ae039)(item, observerCallback, settings.observer)); + lazyItems.forEach((item)=>{ + (0, $5aa3f28da5200ea6$export$2e2bcd8739ae039)(item, observerCallback, settings.observer); + }); }; -export {$a118670bf7476f3e$export$2e2bcd8739ae039 as default}; -//# sourceMappingURL=lazy-load.js.map +export {$3e2aed16982f049f$export$2e2bcd8739ae039 as default}; diff --git a/dist/lazy-load.js.map b/dist/lazy-load.js.map index 2dff4e5..d820dd4 100644 --- a/dist/lazy-load.js.map +++ b/dist/lazy-load.js.map @@ -1 +1 @@ -{"mappings":"AAAA;;;;;;;;ICAA,2CAAe;IACb,OAAO;QACL,KAAK;QACL,QAAQ;QACR,QAAQ;IACV;IACA,WAAW;QACT,QAAQ;QACR,SAAS;IACX;IACA,UAAU,KAAO;IACjB,WAAW,KAAO;IAClB,SAAS,CAAC,SAAS,QAAU,QAAQ,KAAK,aAAa,SAAS;IAChE,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;;CDVC;AERD,MAAM,oCAAc,CAAC,SAAS;IAC5B,QAAQ,MAAM,OAAO;AACvB;AAEA,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM,OAAO;IACrB,IAAI,OAAO,QAAQ,QAAQ,SAAS,OAAO;AAC7C;AAEA,MAAM,kCAAY,CAAC,SAAS;IAC1B,QAAQ,MAAM,OAAO;IACrB,IAAI,OAAO,QAAQ,QAAQ,SAAS,OAAO;AAC7C;AAEA,MAAM,oCAAc,CAAC,SAAS;IAC5B,IAAI,MAAM,QAAQ,cAAc;IAEhC,IAAI,CAAC,KAAK;QACR,MAAM,SAAS,cAAc;QAC7B,QAAQ,YAAY;IACtB;IAEA,gCAAU,KAAK;AACjB;AAEA,MAAM,qCAAe;IACnB,KAAK;IACL,SAAS;IACT,OAAO;IACP,QAAQ;IACR,OAAO;IACP,QAAQ;AACV;IAEA,2CAAe,CAAC,SAAS;IACvB,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,cAAc,kCAAY,CAAC,YAAY;IAE7C,MAAM,SAAS;QACb,KAAK,QAAQ,aAAa,SAAS,MAAM;QACzC,QAAQ,QAAQ,aAAa,SAAS,MAAM;QAC5C,QAAQ,QAAQ,aAAa,SAAS,MAAM;IAC9C;IAEA,MAAM,kBAAkB;QACtB,QAAQ,UAAU,OAAO,SAAS,UAAU;QAC5C,QAAQ,UAAU,IAAI,SAAS,UAAU;QAEzC,QAAQ,gBAAgB,SAAS,MAAM;QACvC,QAAQ,gBAAgB,SAAS,MAAM;QACvC,QAAQ,gBAAgB,SAAS,MAAM;QAEvC,SAAS,SAAS;IACpB;IAEA,YAAY,SAAS;IAErB,QAAQ,UAAU,IAAI,SAAS,UAAU;IACzC,QAAQ,iBAAiB,QAAQ,iBAAiB;QAAE,MAAM;IAAK;AACjE;;;IC3DA,2CAAe,CAAC,MAAM,UAAU;IAC9B,MAAM,WAAW,IAAI,qBAAqB,CAAC;QACzC,QAAQ,QAAQ,CAAC;YACf,IAAI,CAAC,MAAM,gBAAgB;YAE3B,SAAS,MAAM;YACf,SAAS,UAAU,MAAM;QAC3B;IACF,GAAG;IAEH,SAAS,QAAQ;AACnB;;;ICXA,2CAAe,CAAC,UAAU,OAAO,QAAQ;IACvC,IAAI,oBAAoB,SAAS,OAAO;QAAC;KAAS;IAClD,IAAI,oBAAoB,UAAU,OAAO;IACzC,IAAI,oBAAoB,OAAO,OAAO;IAEtC,OAAO,KAAK,iBAAiB;AAC/B;;;IJSA,2CAAe,CAAC,UAAU,iBAAiB,CAAC,CAAC;IAC3C,MAAM,WAAW;QAAE,GAAG,CAAA,GAAA,wCAAc,CAAC;QAAE,GAAG,cAAc;IAAC;IACzD,MAAM,YAAY,CAAA,GAAA,wCAAU,EAAE;IAE9B,IAAI,CAAC,UAAU,QAAQ,OAAO,QAAQ,KAAK;IAE3C,MAAM,mBAAmB,CAAC;QACxB,IAAI;YACF,SAAS,UAAU;YACnB,CAAA,GAAA,wCAAQ,EAAE,QAAQ;QACpB,EAAE,OAAO,OAAO;YACd,SAAS,QAAQ,QAAQ,MAAM;QACjC;IACF;IAEA,UAAU,QAAQ,CAAC,OACjB,CAAA,GAAA,wCAAO,EAAE,MAAM,kBAAkB,SAAS;AAE9C","sources":["src/main.js","src/defaultSettings.js","src/assetLoader.js","src/observer.js","src/getElements.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.7\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultSettings from './defaultSettings.js';\nimport loadAsset from './assetLoader.js';\nimport observer from './observer.js';\nimport getElements from './getElements.js';\n\nexport default (selector, customSettings = {}) => {\n const settings = { ...defaultSettings, ...customSettings };\n const lazyItems = getElements(selector);\n\n if (!lazyItems.length) return console.warn('No lazy loadable element found!');\n\n const observerCallback = (target) => {\n try {\n settings.onLoading(target);\n loadAsset(target, settings);\n } catch (error) {\n settings.onError(target, error.message);\n }\n };\n\n lazyItems.forEach((item) =>\n observer(item, observerCallback, settings.observer)\n );\n};\n","export default {\n attrs: {\n src: 'lazy',\n srcset: 'lazy-srcset',\n poster: 'lazy-poster',\n },\n modifiers: {\n loaded: '-loaded',\n loading: '-loading',\n },\n onLoaded: () => {},\n onLoading: () => {},\n onError: (element, error) => console.warn('Error on:', element, error),\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n};\n","const regularLoad = (element, assets) => {\n element.src = assets.src;\n};\n\nconst loadImage = (element, assets) => {\n element.src = assets.src;\n if (assets.srcset) element.srcset = assets.srcset;\n};\n\nconst loadVideo = (element, assets) => {\n element.src = assets.src;\n if (assets.poster) element.poster = assets.poster;\n};\n\nconst loadPicture = (element, assets) => {\n let img = element.querySelector('img');\n\n if (!img) {\n img = document.createElement('img');\n element.appendChild(img);\n }\n\n loadImage(img, assets);\n};\n\nconst assetLoaders = {\n img: loadImage,\n picture: loadPicture,\n video: loadVideo,\n iframe: regularLoad,\n embed: regularLoad,\n object: regularLoad,\n};\n\nexport default (element, settings) => {\n const elementType = element.tagName.toLowerCase();\n const assetLoader = assetLoaders[elementType];\n\n const assets = {\n src: element.getAttribute(settings.attrs.src),\n srcset: element.getAttribute(settings.attrs.srcset),\n poster: element.getAttribute(settings.attrs.poster),\n };\n\n const handleLoadEvent = () => {\n element.classList.remove(settings.modifiers.loading);\n element.classList.add(settings.modifiers.loaded);\n\n element.removeAttribute(settings.attrs.src);\n element.removeAttribute(settings.attrs.srcset);\n element.removeAttribute(settings.attrs.poster);\n\n settings.onLoaded(element);\n };\n\n assetLoader(element, assets);\n\n element.classList.add(settings.modifiers.loading);\n element.addEventListener('load', handleLoadEvent, { once: true });\n};\n","export default (item, callback, settings) => {\n const observer = new IntersectionObserver((entries) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n\n callback(entry.target);\n observer.unobserve(entry.target);\n });\n }, settings);\n\n observer.observe(item);\n};\n","export default (selector, root = document) => {\n if (selector instanceof Element) return [selector];\n if (selector instanceof NodeList) return selector;\n if (selector instanceof Array) return selector;\n\n return root.querySelectorAll(selector);\n};\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file +{"mappings":"AAAA;;;;;;;;ICAA,2CAAe;IACb,OAAO;QACL,KAAK;QACL,QAAQ;QACR,QAAQ;IACV;IACA,WAAW;QACT,QAAQ;QACR,SAAS;IACX;IACA,UAAU,KAAO;IACjB,WAAW,KAAO;IAClB,SAAS,CAAC,SAAS,QAAU,QAAQ,KAAK,aAAa,SAAS;IAChE,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;;CDVC;AERD,MAAM,0CAAoB;IAAC;IAAO;IAAW;IAAS;IAAS;CAAS;AAExE,MAAM,mCAAa,CAAC,SAAS;IAC3B,IAAI,OAAO,KAAK,QAAQ,aAAa,OAAO,OAAO;IACnD,IAAI,OAAO,QAAQ,QAAQ,aAAa,UAAU,OAAO;IACzD,IAAI,OAAO,QAAQ,QAAQ,aAAa,UAAU,OAAO;AAC3D;AAEA,MAAM,sCAAgB,CAAC,SAAS;IAC9B,QAAQ,UAAU,IAAI,SAAS,UAAU;IACzC,QAAQ,UAAU,OAAO,SAAS,UAAU;IAE5C,QAAQ,gBAAgB,SAAS,MAAM;IACvC,QAAQ,gBAAgB,SAAS,MAAM;IACvC,QAAQ,gBAAgB,SAAS,MAAM;IAEvC,SAAS,SAAS;AACpB;IAEA,2CAAe,CAAC,SAAS;IACvB,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,cAAc,wCAAkB,SAAS;IAE/C,IAAI,CAAC,aAAa,OAAO,QAAQ,KAAK,0BAA0B;IAEhE,MAAM,SAAS;QACb,KAAK,QAAQ,aAAa,SAAS,MAAM;QACzC,QAAQ,QAAQ,aAAa,SAAS,MAAM;QAC5C,QAAQ,QAAQ,aAAa,SAAS,MAAM;IAC9C;IACA,MAAM,kBAAkB,IAAM,oCAAc,SAAS;IAErD,iCAAW,SAAS;IAEpB,QAAQ,UAAU,IAAI,SAAS,UAAU;IACzC,QAAQ,iBAAiB,QAAQ,iBAAiB;QAAE,MAAM;IAAK;AACjE;;;ACpCe,kDAA6B,IAAI,EAAE,QAAQ,EAAE,QAAQ;IAClE,MAAM,qBAAqB,CAAC,SAAS;QACnC,QAAQ,QAAQ,CAAC;YACf,IAAI,CAAC,MAAM,gBAAgB;YAE3B,SAAS,MAAM;YACf,SAAS,UAAU,MAAM;QAC3B;IACF;IAEA,MAAM,WAAW,IAAI,qBAAqB,oBAAoB;IAE9D,SAAS,QAAQ;AACnB;;;ICbA,2CAAe,CAAC,UAAU,OAAO,QAAQ;IACvC,IAAI,oBAAoB,SAAS,OAAO;QAAC;KAAS;IAClD,IAAI,oBAAoB,UAAU,OAAO;IACzC,IAAI,oBAAoB,OAAO,OAAO;IAEtC,OAAO,KAAK,iBAAiB;AAC/B;;;IJSA,2CAAe,CAAC,UAAU,iBAAiB,CAAC,CAAC;IAC3C,MAAM,WAAW;QAAE,GAAG,CAAA,GAAA,wCAAc,CAAC;QAAE,GAAG,cAAc;IAAC;IACzD,MAAM,YAAY,CAAA,GAAA,wCAAU,EAAE;IAE9B,IAAI,CAAC,UAAU,QAAQ,OAAO,QAAQ,KAAK;IAE3C,MAAM,mBAAmB,CAAC;QACxB,IAAI;YACF,SAAS,UAAU;YACnB,CAAA,GAAA,wCAAQ,EAAE,QAAQ;QACpB,EAAE,OAAO,OAAO;YACd,SAAS,QAAQ,QAAQ,MAAM;QACjC;IACF;IAEA,UAAU,QAAQ,CAAC;QACjB,CAAA,GAAA,wCAAO,EAAE,MAAM,kBAAkB,SAAS;IAC5C;AACF","sources":["src/app.js","src/defaultSettings.js","src/assetLoader.js","src/observer.js","src/getElements.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.7\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultSettings from './defaultSettings.js';\nimport loadAsset from './assetLoader.js';\nimport observer from './observer.js';\nimport getElements from './getElements.js';\n\nexport default (selector, customSettings = {}) => {\n const settings = { ...defaultSettings, ...customSettings };\n const lazyItems = getElements(selector);\n\n if (!lazyItems.length) return console.warn('No lazy loadable element found!');\n\n const observerCallback = (target) => {\n try {\n settings.onLoading(target);\n loadAsset(target, settings);\n } catch (error) {\n settings.onError(target, error.message);\n }\n };\n\n lazyItems.forEach((item) => {\n observer(item, observerCallback, settings.observer);\n });\n};\n","export default {\n attrs: {\n src: 'lazy',\n srcset: 'lazy-srcset',\n poster: 'lazy-poster',\n },\n modifiers: {\n loaded: '-loaded',\n loading: '-loading',\n },\n onLoaded: () => {},\n onLoading: () => {},\n onError: (element, error) => console.warn('Error on:', element, error),\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n};\n","const supportedElements = ['img', 'picture', 'video', 'embed', 'object'];\n\nconst loadAssets = (element, assets) => {\n if (assets.src) element.setAttribute('src', assets.src);\n if (assets.srcset) element.setAttribute('srcset', assets.srcset);\n if (assets.poster) element.setAttribute('poster', assets.poster);\n};\n\nconst elementLoaded = (element, settings) => {\n element.classList.add(settings.modifiers.loaded);\n element.classList.remove(settings.modifiers.loading);\n\n element.removeAttribute(settings.attrs.src);\n element.removeAttribute(settings.attrs.srcset);\n element.removeAttribute(settings.attrs.poster);\n\n settings.onLoaded(element);\n};\n\nexport default (element, settings) => {\n const elementType = element.tagName.toLowerCase();\n const isSupported = supportedElements.includes(elementType);\n\n if (!isSupported) return console.warn('Element not supported!', element);\n\n const assets = {\n src: element.getAttribute(settings.attrs.src),\n srcset: element.getAttribute(settings.attrs.srcset),\n poster: element.getAttribute(settings.attrs.poster),\n };\n const handleLoadEvent = () => elementLoaded(element, settings);\n\n loadAssets(element, assets);\n\n element.classList.add(settings.modifiers.loading);\n element.addEventListener('load', handleLoadEvent, { once: true });\n};\n","export default function observeIntersection(item, callback, settings) {\n const handleIntersection = (entries, observer) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n\n callback(entry.target);\n observer.unobserve(entry.target);\n });\n };\n\n const observer = new IntersectionObserver(handleIntersection, settings);\n\n observer.observe(item);\n}\n","export default (selector, root = document) => {\n if (selector instanceof Element) return [selector];\n if (selector instanceof NodeList) return selector;\n if (selector instanceof Array) return selector;\n\n return root.querySelectorAll(selector);\n};\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file From 40ecc13949aaf9c4ac081460d82cdf19b0b2fe89 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Tue, 16 Jan 2024 23:12:39 +0300 Subject: [PATCH 110/185] Throw error for unsupported element type --- src/assetLoader.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index 896d1b0..704cb4f 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -21,14 +21,14 @@ export default (element, settings) => { const elementType = element.tagName.toLowerCase(); const isSupported = supportedElements.includes(elementType); - if (!isSupported) return console.warn('Element not supported!', element); + if (!isSupported) throw new Error(`Element type ${elementType} is not supported!`); + const handleLoadEvent = () => elementLoaded(element, settings); const assets = { src: element.getAttribute(settings.attrs.src), srcset: element.getAttribute(settings.attrs.srcset), poster: element.getAttribute(settings.attrs.poster), }; - const handleLoadEvent = () => elementLoaded(element, settings); loadAssets(element, assets); From 96c9a8bc00faf5311941e6b988f136efe1852403 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Tue, 16 Jan 2024 23:14:50 +0300 Subject: [PATCH 111/185] Refactor observeIntersection function to use arrow function --- src/observer.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/observer.js b/src/observer.js index 0f6e36e..9d5b623 100644 --- a/src/observer.js +++ b/src/observer.js @@ -1,4 +1,4 @@ -export default function observeIntersection(item, callback, settings) { +export default (item, callback, settings) => { const handleIntersection = (entries, observer) => { entries.forEach((entry) => { if (!entry.isIntersecting) return; @@ -11,4 +11,4 @@ export default function observeIntersection(item, callback, settings) { const observer = new IntersectionObserver(handleIntersection, settings); observer.observe(item); -} +}; From 2b3ecb7dccfd8b0f7842a57b3b9afb3c62d8f77a Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Tue, 16 Jan 2024 23:16:40 +0300 Subject: [PATCH 112/185] Update error logging in defaultSettings.js --- src/defaultSettings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/defaultSettings.js b/src/defaultSettings.js index d917609..fcbb762 100644 --- a/src/defaultSettings.js +++ b/src/defaultSettings.js @@ -10,7 +10,7 @@ export default { }, onLoaded: () => {}, onLoading: () => {}, - onError: (element, error) => console.warn('Error on:', element, error), + onError: (element, error) => console.error('Error on:', element, error), observer: { root: null, threshold: 1, From 61eefd71bc10ec16c02a91741f7a0796b904fc06 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Tue, 16 Jan 2024 23:21:48 +0300 Subject: [PATCH 113/185] Refactor lazy loading options and error handling --- src/app.js | 16 ++++++------ src/assetLoader.js | 26 +++++++++---------- src/{defaultSettings.js => defaultOptions.js} | 0 3 files changed, 21 insertions(+), 21 deletions(-) rename src/{defaultSettings.js => defaultOptions.js} (100%) diff --git a/src/app.js b/src/app.js index 71cd2bd..9a9eb01 100644 --- a/src/app.js +++ b/src/app.js @@ -8,27 +8,27 @@ * @see {@link https://github.com/drementer/lazy-load.js} */ -import defaultSettings from './defaultSettings.js'; +import defaultOptions from './defaultOptions.js'; import loadAsset from './assetLoader.js'; import observer from './observer.js'; import getElements from './getElements.js'; -export default (selector, customSettings = {}) => { - const settings = { ...defaultSettings, ...customSettings }; +export default (selector, customOptions = {}) => { + const options = { ...defaultOptions, ...customOptions }; const lazyItems = getElements(selector); - if (!lazyItems.length) return console.warn('No lazy loadable element found!'); + if (!lazyItems.length) return console.error('No lazy loadable element found!'); const observerCallback = (target) => { try { - settings.onLoading(target); - loadAsset(target, settings); + options.onLoading(target); + loadAsset(target, options); } catch (error) { - settings.onError(target, error.message); + options.onError(target, error.message); } }; lazyItems.forEach((item) => { - observer(item, observerCallback, settings.observer); + observer(item, observerCallback, options.observer); }); }; diff --git a/src/assetLoader.js b/src/assetLoader.js index 704cb4f..472cdb1 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -6,32 +6,32 @@ const loadAssets = (element, assets) => { if (assets.poster) element.setAttribute('poster', assets.poster); }; -const elementLoaded = (element, settings) => { - element.classList.add(settings.modifiers.loaded); - element.classList.remove(settings.modifiers.loading); +const elementLoaded = (element, options) => { + element.classList.add(options.modifiers.loaded); + element.classList.remove(options.modifiers.loading); - element.removeAttribute(settings.attrs.src); - element.removeAttribute(settings.attrs.srcset); - element.removeAttribute(settings.attrs.poster); + element.removeAttribute(options.attrs.src); + element.removeAttribute(options.attrs.srcset); + element.removeAttribute(options.attrs.poster); - settings.onLoaded(element); + options.onLoaded(element); }; -export default (element, settings) => { +export default (element, options) => { const elementType = element.tagName.toLowerCase(); const isSupported = supportedElements.includes(elementType); if (!isSupported) throw new Error(`Element type ${elementType} is not supported!`); - const handleLoadEvent = () => elementLoaded(element, settings); + const handleLoadEvent = () => elementLoaded(element, options); const assets = { - src: element.getAttribute(settings.attrs.src), - srcset: element.getAttribute(settings.attrs.srcset), - poster: element.getAttribute(settings.attrs.poster), + src: element.getAttribute(options.attrs.src), + srcset: element.getAttribute(options.attrs.srcset), + poster: element.getAttribute(options.attrs.poster), }; loadAssets(element, assets); - element.classList.add(settings.modifiers.loading); + element.classList.add(options.modifiers.loading); element.addEventListener('load', handleLoadEvent, { once: true }); }; diff --git a/src/defaultSettings.js b/src/defaultOptions.js similarity index 100% rename from src/defaultSettings.js rename to src/defaultOptions.js From c8657482ef3c0031a0cc3c7a06e4a60b37eb3f32 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 00:05:51 +0300 Subject: [PATCH 114/185] Update: Order of options --- src/defaultOptions.js | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/defaultOptions.js b/src/defaultOptions.js index fcbb762..ca2eb8b 100644 --- a/src/defaultOptions.js +++ b/src/defaultOptions.js @@ -8,12 +8,12 @@ export default { loaded: '-loaded', loading: '-loading', }, - onLoaded: () => {}, - onLoading: () => {}, - onError: (element, error) => console.error('Error on:', element, error), observer: { root: null, threshold: 1, rootMargin: '100% 0px', }, + onLoaded: () => {}, + onLoading: () => {}, + onError: (element, error) => console.error('Error on:', element, error), }; From fd5f7df443a7206027ca007daac5bfed23ac520f Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 00:06:09 +0300 Subject: [PATCH 115/185] Refactor lazy load initialization --- test/index.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/test/index.js b/test/index.js index 97d5320..a73feff 100644 --- a/test/index.js +++ b/test/index.js @@ -1,7 +1,4 @@ import lazyLoad from '/dist/lazy-load.js'; -const lazyLoadItems = document.querySelectorAll('[lazy]'); - -lazyLoad(lazyLoadItems, { - onLoaded: (element) => console.log(element), -}); +const initLazyLoad = () => lazyLoad('[lazy]'); +window.addEventListener('load', initLazyLoad, { once: true }); From 4be172b69f6ac5a7b9c5f9e825eec6374e29f232 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 00:13:54 +0300 Subject: [PATCH 116/185] Add states.js file with loading, loaded, and error states --- src/states.js | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) create mode 100644 src/states.js diff --git a/src/states.js b/src/states.js new file mode 100644 index 0000000..7bd30c8 --- /dev/null +++ b/src/states.js @@ -0,0 +1,26 @@ +const resetAssets = (element, options) => { + element.removeAttribute(options.attrs.src); + element.removeAttribute(options.attrs.srcset); + element.removeAttribute(options.attrs.poster); +}; + +const states = { + loading: (element, options) => { + const handleLoad = () => states.loaded(element, options); + element.classList.add(options.modifiers.loading); + element.addEventListener('load', handleLoad, { once: true }); + }, + loaded: (element, options) => { + element.classList.remove(options.modifiers.loading); + element.classList.add(options.modifiers.loaded); + + resetAssets(element, options); + options.onLoaded(element); + }, + error: (element, options, error) => { + element.classList.remove(options.modifiers.loading); + options.onError(element, error); + }, +}; + +export default states; From 36d0450aee0bb0847bfe29621a6a5acb5ac4aa0e Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 00:14:01 +0300 Subject: [PATCH 117/185] Refactor assetLoader.js to simplify code --- src/assetLoader.js | 32 +++----------------------------- 1 file changed, 3 insertions(+), 29 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index 472cdb1..b433990 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -1,37 +1,11 @@ -const supportedElements = ['img', 'picture', 'video', 'embed', 'object']; - -const loadAssets = (element, assets) => { - if (assets.src) element.setAttribute('src', assets.src); - if (assets.srcset) element.setAttribute('srcset', assets.srcset); - if (assets.poster) element.setAttribute('poster', assets.poster); -}; - -const elementLoaded = (element, options) => { - element.classList.add(options.modifiers.loaded); - element.classList.remove(options.modifiers.loading); - - element.removeAttribute(options.attrs.src); - element.removeAttribute(options.attrs.srcset); - element.removeAttribute(options.attrs.poster); - - options.onLoaded(element); -}; - export default (element, options) => { - const elementType = element.tagName.toLowerCase(); - const isSupported = supportedElements.includes(elementType); - - if (!isSupported) throw new Error(`Element type ${elementType} is not supported!`); - - const handleLoadEvent = () => elementLoaded(element, options); const assets = { src: element.getAttribute(options.attrs.src), srcset: element.getAttribute(options.attrs.srcset), poster: element.getAttribute(options.attrs.poster), }; - loadAssets(element, assets); - - element.classList.add(options.modifiers.loading); - element.addEventListener('load', handleLoadEvent, { once: true }); + if (assets.src) element.setAttribute('src', assets.src); + if (assets.srcset) element.setAttribute('srcset', assets.srcset); + if (assets.poster) element.setAttribute('poster', assets.poster); }; From b5d390e1cbdae91daac2d9bb8fb617eda3a193a1 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 00:14:07 +0300 Subject: [PATCH 118/185] Add isSupported.js to check if an element is supported --- src/isSupported.js | 9 +++++++++ 1 file changed, 9 insertions(+) create mode 100644 src/isSupported.js diff --git a/src/isSupported.js b/src/isSupported.js new file mode 100644 index 0000000..641fde8 --- /dev/null +++ b/src/isSupported.js @@ -0,0 +1,9 @@ +const supportedElements = ['img', 'picture', 'video', 'embed', 'object']; + +export default (element) => { + const elementType = element.tagName.toLowerCase(); + const isSupported = supportedElements.includes(elementType); + + if (isSupported) return true; + throw new Error(`Element type ${elementType} is not supported!`); +}; From c3356e616dafd402829a31a74339c76475ea348f Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 00:14:11 +0300 Subject: [PATCH 119/185] Add imports and error handling for lazy loading --- src/app.js | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) diff --git a/src/app.js b/src/app.js index 9a9eb01..80a942e 100644 --- a/src/app.js +++ b/src/app.js @@ -9,7 +9,9 @@ */ import defaultOptions from './defaultOptions.js'; +import states from './states.js'; import loadAsset from './assetLoader.js'; +import isSupported from './isSupported.js'; import observer from './observer.js'; import getElements from './getElements.js'; @@ -20,15 +22,16 @@ export default (selector, customOptions = {}) => { if (!lazyItems.length) return console.error('No lazy loadable element found!'); const observerCallback = (target) => { - try { - options.onLoading(target); - loadAsset(target, options); - } catch (error) { - options.onError(target, error.message); - } + states.loading(target, options); + loadAsset(target, options); }; lazyItems.forEach((item) => { - observer(item, observerCallback, options.observer); + try { + isSupported(item); + observer(item, observerCallback, options.observer); + } catch (error) { + states.error(item, options, error.message); + } }); }; From 9b287098598805fbddf3622d8a4b5ea1b1985bd1 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 00:14:40 +0300 Subject: [PATCH 120/185] Production --- dist/lazy-load.js | 107 ++++++++++++++++++++++++------------------ dist/lazy-load.js.map | 2 +- 2 files changed, 63 insertions(+), 46 deletions(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index 745213d..982b77b 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -6,7 +6,7 @@ * @version 1.0.7 * @license MIT * @see {@link https://github.com/drementer/lazy-load.js} - */ var $eca09eba1a2796e9$export$2e2bcd8739ae039 = { + */ var $caecf5182af9e868$export$2e2bcd8739ae039 = { attrs: { src: "lazy", srcset: "lazy-srcset", @@ -16,56 +16,72 @@ loaded: "-loaded", loading: "-loading" }, - onLoaded: ()=>{}, - onLoading: ()=>{}, - onError: (element, error)=>console.warn("Error on:", element, error), observer: { root: null, threshold: 1, rootMargin: "100% 0px" + }, + onLoaded: ()=>{}, + onLoading: ()=>{}, + onError: (element, error)=>console.error("Error on:", element, error) +}; + + +const $94035bc41cd26735$var$resetAssets = (element, options)=>{ + element.removeAttribute(options.attrs.src); + element.removeAttribute(options.attrs.srcset); + element.removeAttribute(options.attrs.poster); +}; +const $94035bc41cd26735$var$states = { + loading: (element, options)=>{ + const handleLoad = ()=>$94035bc41cd26735$var$states.loaded(element, options); + element.classList.add(options.modifiers.loading); + element.addEventListener("load", handleLoad, { + once: true + }); + }, + loaded: (element, options)=>{ + element.classList.remove(options.modifiers.loading); + element.classList.add(options.modifiers.loaded); + $94035bc41cd26735$var$resetAssets(element, options); + options.onLoaded(element); + }, + error: (element, options, error)=>{ + element.classList.remove(options.modifiers.loading); + options.onError(element, error); } }; +var $94035bc41cd26735$export$2e2bcd8739ae039 = $94035bc41cd26735$var$states; -const $fa423858cf60d4ae$var$supportedElements = [ +var $fa423858cf60d4ae$export$2e2bcd8739ae039 = (element, options)=>{ + const assets = { + src: element.getAttribute(options.attrs.src), + srcset: element.getAttribute(options.attrs.srcset), + poster: element.getAttribute(options.attrs.poster) + }; + if (assets.src) element.setAttribute("src", assets.src); + if (assets.srcset) element.setAttribute("srcset", assets.srcset); + if (assets.poster) element.setAttribute("poster", assets.poster); +}; + + +const $3557b12f3d798a99$var$supportedElements = [ "img", "picture", "video", "embed", "object" ]; -const $fa423858cf60d4ae$var$loadAssets = (element, assets)=>{ - if (assets.src) element.setAttribute("src", assets.src); - if (assets.srcset) element.setAttribute("srcset", assets.srcset); - if (assets.poster) element.setAttribute("poster", assets.poster); -}; -const $fa423858cf60d4ae$var$elementLoaded = (element, settings)=>{ - element.classList.add(settings.modifiers.loaded); - element.classList.remove(settings.modifiers.loading); - element.removeAttribute(settings.attrs.src); - element.removeAttribute(settings.attrs.srcset); - element.removeAttribute(settings.attrs.poster); - settings.onLoaded(element); -}; -var $fa423858cf60d4ae$export$2e2bcd8739ae039 = (element, settings)=>{ +var $3557b12f3d798a99$export$2e2bcd8739ae039 = (element)=>{ const elementType = element.tagName.toLowerCase(); - const isSupported = $fa423858cf60d4ae$var$supportedElements.includes(elementType); - if (!isSupported) return console.warn("Element not supported!", element); - const assets = { - src: element.getAttribute(settings.attrs.src), - srcset: element.getAttribute(settings.attrs.srcset), - poster: element.getAttribute(settings.attrs.poster) - }; - const handleLoadEvent = ()=>$fa423858cf60d4ae$var$elementLoaded(element, settings); - $fa423858cf60d4ae$var$loadAssets(element, assets); - element.classList.add(settings.modifiers.loading); - element.addEventListener("load", handleLoadEvent, { - once: true - }); + const isSupported = $3557b12f3d798a99$var$supportedElements.includes(elementType); + if (isSupported) return true; + throw new Error(`Element type ${elementType} is not supported!`); }; -function $5aa3f28da5200ea6$export$2e2bcd8739ae039(item, callback, settings) { +var $5aa3f28da5200ea6$export$2e2bcd8739ae039 = (item, callback, settings)=>{ const handleIntersection = (entries, observer)=>{ entries.forEach((entry)=>{ if (!entry.isIntersecting) return; @@ -75,7 +91,7 @@ function $5aa3f28da5200ea6$export$2e2bcd8739ae039(item, callback, settings) { }; const observer = new IntersectionObserver(handleIntersection, settings); observer.observe(item); -} +}; var $e5a64a9b43e3c02c$export$2e2bcd8739ae039 = (selector, root = document)=>{ @@ -88,23 +104,24 @@ var $e5a64a9b43e3c02c$export$2e2bcd8739ae039 = (selector, root = document)=>{ }; -var $3e2aed16982f049f$export$2e2bcd8739ae039 = (selector, customSettings = {})=>{ - const settings = { - ...(0, $eca09eba1a2796e9$export$2e2bcd8739ae039), - ...customSettings +var $3e2aed16982f049f$export$2e2bcd8739ae039 = (selector, customOptions = {})=>{ + const options = { + ...(0, $caecf5182af9e868$export$2e2bcd8739ae039), + ...customOptions }; const lazyItems = (0, $e5a64a9b43e3c02c$export$2e2bcd8739ae039)(selector); - if (!lazyItems.length) return console.warn("No lazy loadable element found!"); + if (!lazyItems.length) return console.error("No lazy loadable element found!"); const observerCallback = (target)=>{ + (0, $94035bc41cd26735$export$2e2bcd8739ae039).loading(target, options); + (0, $fa423858cf60d4ae$export$2e2bcd8739ae039)(target, options); + }; + lazyItems.forEach((item)=>{ try { - settings.onLoading(target); - (0, $fa423858cf60d4ae$export$2e2bcd8739ae039)(target, settings); + (0, $3557b12f3d798a99$export$2e2bcd8739ae039)(item); + (0, $5aa3f28da5200ea6$export$2e2bcd8739ae039)(item, observerCallback, options.observer); } catch (error) { - settings.onError(target, error.message); + (0, $94035bc41cd26735$export$2e2bcd8739ae039).error(item, options, error.message); } - }; - lazyItems.forEach((item)=>{ - (0, $5aa3f28da5200ea6$export$2e2bcd8739ae039)(item, observerCallback, settings.observer); }); }; diff --git a/dist/lazy-load.js.map b/dist/lazy-load.js.map index d820dd4..92719a2 100644 --- a/dist/lazy-load.js.map +++ b/dist/lazy-load.js.map @@ -1 +1 @@ -{"mappings":"AAAA;;;;;;;;ICAA,2CAAe;IACb,OAAO;QACL,KAAK;QACL,QAAQ;QACR,QAAQ;IACV;IACA,WAAW;QACT,QAAQ;QACR,SAAS;IACX;IACA,UAAU,KAAO;IACjB,WAAW,KAAO;IAClB,SAAS,CAAC,SAAS,QAAU,QAAQ,KAAK,aAAa,SAAS;IAChE,UAAU;QACR,MAAM;QACN,WAAW;QACX,YAAY;IACd;AACF;;CDVC;AERD,MAAM,0CAAoB;IAAC;IAAO;IAAW;IAAS;IAAS;CAAS;AAExE,MAAM,mCAAa,CAAC,SAAS;IAC3B,IAAI,OAAO,KAAK,QAAQ,aAAa,OAAO,OAAO;IACnD,IAAI,OAAO,QAAQ,QAAQ,aAAa,UAAU,OAAO;IACzD,IAAI,OAAO,QAAQ,QAAQ,aAAa,UAAU,OAAO;AAC3D;AAEA,MAAM,sCAAgB,CAAC,SAAS;IAC9B,QAAQ,UAAU,IAAI,SAAS,UAAU;IACzC,QAAQ,UAAU,OAAO,SAAS,UAAU;IAE5C,QAAQ,gBAAgB,SAAS,MAAM;IACvC,QAAQ,gBAAgB,SAAS,MAAM;IACvC,QAAQ,gBAAgB,SAAS,MAAM;IAEvC,SAAS,SAAS;AACpB;IAEA,2CAAe,CAAC,SAAS;IACvB,MAAM,cAAc,QAAQ,QAAQ;IACpC,MAAM,cAAc,wCAAkB,SAAS;IAE/C,IAAI,CAAC,aAAa,OAAO,QAAQ,KAAK,0BAA0B;IAEhE,MAAM,SAAS;QACb,KAAK,QAAQ,aAAa,SAAS,MAAM;QACzC,QAAQ,QAAQ,aAAa,SAAS,MAAM;QAC5C,QAAQ,QAAQ,aAAa,SAAS,MAAM;IAC9C;IACA,MAAM,kBAAkB,IAAM,oCAAc,SAAS;IAErD,iCAAW,SAAS;IAEpB,QAAQ,UAAU,IAAI,SAAS,UAAU;IACzC,QAAQ,iBAAiB,QAAQ,iBAAiB;QAAE,MAAM;IAAK;AACjE;;;ACpCe,kDAA6B,IAAI,EAAE,QAAQ,EAAE,QAAQ;IAClE,MAAM,qBAAqB,CAAC,SAAS;QACnC,QAAQ,QAAQ,CAAC;YACf,IAAI,CAAC,MAAM,gBAAgB;YAE3B,SAAS,MAAM;YACf,SAAS,UAAU,MAAM;QAC3B;IACF;IAEA,MAAM,WAAW,IAAI,qBAAqB,oBAAoB;IAE9D,SAAS,QAAQ;AACnB;;;ICbA,2CAAe,CAAC,UAAU,OAAO,QAAQ;IACvC,IAAI,oBAAoB,SAAS,OAAO;QAAC;KAAS;IAClD,IAAI,oBAAoB,UAAU,OAAO;IACzC,IAAI,oBAAoB,OAAO,OAAO;IAEtC,OAAO,KAAK,iBAAiB;AAC/B;;;IJSA,2CAAe,CAAC,UAAU,iBAAiB,CAAC,CAAC;IAC3C,MAAM,WAAW;QAAE,GAAG,CAAA,GAAA,wCAAc,CAAC;QAAE,GAAG,cAAc;IAAC;IACzD,MAAM,YAAY,CAAA,GAAA,wCAAU,EAAE;IAE9B,IAAI,CAAC,UAAU,QAAQ,OAAO,QAAQ,KAAK;IAE3C,MAAM,mBAAmB,CAAC;QACxB,IAAI;YACF,SAAS,UAAU;YACnB,CAAA,GAAA,wCAAQ,EAAE,QAAQ;QACpB,EAAE,OAAO,OAAO;YACd,SAAS,QAAQ,QAAQ,MAAM;QACjC;IACF;IAEA,UAAU,QAAQ,CAAC;QACjB,CAAA,GAAA,wCAAO,EAAE,MAAM,kBAAkB,SAAS;IAC5C;AACF","sources":["src/app.js","src/defaultSettings.js","src/assetLoader.js","src/observer.js","src/getElements.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.7\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultSettings from './defaultSettings.js';\nimport loadAsset from './assetLoader.js';\nimport observer from './observer.js';\nimport getElements from './getElements.js';\n\nexport default (selector, customSettings = {}) => {\n const settings = { ...defaultSettings, ...customSettings };\n const lazyItems = getElements(selector);\n\n if (!lazyItems.length) return console.warn('No lazy loadable element found!');\n\n const observerCallback = (target) => {\n try {\n settings.onLoading(target);\n loadAsset(target, settings);\n } catch (error) {\n settings.onError(target, error.message);\n }\n };\n\n lazyItems.forEach((item) => {\n observer(item, observerCallback, settings.observer);\n });\n};\n","export default {\n attrs: {\n src: 'lazy',\n srcset: 'lazy-srcset',\n poster: 'lazy-poster',\n },\n modifiers: {\n loaded: '-loaded',\n loading: '-loading',\n },\n onLoaded: () => {},\n onLoading: () => {},\n onError: (element, error) => console.warn('Error on:', element, error),\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n};\n","const supportedElements = ['img', 'picture', 'video', 'embed', 'object'];\n\nconst loadAssets = (element, assets) => {\n if (assets.src) element.setAttribute('src', assets.src);\n if (assets.srcset) element.setAttribute('srcset', assets.srcset);\n if (assets.poster) element.setAttribute('poster', assets.poster);\n};\n\nconst elementLoaded = (element, settings) => {\n element.classList.add(settings.modifiers.loaded);\n element.classList.remove(settings.modifiers.loading);\n\n element.removeAttribute(settings.attrs.src);\n element.removeAttribute(settings.attrs.srcset);\n element.removeAttribute(settings.attrs.poster);\n\n settings.onLoaded(element);\n};\n\nexport default (element, settings) => {\n const elementType = element.tagName.toLowerCase();\n const isSupported = supportedElements.includes(elementType);\n\n if (!isSupported) return console.warn('Element not supported!', element);\n\n const assets = {\n src: element.getAttribute(settings.attrs.src),\n srcset: element.getAttribute(settings.attrs.srcset),\n poster: element.getAttribute(settings.attrs.poster),\n };\n const handleLoadEvent = () => elementLoaded(element, settings);\n\n loadAssets(element, assets);\n\n element.classList.add(settings.modifiers.loading);\n element.addEventListener('load', handleLoadEvent, { once: true });\n};\n","export default function observeIntersection(item, callback, settings) {\n const handleIntersection = (entries, observer) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n\n callback(entry.target);\n observer.unobserve(entry.target);\n });\n };\n\n const observer = new IntersectionObserver(handleIntersection, settings);\n\n observer.observe(item);\n}\n","export default (selector, root = document) => {\n if (selector instanceof Element) return [selector];\n if (selector instanceof NodeList) return selector;\n if (selector instanceof Array) return selector;\n\n return root.querySelectorAll(selector);\n};\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file +{"mappings":"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","sources":["src/app.js","src/defaultOptions.js","src/states.js","src/assetLoader.js","src/isSupported.js","src/observer.js","src/getElements.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.7\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './defaultOptions.js';\nimport states from './states.js';\nimport loadAsset from './assetLoader.js';\nimport isSupported from './isSupported.js';\nimport observer from './observer.js';\nimport getElements from './getElements.js';\n\nexport default (selector, customOptions = {}) => {\n const options = { ...defaultOptions, ...customOptions };\n const lazyItems = getElements(selector);\n\n if (!lazyItems.length) return console.error('No lazy loadable element found!');\n\n const observerCallback = (target) => {\n states.loading(target, options);\n loadAsset(target, options);\n };\n\n lazyItems.forEach((item) => {\n try {\n isSupported(item);\n observer(item, observerCallback, options.observer);\n } catch (error) {\n states.error(item, options, error.message);\n }\n });\n};\n","export default {\n attrs: {\n src: 'lazy',\n srcset: 'lazy-srcset',\n poster: 'lazy-poster',\n },\n modifiers: {\n loaded: '-loaded',\n loading: '-loading',\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n onLoaded: () => {},\n onLoading: () => {},\n onError: (element, error) => console.error('Error on:', element, error),\n};\n","const resetAssets = (element, options) => {\n element.removeAttribute(options.attrs.src);\n element.removeAttribute(options.attrs.srcset);\n element.removeAttribute(options.attrs.poster);\n};\n\nconst states = {\n loading: (element, options) => {\n const handleLoad = () => states.loaded(element, options);\n element.classList.add(options.modifiers.loading);\n element.addEventListener('load', handleLoad, { once: true });\n },\n loaded: (element, options) => {\n element.classList.remove(options.modifiers.loading);\n element.classList.add(options.modifiers.loaded);\n\n resetAssets(element, options);\n options.onLoaded(element);\n },\n error: (element, options, error) => {\n element.classList.remove(options.modifiers.loading);\n options.onError(element, error);\n },\n};\n\nexport default states;\n","export default (element, options) => {\n const assets = {\n src: element.getAttribute(options.attrs.src),\n srcset: element.getAttribute(options.attrs.srcset),\n poster: element.getAttribute(options.attrs.poster),\n };\n\n if (assets.src) element.setAttribute('src', assets.src);\n if (assets.srcset) element.setAttribute('srcset', assets.srcset);\n if (assets.poster) element.setAttribute('poster', assets.poster);\n};\n","const supportedElements = ['img', 'picture', 'video', 'embed', 'object'];\n\nexport default (element) => {\n const elementType = element.tagName.toLowerCase();\n const isSupported = supportedElements.includes(elementType);\n\n if (isSupported) return true;\n throw new Error(`Element type ${elementType} is not supported!`);\n};\n","export default (item, callback, settings) => {\n const handleIntersection = (entries, observer) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n\n callback(entry.target);\n observer.unobserve(entry.target);\n });\n };\n\n const observer = new IntersectionObserver(handleIntersection, settings);\n\n observer.observe(item);\n};\n","export default (selector, root = document) => {\n if (selector instanceof Element) return [selector];\n if (selector instanceof NodeList) return selector;\n if (selector instanceof Array) return selector;\n\n return root.querySelectorAll(selector);\n};\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file From c6ec25e02e041c0eab26639dbf53e9996a6d05af Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 19:46:00 +0300 Subject: [PATCH 121/185] Refactor isSupported function to checkSupport --- src/app.js | 6 ++---- src/checkSupport.js | 9 +++++++++ 2 files changed, 11 insertions(+), 4 deletions(-) create mode 100644 src/checkSupport.js diff --git a/src/app.js b/src/app.js index 80a942e..07c0c47 100644 --- a/src/app.js +++ b/src/app.js @@ -11,7 +11,7 @@ import defaultOptions from './defaultOptions.js'; import states from './states.js'; import loadAsset from './assetLoader.js'; -import isSupported from './isSupported.js'; +import checkSupport from './checkSupport.js'; import observer from './observer.js'; import getElements from './getElements.js'; @@ -19,8 +19,6 @@ export default (selector, customOptions = {}) => { const options = { ...defaultOptions, ...customOptions }; const lazyItems = getElements(selector); - if (!lazyItems.length) return console.error('No lazy loadable element found!'); - const observerCallback = (target) => { states.loading(target, options); loadAsset(target, options); @@ -28,7 +26,7 @@ export default (selector, customOptions = {}) => { lazyItems.forEach((item) => { try { - isSupported(item); + checkSupport(item); observer(item, observerCallback, options.observer); } catch (error) { states.error(item, options, error.message); diff --git a/src/checkSupport.js b/src/checkSupport.js new file mode 100644 index 0000000..641fde8 --- /dev/null +++ b/src/checkSupport.js @@ -0,0 +1,9 @@ +const supportedElements = ['img', 'picture', 'video', 'embed', 'object']; + +export default (element) => { + const elementType = element.tagName.toLowerCase(); + const isSupported = supportedElements.includes(elementType); + + if (isSupported) return true; + throw new Error(`Element type ${elementType} is not supported!`); +}; From 08be86ea24013940a21c7979d2c764fba081293e Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 20:46:44 +0300 Subject: [PATCH 122/185] Add lazy loading default options and update getElements function --- src/defaultOptions.js | 21 +++++++++++++++++++++ src/getElements.js | 10 ++++++++-- 2 files changed, 29 insertions(+), 2 deletions(-) diff --git a/src/defaultOptions.js b/src/defaultOptions.js index ca2eb8b..943a41f 100644 --- a/src/defaultOptions.js +++ b/src/defaultOptions.js @@ -1,3 +1,24 @@ +/** + * Default options for the lazy loading functionality. + * + * @property {Object} attrs - The attributes to be used for lazy loading. + * @property {string} attrs.src - The attribute for the source of the media. + * @property {string} attrs.srcset - The attribute for the source set of the media. + * @property {string} attrs.poster - The attribute for the poster of the media. + * + * @property {Object} modifiers - The modifiers to be used for the states of loading. + * @property {string} modifiers.loaded - The modifier for the loaded state. + * @property {string} modifiers.loading - The modifier for the loading state. + * + * @property {Object} observer - The options for the Intersection Observer. + * @property {Element} observer.root - The root element for the Intersection Observer. + * @property {number} observer.threshold - The threshold for the Intersection Observer. + * @property {string} observer.rootMargin - The root margin for the Intersection Observer. + * + * @property {Function} onLoaded - The callback to be executed when the media is loaded. + * @property {Function} onLoading - The callback to be executed when the media is loading. + * @property {Function} onError - The callback to be executed when there is an error loading the media. + */ export default { attrs: { src: 'lazy', diff --git a/src/getElements.js b/src/getElements.js index bea12dc..5060b32 100644 --- a/src/getElements.js +++ b/src/getElements.js @@ -1,7 +1,13 @@ -export default (selector, root = document) => { +/** + * Select elements based on a given selector within a specified root element. + * + * @param {string | Element | NodeList | Array} selector - The selector to match elements. + * @returns {NodeList} - The NodeList containing the selected elements. + */ +export default (selector) => { if (selector instanceof Element) return [selector]; if (selector instanceof NodeList) return selector; if (selector instanceof Array) return selector; - return root.querySelectorAll(selector); + return document.querySelectorAll(selector); }; From 68ade71f4e5b708dc6281d5f0b7123ca3b4996e5 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 20:47:03 +0300 Subject: [PATCH 123/185] Refactor image loading logic --- src/states.js | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/states.js b/src/states.js index 7bd30c8..2a90503 100644 --- a/src/states.js +++ b/src/states.js @@ -1,20 +1,19 @@ -const resetAssets = (element, options) => { - element.removeAttribute(options.attrs.src); - element.removeAttribute(options.attrs.srcset); - element.removeAttribute(options.attrs.poster); -}; - const states = { loading: (element, options) => { const handleLoad = () => states.loaded(element, options); element.classList.add(options.modifiers.loading); element.addEventListener('load', handleLoad, { once: true }); + + options.onLoading(element); }, loaded: (element, options) => { element.classList.remove(options.modifiers.loading); element.classList.add(options.modifiers.loaded); - resetAssets(element, options); + element.removeAttribute(options.attrs.src); + element.removeAttribute(options.attrs.srcset); + element.removeAttribute(options.attrs.poster); + options.onLoaded(element); }, error: (element, options, error) => { From 3d34e4756f55847f5df6adbf8ddeb18c2188fbbf Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 20:47:40 +0300 Subject: [PATCH 124/185] Remove unsupported element check --- src/isSupported.js | 9 --------- 1 file changed, 9 deletions(-) delete mode 100644 src/isSupported.js diff --git a/src/isSupported.js b/src/isSupported.js deleted file mode 100644 index 641fde8..0000000 --- a/src/isSupported.js +++ /dev/null @@ -1,9 +0,0 @@ -const supportedElements = ['img', 'picture', 'video', 'embed', 'object']; - -export default (element) => { - const elementType = element.tagName.toLowerCase(); - const isSupported = supportedElements.includes(elementType); - - if (isSupported) return true; - throw new Error(`Element type ${elementType} is not supported!`); -}; From aeb459e604b82f4994f16a9e55cf1eaed89846f3 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 20:47:52 +0300 Subject: [PATCH 125/185] Update lazy loading in index.html --- test/index.html | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/test/index.html b/test/index.html index dc9026c..59a4ca0 100644 --- a/test/index.html +++ b/test/index.html @@ -5,15 +5,16 @@ Lazy-load.js + + -
+
- Random Image Random Image Random Image Random Image @@ -23,7 +24,5 @@ Random Image Random Image - - \ No newline at end of file From 2dfbfc0cb3dd536c3d0e29ec0c03a4b2b2aea662 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 21:02:59 +0300 Subject: [PATCH 126/185] Add: JSDoc's --- src/assetLoader.js | 10 ++++++++++ src/checkSupport.js | 12 ++++++++++++ src/observer.js | 7 +++++++ src/states.js | 12 +++++++++--- 4 files changed, 38 insertions(+), 3 deletions(-) diff --git a/src/assetLoader.js b/src/assetLoader.js index b433990..2690eda 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -1,3 +1,13 @@ +/** + * Set attributes on the given HTML element based on the provided options. + * + * @param {HTMLElement} element - The HTML element to set attributes on. + * @param {Object} options - Options for attribute names. + * @param {Object} options.attrs - Attribute names. + * @param {string} [options.attrs.src] - Attribute name for 'src'. + * @param {string} [options.attrs.srcset] - Attribute name for 'srcset'. + * @param {string} [options.attrs.poster] - Attribute name for 'poster'. + */ export default (element, options) => { const assets = { src: element.getAttribute(options.attrs.src), diff --git a/src/checkSupport.js b/src/checkSupport.js index 641fde8..4187500 100644 --- a/src/checkSupport.js +++ b/src/checkSupport.js @@ -1,9 +1,21 @@ +/** + * @type {Array} + * List of supported HTML element types. + */ const supportedElements = ['img', 'picture', 'video', 'embed', 'object']; +/** + * Checks if the given HTML element is of a supported type. + * + * @param {HTMLElement} element - The HTML element to be checked. + * @throws {Error} Throws an error if the element type is not supported. + * @returns {boolean} Returns true if the element type is supported. + */ export default (element) => { const elementType = element.tagName.toLowerCase(); const isSupported = supportedElements.includes(elementType); if (isSupported) return true; + throw new Error(`Element type ${elementType} is not supported!`); }; diff --git a/src/observer.js b/src/observer.js index 9d5b623..cb057bf 100644 --- a/src/observer.js +++ b/src/observer.js @@ -1,3 +1,10 @@ +/** + * Creates an Intersection Observer and starts observing the given item. + * + * @param {Element} item - The DOM element to be observed. + * @param {Function} callback - The function to be called when the item is intersecting. + * @param {Object} settings - The options for the Intersection Observer. + */ export default (item, callback, settings) => { const handleIntersection = (entries, observer) => { entries.forEach((entry) => { diff --git a/src/states.js b/src/states.js index 2a90503..a190789 100644 --- a/src/states.js +++ b/src/states.js @@ -1,21 +1,27 @@ +/** + * Object managing different states. + * + * @property {function} loading - Function handling loading state operations. + * @property {function} loaded - Function handling loaded state operations. + * @property {function} error - Function handling error state operations. + */ const states = { loading: (element, options) => { const handleLoad = () => states.loaded(element, options); element.classList.add(options.modifiers.loading); element.addEventListener('load', handleLoad, { once: true }); - options.onLoading(element); }, + loaded: (element, options) => { element.classList.remove(options.modifiers.loading); element.classList.add(options.modifiers.loaded); - element.removeAttribute(options.attrs.src); element.removeAttribute(options.attrs.srcset); element.removeAttribute(options.attrs.poster); - options.onLoaded(element); }, + error: (element, options, error) => { element.classList.remove(options.modifiers.loading); options.onError(element, error); From b3392238077c3d44b1376bcdd9a7ab2c84bbe81c Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 21:04:08 +0300 Subject: [PATCH 127/185] Refactor lazy loading logic --- src/app.js | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/src/app.js b/src/app.js index 07c0c47..2155b3c 100644 --- a/src/app.js +++ b/src/app.js @@ -17,19 +17,27 @@ import getElements from './getElements.js'; export default (selector, customOptions = {}) => { const options = { ...defaultOptions, ...customOptions }; - const lazyItems = getElements(selector); const observerCallback = (target) => { states.loading(target, options); loadAsset(target, options); }; - lazyItems.forEach((item) => { + const processLazyItem = (item) => { try { checkSupport(item); observer(item, observerCallback, options.observer); } catch (error) { states.error(item, options, error.message); } - }); + }; + + try { + const lazyItems = getElements(selector); + if (!lazyItems.length) throw new Error('No lazy loadable element found!'); + + lazyItems.forEach(processLazyItem); + } catch (error) { + console.error('Lazy error:', error.message); + } }; From 8121ade68939193bc673ec813184ba58ca914b39 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 21:53:36 +0300 Subject: [PATCH 128/185] Add: Settings --- src/checkSupport.js | 8 ++------ src/defaultOptions.js | 8 -------- src/settings.js | 19 +++++++++++++++++++ src/states.js | 26 +++++++++++++++++++++----- 4 files changed, 42 insertions(+), 19 deletions(-) create mode 100644 src/settings.js diff --git a/src/checkSupport.js b/src/checkSupport.js index 4187500..154fb7d 100644 --- a/src/checkSupport.js +++ b/src/checkSupport.js @@ -1,8 +1,4 @@ -/** - * @type {Array} - * List of supported HTML element types. - */ -const supportedElements = ['img', 'picture', 'video', 'embed', 'object']; +import settings from './settings.js'; /** * Checks if the given HTML element is of a supported type. @@ -13,7 +9,7 @@ const supportedElements = ['img', 'picture', 'video', 'embed', 'object']; */ export default (element) => { const elementType = element.tagName.toLowerCase(); - const isSupported = supportedElements.includes(elementType); + const isSupported = settings.supportedElements.includes(elementType); if (isSupported) return true; diff --git a/src/defaultOptions.js b/src/defaultOptions.js index 943a41f..1368284 100644 --- a/src/defaultOptions.js +++ b/src/defaultOptions.js @@ -6,10 +6,6 @@ * @property {string} attrs.srcset - The attribute for the source set of the media. * @property {string} attrs.poster - The attribute for the poster of the media. * - * @property {Object} modifiers - The modifiers to be used for the states of loading. - * @property {string} modifiers.loaded - The modifier for the loaded state. - * @property {string} modifiers.loading - The modifier for the loading state. - * * @property {Object} observer - The options for the Intersection Observer. * @property {Element} observer.root - The root element for the Intersection Observer. * @property {number} observer.threshold - The threshold for the Intersection Observer. @@ -25,10 +21,6 @@ export default { srcset: 'lazy-srcset', poster: 'lazy-poster', }, - modifiers: { - loaded: '-loaded', - loading: '-loading', - }, observer: { root: null, threshold: 1, diff --git a/src/settings.js b/src/settings.js new file mode 100644 index 0000000..995876b --- /dev/null +++ b/src/settings.js @@ -0,0 +1,19 @@ +/** + * @property {string} stateAttr - The attribute to store the state of the lazy loading process. + * @property {Object} states - The possible states of the lazy loading process. + * @property {string} states.waiting - The state when the element is waiting to be loaded. + * @property {string} states.loading - The state when the element is currently loading. + * @property {string} states.loaded - The state when the element has finished loading. + * @property {string} states.error - The state when there was an error loading the element. + * @property {Array.} supportedElements - The types of elements that are supported for lazy loading. + */ +export default { + stateAttr: 'lazy-state', + states: { + waiting: 'waiting', + loading: 'loading', + loaded: 'loaded', + error: 'error', + }, + supportedElements: ['img', 'picture', 'video', 'embed', 'object'], +}; diff --git a/src/states.js b/src/states.js index a190789..d9796ad 100644 --- a/src/states.js +++ b/src/states.js @@ -1,3 +1,5 @@ +import settings from './settings.js'; + /** * Object managing different states. * @@ -6,24 +8,38 @@ * @property {function} error - Function handling error state operations. */ const states = { + waiting: (element, options) => { + element.setAttribute(settings.stateAttr, settings.states.waiting); + }, + loading: (element, options) => { - const handleLoad = () => states.loaded(element, options); - element.classList.add(options.modifiers.loading); + const handleLoad = () => { + states.loaded(element, options); + }; + const handleError = () => { + states.error(element, options, 'loading media.'); + }; + element.addEventListener('load', handleLoad, { once: true }); + element.addEventListener('error', handleError, { once: true }); + + element.setAttribute(settings.stateAttr, settings.states.loading); options.onLoading(element); }, loaded: (element, options) => { - element.classList.remove(options.modifiers.loading); - element.classList.add(options.modifiers.loaded); + element.setAttribute(settings.stateAttr, settings.states.loaded); + element.removeAttribute(options.attrs.src); element.removeAttribute(options.attrs.srcset); element.removeAttribute(options.attrs.poster); + options.onLoaded(element); }, error: (element, options, error) => { - element.classList.remove(options.modifiers.loading); + element.setAttribute(settings.stateAttr, settings.states.error); + options.onError(element, error); }, }; From 85c1385246b60144b2b582cc98a602cbabf94f64 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 21:54:14 +0300 Subject: [PATCH 129/185] Add waiting state for items --- src/app.js | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/app.js b/src/app.js index 2155b3c..bc97ec8 100644 --- a/src/app.js +++ b/src/app.js @@ -25,6 +25,8 @@ export default (selector, customOptions = {}) => { const processLazyItem = (item) => { try { + states.waiting(item, options); + checkSupport(item); observer(item, observerCallback, options.observer); } catch (error) { From 02a18f3efbcc3d62614f4eaf73e78f61baa4e005 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 21:54:46 +0300 Subject: [PATCH 130/185] Add: Broken Image link for test --- test/index.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/test/index.html b/test/index.html index 59a4ca0..d7bfc0c 100644 --- a/test/index.html +++ b/test/index.html @@ -15,7 +15,7 @@
- Random Image + Random Image Random Image Random Image Random Image From a9d851fbca636931e18b1de812bfa23dd0e9e351 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 21:55:57 +0300 Subject: [PATCH 131/185] Update version to 1.1.0 --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index e2d3e04..40bee41 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lazy-load.js", - "version": "1.0.7", + "version": "1.1.0", "homepage": "https://github.com/drementer/lazy-load.js", "description": "Loads visual content when it approaches the visible area of ​​the screen to increase page loading speed.", "source": "src/app.js", From 4a5b710a365c14a2d721028bb23a518f8bdb0254 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 22:00:26 +0300 Subject: [PATCH 132/185] Add module documentation --- src/assetLoader.js | 2 ++ src/checkSupport.js | 2 ++ src/defaultOptions.js | 2 ++ src/getElements.js | 2 ++ src/observer.js | 2 ++ src/settings.js | 4 ++++ src/states.js | 2 ++ 7 files changed, 16 insertions(+) diff --git a/src/assetLoader.js b/src/assetLoader.js index 2690eda..cc9d5c2 100644 --- a/src/assetLoader.js +++ b/src/assetLoader.js @@ -1,6 +1,8 @@ /** * Set attributes on the given HTML element based on the provided options. * + * @module assetLoader + * * @param {HTMLElement} element - The HTML element to set attributes on. * @param {Object} options - Options for attribute names. * @param {Object} options.attrs - Attribute names. diff --git a/src/checkSupport.js b/src/checkSupport.js index 154fb7d..ac2d9ad 100644 --- a/src/checkSupport.js +++ b/src/checkSupport.js @@ -3,6 +3,8 @@ import settings from './settings.js'; /** * Checks if the given HTML element is of a supported type. * + * @module checkSupport + * * @param {HTMLElement} element - The HTML element to be checked. * @throws {Error} Throws an error if the element type is not supported. * @returns {boolean} Returns true if the element type is supported. diff --git a/src/defaultOptions.js b/src/defaultOptions.js index 1368284..a95a873 100644 --- a/src/defaultOptions.js +++ b/src/defaultOptions.js @@ -1,6 +1,8 @@ /** * Default options for the lazy loading functionality. * + * @module defaultOptions + * * @property {Object} attrs - The attributes to be used for lazy loading. * @property {string} attrs.src - The attribute for the source of the media. * @property {string} attrs.srcset - The attribute for the source set of the media. diff --git a/src/getElements.js b/src/getElements.js index 5060b32..1965a76 100644 --- a/src/getElements.js +++ b/src/getElements.js @@ -1,6 +1,8 @@ /** * Select elements based on a given selector within a specified root element. * + * @module getElements + * * @param {string | Element | NodeList | Array} selector - The selector to match elements. * @returns {NodeList} - The NodeList containing the selected elements. */ diff --git a/src/observer.js b/src/observer.js index cb057bf..a3f7531 100644 --- a/src/observer.js +++ b/src/observer.js @@ -1,6 +1,8 @@ /** * Creates an Intersection Observer and starts observing the given item. * + * @module observer + * * @param {Element} item - The DOM element to be observed. * @param {Function} callback - The function to be called when the item is intersecting. * @param {Object} settings - The options for the Intersection Observer. diff --git a/src/settings.js b/src/settings.js index 995876b..d011428 100644 --- a/src/settings.js +++ b/src/settings.js @@ -1,4 +1,8 @@ /** + * Default settings for the lazy loading functionality. + * + * @module settings + * * @property {string} stateAttr - The attribute to store the state of the lazy loading process. * @property {Object} states - The possible states of the lazy loading process. * @property {string} states.waiting - The state when the element is waiting to be loaded. diff --git a/src/states.js b/src/states.js index d9796ad..5ef4619 100644 --- a/src/states.js +++ b/src/states.js @@ -3,6 +3,8 @@ import settings from './settings.js'; /** * Object managing different states. * + * @module states + * * @property {function} loading - Function handling loading state operations. * @property {function} loaded - Function handling loaded state operations. * @property {function} error - Function handling error state operations. From 681fdbde94a03abde29a0393bcfb74a214e3612c Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 22:04:16 +0300 Subject: [PATCH 133/185] Update image URLs in index.html --- test/index.html | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/test/index.html b/test/index.html index d7bfc0c..c398174 100644 --- a/test/index.html +++ b/test/index.html @@ -16,13 +16,13 @@
Random Image - Random Image - Random Image - Random Image - Random Image - Random Image - Random Image - Random Image + Random Image + Random Image + Random Image + Random Image + Random Image + Random Image + Random Image \ No newline at end of file From f4a9b1305fec598cb77584bf76715e5310a34008 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 22:09:20 +0300 Subject: [PATCH 134/185] Update package.json description --- package.json | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/package.json b/package.json index 40bee41..4601301 100644 --- a/package.json +++ b/package.json @@ -2,18 +2,31 @@ "name": "lazy-load.js", "version": "1.1.0", "homepage": "https://github.com/drementer/lazy-load.js", - "description": "Loads visual content when it approaches the visible area of ​​the screen to increase page loading speed.", + "description": "Another, another and another Lazy Load Library", "source": "src/app.js", "module": "dist/lazy-load.js", + "files": [ + "dist" + ], "scripts": { "watch": "parcel watch", "build": "parcel build --no-source-maps --no-cache" }, "keywords": [ - "js", "lazy", "lazy load", - "lazy-load.js" + "lazy loader", + "lazy loading", + "lazy-load.js", + "loader", + "lazyloader", + "lazyload", + "performance", + "web performance", + "IntersectionObserver", + "image", + "video", + "iframe" ], "author": "drementer (https://github.com/drementer)", "repository": { From 7e819cf9da2cc04178e8f19f6f37369fae772815 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 22:15:03 +0300 Subject: [PATCH 135/185] Update copyright year in LICENSE file --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index 93c427c..df75975 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 - 2023 drementer +Copyright (c) 2022 - 2024 drementer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 789d1c3452e124e62cb71d8bc49772ad513f5996 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 22:15:33 +0300 Subject: [PATCH 136/185] Production --- dist/lazy-load.js | 160 +++++++++++++++++++++++++++++++++--------- dist/lazy-load.js.map | 2 +- 2 files changed, 128 insertions(+), 34 deletions(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index 982b77b..a954adf 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -6,16 +6,30 @@ * @version 1.0.7 * @license MIT * @see {@link https://github.com/drementer/lazy-load.js} + */ /** + * Default options for the lazy loading functionality. + * + * @module defaultOptions + * + * @property {Object} attrs - The attributes to be used for lazy loading. + * @property {string} attrs.src - The attribute for the source of the media. + * @property {string} attrs.srcset - The attribute for the source set of the media. + * @property {string} attrs.poster - The attribute for the poster of the media. + * + * @property {Object} observer - The options for the Intersection Observer. + * @property {Element} observer.root - The root element for the Intersection Observer. + * @property {number} observer.threshold - The threshold for the Intersection Observer. + * @property {string} observer.rootMargin - The root margin for the Intersection Observer. + * + * @property {Function} onLoaded - The callback to be executed when the media is loaded. + * @property {Function} onLoading - The callback to be executed when the media is loading. + * @property {Function} onError - The callback to be executed when there is an error loading the media. */ var $caecf5182af9e868$export$2e2bcd8739ae039 = { attrs: { src: "lazy", srcset: "lazy-srcset", poster: "lazy-poster" }, - modifiers: { - loaded: "-loaded", - loading: "-loading" - }, observer: { root: null, threshold: 1, @@ -27,34 +41,91 @@ }; -const $94035bc41cd26735$var$resetAssets = (element, options)=>{ - element.removeAttribute(options.attrs.src); - element.removeAttribute(options.attrs.srcset); - element.removeAttribute(options.attrs.poster); +/** + * Default settings for the lazy loading functionality. + * + * @module settings + * + * @property {string} stateAttr - The attribute to store the state of the lazy loading process. + * @property {Object} states - The possible states of the lazy loading process. + * @property {string} states.waiting - The state when the element is waiting to be loaded. + * @property {string} states.loading - The state when the element is currently loading. + * @property {string} states.loaded - The state when the element has finished loading. + * @property {string} states.error - The state when there was an error loading the element. + * @property {Array.} supportedElements - The types of elements that are supported for lazy loading. + */ var $51e72698ed0f3e92$export$2e2bcd8739ae039 = { + stateAttr: "lazy-state", + states: { + waiting: "waiting", + loading: "loading", + loaded: "loaded", + error: "error" + }, + supportedElements: [ + "img", + "picture", + "video", + "embed", + "object" + ] }; -const $94035bc41cd26735$var$states = { + + +/** + * Object managing different states. + * + * @module states + * + * @property {function} loading - Function handling loading state operations. + * @property {function} loaded - Function handling loaded state operations. + * @property {function} error - Function handling error state operations. + */ const $94035bc41cd26735$var$states = { + waiting: (element, options)=>{ + element.setAttribute((0, $51e72698ed0f3e92$export$2e2bcd8739ae039).stateAttr, (0, $51e72698ed0f3e92$export$2e2bcd8739ae039).states.waiting); + }, loading: (element, options)=>{ - const handleLoad = ()=>$94035bc41cd26735$var$states.loaded(element, options); - element.classList.add(options.modifiers.loading); + const handleLoad = ()=>{ + $94035bc41cd26735$var$states.loaded(element, options); + }; + const handleError = ()=>{ + $94035bc41cd26735$var$states.error(element, options, "loading media."); + }; element.addEventListener("load", handleLoad, { once: true }); + element.addEventListener("error", handleError, { + once: true + }); + element.setAttribute((0, $51e72698ed0f3e92$export$2e2bcd8739ae039).stateAttr, (0, $51e72698ed0f3e92$export$2e2bcd8739ae039).states.loading); + options.onLoading(element); }, loaded: (element, options)=>{ - element.classList.remove(options.modifiers.loading); - element.classList.add(options.modifiers.loaded); - $94035bc41cd26735$var$resetAssets(element, options); + element.setAttribute((0, $51e72698ed0f3e92$export$2e2bcd8739ae039).stateAttr, (0, $51e72698ed0f3e92$export$2e2bcd8739ae039).states.loaded); + element.removeAttribute(options.attrs.src); + element.removeAttribute(options.attrs.srcset); + element.removeAttribute(options.attrs.poster); options.onLoaded(element); }, error: (element, options, error)=>{ - element.classList.remove(options.modifiers.loading); + element.setAttribute((0, $51e72698ed0f3e92$export$2e2bcd8739ae039).stateAttr, (0, $51e72698ed0f3e92$export$2e2bcd8739ae039).states.error); options.onError(element, error); } }; var $94035bc41cd26735$export$2e2bcd8739ae039 = $94035bc41cd26735$var$states; -var $fa423858cf60d4ae$export$2e2bcd8739ae039 = (element, options)=>{ +/** + * Set attributes on the given HTML element based on the provided options. + * + * @module assetLoader + * + * @param {HTMLElement} element - The HTML element to set attributes on. + * @param {Object} options - Options for attribute names. + * @param {Object} options.attrs - Attribute names. + * @param {string} [options.attrs.src] - Attribute name for 'src'. + * @param {string} [options.attrs.srcset] - Attribute name for 'srcset'. + * @param {string} [options.attrs.poster] - Attribute name for 'poster'. + */ var $fa423858cf60d4ae$export$2e2bcd8739ae039 = (element, options)=>{ const assets = { src: element.getAttribute(options.attrs.src), srcset: element.getAttribute(options.attrs.srcset), @@ -66,22 +137,32 @@ var $fa423858cf60d4ae$export$2e2bcd8739ae039 = (element, options)=>{ }; -const $3557b12f3d798a99$var$supportedElements = [ - "img", - "picture", - "video", - "embed", - "object" -]; -var $3557b12f3d798a99$export$2e2bcd8739ae039 = (element)=>{ + +var /** + * Checks if the given HTML element is of a supported type. + * + * @module checkSupport + * + * @param {HTMLElement} element - The HTML element to be checked. + * @throws {Error} Throws an error if the element type is not supported. + * @returns {boolean} Returns true if the element type is supported. + */ $4a8d64b6206062f5$export$2e2bcd8739ae039 = (element)=>{ const elementType = element.tagName.toLowerCase(); - const isSupported = $3557b12f3d798a99$var$supportedElements.includes(elementType); + const isSupported = (0, $51e72698ed0f3e92$export$2e2bcd8739ae039).supportedElements.includes(elementType); if (isSupported) return true; throw new Error(`Element type ${elementType} is not supported!`); }; -var $5aa3f28da5200ea6$export$2e2bcd8739ae039 = (item, callback, settings)=>{ +/** + * Creates an Intersection Observer and starts observing the given item. + * + * @module observer + * + * @param {Element} item - The DOM element to be observed. + * @param {Function} callback - The function to be called when the item is intersecting. + * @param {Object} settings - The options for the Intersection Observer. + */ var $5aa3f28da5200ea6$export$2e2bcd8739ae039 = (item, callback, settings)=>{ const handleIntersection = (entries, observer)=>{ entries.forEach((entry)=>{ if (!entry.isIntersecting) return; @@ -94,13 +175,20 @@ var $5aa3f28da5200ea6$export$2e2bcd8739ae039 = (item, callback, settings)=>{ }; -var $e5a64a9b43e3c02c$export$2e2bcd8739ae039 = (selector, root = document)=>{ +/** + * Select elements based on a given selector within a specified root element. + * + * @module getElements + * + * @param {string | Element | NodeList | Array} selector - The selector to match elements. + * @returns {NodeList} - The NodeList containing the selected elements. + */ var $e5a64a9b43e3c02c$export$2e2bcd8739ae039 = (selector)=>{ if (selector instanceof Element) return [ selector ]; if (selector instanceof NodeList) return selector; if (selector instanceof Array) return selector; - return root.querySelectorAll(selector); + return document.querySelectorAll(selector); }; @@ -109,20 +197,26 @@ var $3e2aed16982f049f$export$2e2bcd8739ae039 = (selector, customOptions = {})=>{ ...(0, $caecf5182af9e868$export$2e2bcd8739ae039), ...customOptions }; - const lazyItems = (0, $e5a64a9b43e3c02c$export$2e2bcd8739ae039)(selector); - if (!lazyItems.length) return console.error("No lazy loadable element found!"); const observerCallback = (target)=>{ (0, $94035bc41cd26735$export$2e2bcd8739ae039).loading(target, options); (0, $fa423858cf60d4ae$export$2e2bcd8739ae039)(target, options); }; - lazyItems.forEach((item)=>{ + const processLazyItem = (item)=>{ try { - (0, $3557b12f3d798a99$export$2e2bcd8739ae039)(item); + (0, $94035bc41cd26735$export$2e2bcd8739ae039).waiting(item, options); + (0, $4a8d64b6206062f5$export$2e2bcd8739ae039)(item); (0, $5aa3f28da5200ea6$export$2e2bcd8739ae039)(item, observerCallback, options.observer); } catch (error) { (0, $94035bc41cd26735$export$2e2bcd8739ae039).error(item, options, error.message); } - }); + }; + try { + const lazyItems = (0, $e5a64a9b43e3c02c$export$2e2bcd8739ae039)(selector); + if (!lazyItems.length) throw new Error("No lazy loadable element found!"); + lazyItems.forEach(processLazyItem); + } catch (error) { + console.error("Lazy error:", error.message); + } }; diff --git a/dist/lazy-load.js.map b/dist/lazy-load.js.map index 92719a2..ea3a898 100644 --- a/dist/lazy-load.js.map +++ b/dist/lazy-load.js.map @@ -1 +1 @@ -{"mappings":"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","sources":["src/app.js","src/defaultOptions.js","src/states.js","src/assetLoader.js","src/isSupported.js","src/observer.js","src/getElements.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.7\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './defaultOptions.js';\nimport states from './states.js';\nimport loadAsset from './assetLoader.js';\nimport isSupported from './isSupported.js';\nimport observer from './observer.js';\nimport getElements from './getElements.js';\n\nexport default (selector, customOptions = {}) => {\n const options = { ...defaultOptions, ...customOptions };\n const lazyItems = getElements(selector);\n\n if (!lazyItems.length) return console.error('No lazy loadable element found!');\n\n const observerCallback = (target) => {\n states.loading(target, options);\n loadAsset(target, options);\n };\n\n lazyItems.forEach((item) => {\n try {\n isSupported(item);\n observer(item, observerCallback, options.observer);\n } catch (error) {\n states.error(item, options, error.message);\n }\n });\n};\n","export default {\n attrs: {\n src: 'lazy',\n srcset: 'lazy-srcset',\n poster: 'lazy-poster',\n },\n modifiers: {\n loaded: '-loaded',\n loading: '-loading',\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n onLoaded: () => {},\n onLoading: () => {},\n onError: (element, error) => console.error('Error on:', element, error),\n};\n","const resetAssets = (element, options) => {\n element.removeAttribute(options.attrs.src);\n element.removeAttribute(options.attrs.srcset);\n element.removeAttribute(options.attrs.poster);\n};\n\nconst states = {\n loading: (element, options) => {\n const handleLoad = () => states.loaded(element, options);\n element.classList.add(options.modifiers.loading);\n element.addEventListener('load', handleLoad, { once: true });\n },\n loaded: (element, options) => {\n element.classList.remove(options.modifiers.loading);\n element.classList.add(options.modifiers.loaded);\n\n resetAssets(element, options);\n options.onLoaded(element);\n },\n error: (element, options, error) => {\n element.classList.remove(options.modifiers.loading);\n options.onError(element, error);\n },\n};\n\nexport default states;\n","export default (element, options) => {\n const assets = {\n src: element.getAttribute(options.attrs.src),\n srcset: element.getAttribute(options.attrs.srcset),\n poster: element.getAttribute(options.attrs.poster),\n };\n\n if (assets.src) element.setAttribute('src', assets.src);\n if (assets.srcset) element.setAttribute('srcset', assets.srcset);\n if (assets.poster) element.setAttribute('poster', assets.poster);\n};\n","const supportedElements = ['img', 'picture', 'video', 'embed', 'object'];\n\nexport default (element) => {\n const elementType = element.tagName.toLowerCase();\n const isSupported = supportedElements.includes(elementType);\n\n if (isSupported) return true;\n throw new Error(`Element type ${elementType} is not supported!`);\n};\n","export default (item, callback, settings) => {\n const handleIntersection = (entries, observer) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n\n callback(entry.target);\n observer.unobserve(entry.target);\n });\n };\n\n const observer = new IntersectionObserver(handleIntersection, settings);\n\n observer.observe(item);\n};\n","export default (selector, root = document) => {\n if (selector instanceof Element) return [selector];\n if (selector instanceof NodeList) return selector;\n if (selector instanceof Array) return selector;\n\n return root.querySelectorAll(selector);\n};\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file +{"mappings":"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","sources":["src/app.js","src/defaultOptions.js","src/states.js","src/settings.js","src/assetLoader.js","src/checkSupport.js","src/observer.js","src/getElements.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.7\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './defaultOptions.js';\nimport states from './states.js';\nimport loadAsset from './assetLoader.js';\nimport checkSupport from './checkSupport.js';\nimport observer from './observer.js';\nimport getElements from './getElements.js';\n\nexport default (selector, customOptions = {}) => {\n const options = { ...defaultOptions, ...customOptions };\n\n const observerCallback = (target) => {\n states.loading(target, options);\n loadAsset(target, options);\n };\n\n const processLazyItem = (item) => {\n try {\n states.waiting(item, options);\n\n checkSupport(item);\n observer(item, observerCallback, options.observer);\n } catch (error) {\n states.error(item, options, error.message);\n }\n };\n\n try {\n const lazyItems = getElements(selector);\n if (!lazyItems.length) throw new Error('No lazy loadable element found!');\n\n lazyItems.forEach(processLazyItem);\n } catch (error) {\n console.error('Lazy error:', error.message);\n }\n};\n","/**\n * Default options for the lazy loading functionality.\n *\n * @module defaultOptions\n *\n * @property {Object} attrs - The attributes to be used for lazy loading.\n * @property {string} attrs.src - The attribute for the source of the media.\n * @property {string} attrs.srcset - The attribute for the source set of the media.\n * @property {string} attrs.poster - The attribute for the poster of the media.\n *\n * @property {Object} observer - The options for the Intersection Observer.\n * @property {Element} observer.root - The root element for the Intersection Observer.\n * @property {number} observer.threshold - The threshold for the Intersection Observer.\n * @property {string} observer.rootMargin - The root margin for the Intersection Observer.\n *\n * @property {Function} onLoaded - The callback to be executed when the media is loaded.\n * @property {Function} onLoading - The callback to be executed when the media is loading.\n * @property {Function} onError - The callback to be executed when there is an error loading the media.\n */\nexport default {\n attrs: {\n src: 'lazy',\n srcset: 'lazy-srcset',\n poster: 'lazy-poster',\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n onLoaded: () => {},\n onLoading: () => {},\n onError: (element, error) => console.error('Error on:', element, error),\n};\n","import settings from './settings.js';\n\n/**\n * Object managing different states.\n *\n * @module states\n *\n * @property {function} loading - Function handling loading state operations.\n * @property {function} loaded - Function handling loaded state operations.\n * @property {function} error - Function handling error state operations.\n */\nconst states = {\n waiting: (element, options) => {\n element.setAttribute(settings.stateAttr, settings.states.waiting);\n },\n\n loading: (element, options) => {\n const handleLoad = () => {\n states.loaded(element, options);\n };\n const handleError = () => {\n states.error(element, options, 'loading media.');\n };\n\n element.addEventListener('load', handleLoad, { once: true });\n element.addEventListener('error', handleError, { once: true });\n\n element.setAttribute(settings.stateAttr, settings.states.loading);\n options.onLoading(element);\n },\n\n loaded: (element, options) => {\n element.setAttribute(settings.stateAttr, settings.states.loaded);\n\n element.removeAttribute(options.attrs.src);\n element.removeAttribute(options.attrs.srcset);\n element.removeAttribute(options.attrs.poster);\n\n options.onLoaded(element);\n },\n\n error: (element, options, error) => {\n element.setAttribute(settings.stateAttr, settings.states.error);\n\n options.onError(element, error);\n },\n};\n\nexport default states;\n","/**\n * Default settings for the lazy loading functionality.\n *\n * @module settings\n *\n * @property {string} stateAttr - The attribute to store the state of the lazy loading process.\n * @property {Object} states - The possible states of the lazy loading process.\n * @property {string} states.waiting - The state when the element is waiting to be loaded.\n * @property {string} states.loading - The state when the element is currently loading.\n * @property {string} states.loaded - The state when the element has finished loading.\n * @property {string} states.error - The state when there was an error loading the element.\n * @property {Array.} supportedElements - The types of elements that are supported for lazy loading.\n */\nexport default {\n stateAttr: 'lazy-state',\n states: {\n waiting: 'waiting',\n loading: 'loading',\n loaded: 'loaded',\n error: 'error',\n },\n supportedElements: ['img', 'picture', 'video', 'embed', 'object'],\n};\n","/**\n * Set attributes on the given HTML element based on the provided options.\n *\n * @module assetLoader\n *\n * @param {HTMLElement} element - The HTML element to set attributes on.\n * @param {Object} options - Options for attribute names.\n * @param {Object} options.attrs - Attribute names.\n * @param {string} [options.attrs.src] - Attribute name for 'src'.\n * @param {string} [options.attrs.srcset] - Attribute name for 'srcset'.\n * @param {string} [options.attrs.poster] - Attribute name for 'poster'.\n */\nexport default (element, options) => {\n const assets = {\n src: element.getAttribute(options.attrs.src),\n srcset: element.getAttribute(options.attrs.srcset),\n poster: element.getAttribute(options.attrs.poster),\n };\n\n if (assets.src) element.setAttribute('src', assets.src);\n if (assets.srcset) element.setAttribute('srcset', assets.srcset);\n if (assets.poster) element.setAttribute('poster', assets.poster);\n};\n","import settings from './settings.js';\n\n/**\n * Checks if the given HTML element is of a supported type.\n *\n * @module checkSupport\n *\n * @param {HTMLElement} element - The HTML element to be checked.\n * @throws {Error} Throws an error if the element type is not supported.\n * @returns {boolean} Returns true if the element type is supported.\n */\nexport default (element) => {\n const elementType = element.tagName.toLowerCase();\n const isSupported = settings.supportedElements.includes(elementType);\n\n if (isSupported) return true;\n\n throw new Error(`Element type ${elementType} is not supported!`);\n};\n","/**\n * Creates an Intersection Observer and starts observing the given item.\n *\n * @module observer\n *\n * @param {Element} item - The DOM element to be observed.\n * @param {Function} callback - The function to be called when the item is intersecting.\n * @param {Object} settings - The options for the Intersection Observer.\n */\nexport default (item, callback, settings) => {\n const handleIntersection = (entries, observer) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n\n callback(entry.target);\n observer.unobserve(entry.target);\n });\n };\n\n const observer = new IntersectionObserver(handleIntersection, settings);\n\n observer.observe(item);\n};\n","/**\n * Select elements based on a given selector within a specified root element.\n *\n * @module getElements\n *\n * @param {string | Element | NodeList | Array} selector - The selector to match elements.\n * @returns {NodeList} - The NodeList containing the selected elements.\n */\nexport default (selector) => {\n if (selector instanceof Element) return [selector];\n if (selector instanceof NodeList) return selector;\n if (selector instanceof Array) return selector;\n\n return document.querySelectorAll(selector);\n};\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file From bc07538a8f47bd99a152f598ca3062774c115ffa Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 22:21:29 +0300 Subject: [PATCH 137/185] Add lazy loading functionality to app.js and update index.html --- test/{index.js => app.js} | 0 test/index.html | 2 +- 2 files changed, 1 insertion(+), 1 deletion(-) rename test/{index.js => app.js} (100%) diff --git a/test/index.js b/test/app.js similarity index 100% rename from test/index.js rename to test/app.js diff --git a/test/index.html b/test/index.html index c398174..1b0acb7 100644 --- a/test/index.html +++ b/test/index.html @@ -7,7 +7,7 @@ Lazy-load.js - + From 2e6eb7818b1e122d597ed80f293f72356a9986bd Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Wed, 17 Jan 2024 22:21:50 +0300 Subject: [PATCH 138/185] Update version to 2.0.0 in package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 4601301..56f68c2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lazy-load.js", - "version": "1.1.0", + "version": "2.0.0", "homepage": "https://github.com/drementer/lazy-load.js", "description": "Another, another and another Lazy Load Library", "source": "src/app.js", From 57b6d059cf0434acdf6e869dae59f491d21b1ef6 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 10 Feb 2024 23:38:51 +0300 Subject: [PATCH 139/185] Refactor waiting state function in states.js --- src/states.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/states.js b/src/states.js index 5ef4619..08cc90e 100644 --- a/src/states.js +++ b/src/states.js @@ -10,7 +10,7 @@ import settings from './settings.js'; * @property {function} error - Function handling error state operations. */ const states = { - waiting: (element, options) => { + waiting: (element) => { element.setAttribute(settings.stateAttr, settings.states.waiting); }, From 8a396cc76911f1b609071e89d1eaae45d7a89f2f Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 22 Feb 2024 23:11:43 +0300 Subject: [PATCH 140/185] Add Jasmine unit tests for lazy loading --- package.json | 8 +++++-- spec/helpers/checkState.mjs | 3 +++ spec/helpers/createImage.mjs | 6 ++++++ spec/support/jasmine-browser.json | 17 +++++++++++++++ spec/unit-test.spec.mjs | 35 +++++++++++++++++++++++++++++++ 5 files changed, 67 insertions(+), 2 deletions(-) create mode 100644 spec/helpers/checkState.mjs create mode 100644 spec/helpers/createImage.mjs create mode 100644 spec/support/jasmine-browser.json create mode 100644 spec/unit-test.spec.mjs diff --git a/package.json b/package.json index 56f68c2..3892a7d 100644 --- a/package.json +++ b/package.json @@ -5,12 +5,13 @@ "description": "Another, another and another Lazy Load Library", "source": "src/app.js", "module": "dist/lazy-load.js", - "files": [ + "files": [ "dist" ], "scripts": { "watch": "parcel watch", - "build": "parcel build --no-source-maps --no-cache" + "build": "parcel build --no-source-maps --no-cache", + "jasmine": "jasmine-browser-runner serve" }, "keywords": [ "lazy", @@ -39,6 +40,9 @@ "license": "MIT", "devDependencies": { "@parcel/resolver-glob": "^2.9.3", + "jasmine": "^5.1.0", + "jasmine-browser-runner": "^2.3.0", + "jasmine-core": "^5.1.2", "parcel": "^2.9.3" } } diff --git a/spec/helpers/checkState.mjs b/spec/helpers/checkState.mjs new file mode 100644 index 0000000..cd88311 --- /dev/null +++ b/spec/helpers/checkState.mjs @@ -0,0 +1,3 @@ +export default (image, state) => { + return image.getAttribute('lazy-state') == state; +}; diff --git a/spec/helpers/createImage.mjs b/spec/helpers/createImage.mjs new file mode 100644 index 0000000..8539562 --- /dev/null +++ b/spec/helpers/createImage.mjs @@ -0,0 +1,6 @@ +export default (src) => { + const image = document.createElement('img'); + image.setAttribute('lazy', `${src}?random=${Math.random()}`); + + return document.body.appendChild(image); +}; diff --git a/spec/support/jasmine-browser.json b/spec/support/jasmine-browser.json new file mode 100644 index 0000000..3ee52de --- /dev/null +++ b/spec/support/jasmine-browser.json @@ -0,0 +1,17 @@ +{ + "srcDir": ".", + "srcFiles": [], + "specDir": ".", + "esmFilenameExtension": ".mjs", + "enableTopLevelAwait": false, + "specFiles": ["spec/**/*[sS]pec.?(m)js"], + "helpers": ["spec/helpers/**/*.?(m)js"], + "env": { + "stopSpecOnExpectationFailure": false, + "stopOnSpecFailure": false, + "random": true + }, + "browser": { + "name": "firefox" + } +} diff --git a/spec/unit-test.spec.mjs b/spec/unit-test.spec.mjs new file mode 100644 index 0000000..a7c4c97 --- /dev/null +++ b/spec/unit-test.spec.mjs @@ -0,0 +1,35 @@ +import lazyLoad from '../dist/lazy-load.js'; +import createImage from './helpers/createImage.mjs'; +import checkState from './helpers/checkState.mjs'; + +const states = { + waiting: 'waiting', + loading: 'loading', + loaded: 'loaded', + error: 'error', +}; + +describe('Lazy Load Test', () => { + let image; + + beforeEach(function () { + this.image = createImage('https://unsplash.it/400/400?gravity=center'); + lazyLoad(this.image); + }, 1000); + + it('Was lazy load started?', function (done) { + const isWaiting = checkState(this.image, states.waiting); + + expect(isWaiting).toBe(true); + done(); + }); + + it('Was image loaded?', function (done) { + this.image.onload = () => { + const isLoaded = checkState(this.image, states.loaded); + + expect(isLoaded).toBe(true); + done(); + }; + }); +}); From ace5e91c8ad66f740d4baed9574b663f443c7cba Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 22 Feb 2024 23:11:51 +0300 Subject: [PATCH 141/185] Refactor waiting state function in lazy-load.js --- dist/lazy-load.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index a954adf..56fc29e 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -80,7 +80,7 @@ * @property {function} loaded - Function handling loaded state operations. * @property {function} error - Function handling error state operations. */ const $94035bc41cd26735$var$states = { - waiting: (element, options)=>{ + waiting: (element)=>{ element.setAttribute((0, $51e72698ed0f3e92$export$2e2bcd8739ae039).stateAttr, (0, $51e72698ed0f3e92$export$2e2bcd8739ae039).states.waiting); }, loading: (element, options)=>{ From 92bd974de25a8c852dd6c4aa8d9f5f1cc93210c4 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 22 Feb 2024 23:15:59 +0300 Subject: [PATCH 142/185] Remove unused variable in unit test spec --- spec/unit-test.spec.mjs | 2 -- 1 file changed, 2 deletions(-) diff --git a/spec/unit-test.spec.mjs b/spec/unit-test.spec.mjs index a7c4c97..398a78c 100644 --- a/spec/unit-test.spec.mjs +++ b/spec/unit-test.spec.mjs @@ -10,8 +10,6 @@ const states = { }; describe('Lazy Load Test', () => { - let image; - beforeEach(function () { this.image = createImage('https://unsplash.it/400/400?gravity=center'); lazyLoad(this.image); From 62b339d826417be0dda07b6be5e6dc00d66d7539 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 22 Feb 2024 23:16:09 +0300 Subject: [PATCH 143/185] Refactor image creation in createImage helper --- spec/helpers/createImage.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/helpers/createImage.mjs b/spec/helpers/createImage.mjs index 8539562..8bb2d30 100644 --- a/spec/helpers/createImage.mjs +++ b/spec/helpers/createImage.mjs @@ -1,5 +1,5 @@ export default (src) => { - const image = document.createElement('img'); + const image = new Image(); image.setAttribute('lazy', `${src}?random=${Math.random()}`); return document.body.appendChild(image); From b24d675357d037639225b575a623c01517b4a272 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 22 Feb 2024 23:23:36 +0300 Subject: [PATCH 144/185] Refactor: Project structure --- dist/lazy-load.js | 90 +++++++++++++++---------------- dist/lazy-load.js.map | 2 +- src/app.js | 12 ++--- src/{ => helpers}/assetLoader.js | 0 src/{ => helpers}/checkSupport.js | 2 +- src/{ => helpers}/getElements.js | 0 src/{ => helpers}/observer.js | 0 src/{ => helpers}/states.js | 2 +- src/{ => utils}/defaultOptions.js | 0 src/{ => utils}/settings.js | 0 10 files changed, 54 insertions(+), 54 deletions(-) rename src/{ => helpers}/assetLoader.js (100%) rename src/{ => helpers}/checkSupport.js (92%) rename src/{ => helpers}/getElements.js (100%) rename src/{ => helpers}/observer.js (100%) rename src/{ => helpers}/states.js (96%) rename src/{ => utils}/defaultOptions.js (100%) rename src/{ => utils}/settings.js (100%) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index 56fc29e..8212295 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -24,7 +24,7 @@ * @property {Function} onLoaded - The callback to be executed when the media is loaded. * @property {Function} onLoading - The callback to be executed when the media is loading. * @property {Function} onError - The callback to be executed when there is an error loading the media. - */ var $caecf5182af9e868$export$2e2bcd8739ae039 = { + */ var $e4e7a73bee6a4aee$export$2e2bcd8739ae039 = { attrs: { src: "lazy", srcset: "lazy-srcset", @@ -41,6 +41,29 @@ }; +/** + * Set attributes on the given HTML element based on the provided options. + * + * @module assetLoader + * + * @param {HTMLElement} element - The HTML element to set attributes on. + * @param {Object} options - Options for attribute names. + * @param {Object} options.attrs - Attribute names. + * @param {string} [options.attrs.src] - Attribute name for 'src'. + * @param {string} [options.attrs.srcset] - Attribute name for 'srcset'. + * @param {string} [options.attrs.poster] - Attribute name for 'poster'. + */ var $55aebfb21ba6071b$export$2e2bcd8739ae039 = (element, options)=>{ + const assets = { + src: element.getAttribute(options.attrs.src), + srcset: element.getAttribute(options.attrs.srcset), + poster: element.getAttribute(options.attrs.poster) + }; + if (assets.src) element.setAttribute("src", assets.src); + if (assets.srcset) element.setAttribute("srcset", assets.srcset); + if (assets.poster) element.setAttribute("poster", assets.poster); +}; + + /** * Default settings for the lazy loading functionality. * @@ -53,7 +76,7 @@ * @property {string} states.loaded - The state when the element has finished loading. * @property {string} states.error - The state when there was an error loading the element. * @property {Array.} supportedElements - The types of elements that are supported for lazy loading. - */ var $51e72698ed0f3e92$export$2e2bcd8739ae039 = { + */ var $2e06dbd9a7176757$export$2e2bcd8739ae039 = { stateAttr: "lazy-state", states: { waiting: "waiting", @@ -79,16 +102,16 @@ * @property {function} loading - Function handling loading state operations. * @property {function} loaded - Function handling loaded state operations. * @property {function} error - Function handling error state operations. - */ const $94035bc41cd26735$var$states = { + */ const $be4bb12be4dd9f4e$var$states = { waiting: (element)=>{ - element.setAttribute((0, $51e72698ed0f3e92$export$2e2bcd8739ae039).stateAttr, (0, $51e72698ed0f3e92$export$2e2bcd8739ae039).states.waiting); + element.setAttribute((0, $2e06dbd9a7176757$export$2e2bcd8739ae039).stateAttr, (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).states.waiting); }, loading: (element, options)=>{ const handleLoad = ()=>{ - $94035bc41cd26735$var$states.loaded(element, options); + $be4bb12be4dd9f4e$var$states.loaded(element, options); }; const handleError = ()=>{ - $94035bc41cd26735$var$states.error(element, options, "loading media."); + $be4bb12be4dd9f4e$var$states.error(element, options, "loading media."); }; element.addEventListener("load", handleLoad, { once: true @@ -96,45 +119,22 @@ element.addEventListener("error", handleError, { once: true }); - element.setAttribute((0, $51e72698ed0f3e92$export$2e2bcd8739ae039).stateAttr, (0, $51e72698ed0f3e92$export$2e2bcd8739ae039).states.loading); + element.setAttribute((0, $2e06dbd9a7176757$export$2e2bcd8739ae039).stateAttr, (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).states.loading); options.onLoading(element); }, loaded: (element, options)=>{ - element.setAttribute((0, $51e72698ed0f3e92$export$2e2bcd8739ae039).stateAttr, (0, $51e72698ed0f3e92$export$2e2bcd8739ae039).states.loaded); + element.setAttribute((0, $2e06dbd9a7176757$export$2e2bcd8739ae039).stateAttr, (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).states.loaded); element.removeAttribute(options.attrs.src); element.removeAttribute(options.attrs.srcset); element.removeAttribute(options.attrs.poster); options.onLoaded(element); }, error: (element, options, error)=>{ - element.setAttribute((0, $51e72698ed0f3e92$export$2e2bcd8739ae039).stateAttr, (0, $51e72698ed0f3e92$export$2e2bcd8739ae039).states.error); + element.setAttribute((0, $2e06dbd9a7176757$export$2e2bcd8739ae039).stateAttr, (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).states.error); options.onError(element, error); } }; -var $94035bc41cd26735$export$2e2bcd8739ae039 = $94035bc41cd26735$var$states; - - -/** - * Set attributes on the given HTML element based on the provided options. - * - * @module assetLoader - * - * @param {HTMLElement} element - The HTML element to set attributes on. - * @param {Object} options - Options for attribute names. - * @param {Object} options.attrs - Attribute names. - * @param {string} [options.attrs.src] - Attribute name for 'src'. - * @param {string} [options.attrs.srcset] - Attribute name for 'srcset'. - * @param {string} [options.attrs.poster] - Attribute name for 'poster'. - */ var $fa423858cf60d4ae$export$2e2bcd8739ae039 = (element, options)=>{ - const assets = { - src: element.getAttribute(options.attrs.src), - srcset: element.getAttribute(options.attrs.srcset), - poster: element.getAttribute(options.attrs.poster) - }; - if (assets.src) element.setAttribute("src", assets.src); - if (assets.srcset) element.setAttribute("srcset", assets.srcset); - if (assets.poster) element.setAttribute("poster", assets.poster); -}; +var $be4bb12be4dd9f4e$export$2e2bcd8739ae039 = $be4bb12be4dd9f4e$var$states; @@ -146,9 +146,9 @@ var /** * @param {HTMLElement} element - The HTML element to be checked. * @throws {Error} Throws an error if the element type is not supported. * @returns {boolean} Returns true if the element type is supported. - */ $4a8d64b6206062f5$export$2e2bcd8739ae039 = (element)=>{ + */ $67c2ab11c12b7b4c$export$2e2bcd8739ae039 = (element)=>{ const elementType = element.tagName.toLowerCase(); - const isSupported = (0, $51e72698ed0f3e92$export$2e2bcd8739ae039).supportedElements.includes(elementType); + const isSupported = (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).supportedElements.includes(elementType); if (isSupported) return true; throw new Error(`Element type ${elementType} is not supported!`); }; @@ -162,7 +162,7 @@ var /** * @param {Element} item - The DOM element to be observed. * @param {Function} callback - The function to be called when the item is intersecting. * @param {Object} settings - The options for the Intersection Observer. - */ var $5aa3f28da5200ea6$export$2e2bcd8739ae039 = (item, callback, settings)=>{ + */ var $afbda835b72f3fa2$export$2e2bcd8739ae039 = (item, callback, settings)=>{ const handleIntersection = (entries, observer)=>{ entries.forEach((entry)=>{ if (!entry.isIntersecting) return; @@ -182,7 +182,7 @@ var /** * * @param {string | Element | NodeList | Array} selector - The selector to match elements. * @returns {NodeList} - The NodeList containing the selected elements. - */ var $e5a64a9b43e3c02c$export$2e2bcd8739ae039 = (selector)=>{ + */ var $286db38838bca09d$export$2e2bcd8739ae039 = (selector)=>{ if (selector instanceof Element) return [ selector ]; @@ -194,24 +194,24 @@ var /** var $3e2aed16982f049f$export$2e2bcd8739ae039 = (selector, customOptions = {})=>{ const options = { - ...(0, $caecf5182af9e868$export$2e2bcd8739ae039), + ...(0, $e4e7a73bee6a4aee$export$2e2bcd8739ae039), ...customOptions }; const observerCallback = (target)=>{ - (0, $94035bc41cd26735$export$2e2bcd8739ae039).loading(target, options); - (0, $fa423858cf60d4ae$export$2e2bcd8739ae039)(target, options); + (0, $be4bb12be4dd9f4e$export$2e2bcd8739ae039).loading(target, options); + (0, $55aebfb21ba6071b$export$2e2bcd8739ae039)(target, options); }; const processLazyItem = (item)=>{ try { - (0, $94035bc41cd26735$export$2e2bcd8739ae039).waiting(item, options); - (0, $4a8d64b6206062f5$export$2e2bcd8739ae039)(item); - (0, $5aa3f28da5200ea6$export$2e2bcd8739ae039)(item, observerCallback, options.observer); + (0, $be4bb12be4dd9f4e$export$2e2bcd8739ae039).waiting(item, options); + (0, $67c2ab11c12b7b4c$export$2e2bcd8739ae039)(item); + (0, $afbda835b72f3fa2$export$2e2bcd8739ae039)(item, observerCallback, options.observer); } catch (error) { - (0, $94035bc41cd26735$export$2e2bcd8739ae039).error(item, options, error.message); + (0, $be4bb12be4dd9f4e$export$2e2bcd8739ae039).error(item, options, error.message); } }; try { - const lazyItems = (0, $e5a64a9b43e3c02c$export$2e2bcd8739ae039)(selector); + const lazyItems = (0, $286db38838bca09d$export$2e2bcd8739ae039)(selector); if (!lazyItems.length) throw new Error("No lazy loadable element found!"); lazyItems.forEach(processLazyItem); } catch (error) { diff --git a/dist/lazy-load.js.map b/dist/lazy-load.js.map index ea3a898..00a6fb6 100644 --- a/dist/lazy-load.js.map +++ b/dist/lazy-load.js.map @@ -1 +1 @@ -{"mappings":"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","sources":["src/app.js","src/defaultOptions.js","src/states.js","src/settings.js","src/assetLoader.js","src/checkSupport.js","src/observer.js","src/getElements.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.7\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './defaultOptions.js';\nimport states from './states.js';\nimport loadAsset from './assetLoader.js';\nimport checkSupport from './checkSupport.js';\nimport observer from './observer.js';\nimport getElements from './getElements.js';\n\nexport default (selector, customOptions = {}) => {\n const options = { ...defaultOptions, ...customOptions };\n\n const observerCallback = (target) => {\n states.loading(target, options);\n loadAsset(target, options);\n };\n\n const processLazyItem = (item) => {\n try {\n states.waiting(item, options);\n\n checkSupport(item);\n observer(item, observerCallback, options.observer);\n } catch (error) {\n states.error(item, options, error.message);\n }\n };\n\n try {\n const lazyItems = getElements(selector);\n if (!lazyItems.length) throw new Error('No lazy loadable element found!');\n\n lazyItems.forEach(processLazyItem);\n } catch (error) {\n console.error('Lazy error:', error.message);\n }\n};\n","/**\n * Default options for the lazy loading functionality.\n *\n * @module defaultOptions\n *\n * @property {Object} attrs - The attributes to be used for lazy loading.\n * @property {string} attrs.src - The attribute for the source of the media.\n * @property {string} attrs.srcset - The attribute for the source set of the media.\n * @property {string} attrs.poster - The attribute for the poster of the media.\n *\n * @property {Object} observer - The options for the Intersection Observer.\n * @property {Element} observer.root - The root element for the Intersection Observer.\n * @property {number} observer.threshold - The threshold for the Intersection Observer.\n * @property {string} observer.rootMargin - The root margin for the Intersection Observer.\n *\n * @property {Function} onLoaded - The callback to be executed when the media is loaded.\n * @property {Function} onLoading - The callback to be executed when the media is loading.\n * @property {Function} onError - The callback to be executed when there is an error loading the media.\n */\nexport default {\n attrs: {\n src: 'lazy',\n srcset: 'lazy-srcset',\n poster: 'lazy-poster',\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n onLoaded: () => {},\n onLoading: () => {},\n onError: (element, error) => console.error('Error on:', element, error),\n};\n","import settings from './settings.js';\n\n/**\n * Object managing different states.\n *\n * @module states\n *\n * @property {function} loading - Function handling loading state operations.\n * @property {function} loaded - Function handling loaded state operations.\n * @property {function} error - Function handling error state operations.\n */\nconst states = {\n waiting: (element, options) => {\n element.setAttribute(settings.stateAttr, settings.states.waiting);\n },\n\n loading: (element, options) => {\n const handleLoad = () => {\n states.loaded(element, options);\n };\n const handleError = () => {\n states.error(element, options, 'loading media.');\n };\n\n element.addEventListener('load', handleLoad, { once: true });\n element.addEventListener('error', handleError, { once: true });\n\n element.setAttribute(settings.stateAttr, settings.states.loading);\n options.onLoading(element);\n },\n\n loaded: (element, options) => {\n element.setAttribute(settings.stateAttr, settings.states.loaded);\n\n element.removeAttribute(options.attrs.src);\n element.removeAttribute(options.attrs.srcset);\n element.removeAttribute(options.attrs.poster);\n\n options.onLoaded(element);\n },\n\n error: (element, options, error) => {\n element.setAttribute(settings.stateAttr, settings.states.error);\n\n options.onError(element, error);\n },\n};\n\nexport default states;\n","/**\n * Default settings for the lazy loading functionality.\n *\n * @module settings\n *\n * @property {string} stateAttr - The attribute to store the state of the lazy loading process.\n * @property {Object} states - The possible states of the lazy loading process.\n * @property {string} states.waiting - The state when the element is waiting to be loaded.\n * @property {string} states.loading - The state when the element is currently loading.\n * @property {string} states.loaded - The state when the element has finished loading.\n * @property {string} states.error - The state when there was an error loading the element.\n * @property {Array.} supportedElements - The types of elements that are supported for lazy loading.\n */\nexport default {\n stateAttr: 'lazy-state',\n states: {\n waiting: 'waiting',\n loading: 'loading',\n loaded: 'loaded',\n error: 'error',\n },\n supportedElements: ['img', 'picture', 'video', 'embed', 'object'],\n};\n","/**\n * Set attributes on the given HTML element based on the provided options.\n *\n * @module assetLoader\n *\n * @param {HTMLElement} element - The HTML element to set attributes on.\n * @param {Object} options - Options for attribute names.\n * @param {Object} options.attrs - Attribute names.\n * @param {string} [options.attrs.src] - Attribute name for 'src'.\n * @param {string} [options.attrs.srcset] - Attribute name for 'srcset'.\n * @param {string} [options.attrs.poster] - Attribute name for 'poster'.\n */\nexport default (element, options) => {\n const assets = {\n src: element.getAttribute(options.attrs.src),\n srcset: element.getAttribute(options.attrs.srcset),\n poster: element.getAttribute(options.attrs.poster),\n };\n\n if (assets.src) element.setAttribute('src', assets.src);\n if (assets.srcset) element.setAttribute('srcset', assets.srcset);\n if (assets.poster) element.setAttribute('poster', assets.poster);\n};\n","import settings from './settings.js';\n\n/**\n * Checks if the given HTML element is of a supported type.\n *\n * @module checkSupport\n *\n * @param {HTMLElement} element - The HTML element to be checked.\n * @throws {Error} Throws an error if the element type is not supported.\n * @returns {boolean} Returns true if the element type is supported.\n */\nexport default (element) => {\n const elementType = element.tagName.toLowerCase();\n const isSupported = settings.supportedElements.includes(elementType);\n\n if (isSupported) return true;\n\n throw new Error(`Element type ${elementType} is not supported!`);\n};\n","/**\n * Creates an Intersection Observer and starts observing the given item.\n *\n * @module observer\n *\n * @param {Element} item - The DOM element to be observed.\n * @param {Function} callback - The function to be called when the item is intersecting.\n * @param {Object} settings - The options for the Intersection Observer.\n */\nexport default (item, callback, settings) => {\n const handleIntersection = (entries, observer) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n\n callback(entry.target);\n observer.unobserve(entry.target);\n });\n };\n\n const observer = new IntersectionObserver(handleIntersection, settings);\n\n observer.observe(item);\n};\n","/**\n * Select elements based on a given selector within a specified root element.\n *\n * @module getElements\n *\n * @param {string | Element | NodeList | Array} selector - The selector to match elements.\n * @returns {NodeList} - The NodeList containing the selected elements.\n */\nexport default (selector) => {\n if (selector instanceof Element) return [selector];\n if (selector instanceof NodeList) return selector;\n if (selector instanceof Array) return selector;\n\n return document.querySelectorAll(selector);\n};\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file +{"mappings":"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","sources":["src/app.js","src/utils/defaultOptions.js","src/helpers/assetLoader.js","src/helpers/states.js","src/utils/settings.js","src/helpers/checkSupport.js","src/helpers/observer.js","src/helpers/getElements.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.7\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './utils/defaultOptions.js';\nimport loadAsset from './helpers/assetLoader.js';\nimport states from './helpers/states.js';\nimport checkSupport from './helpers/checkSupport.js';\nimport observer from './helpers/observer.js';\nimport getElements from './helpers/getElements.js';\n\nexport default (selector, customOptions = {}) => {\n const options = { ...defaultOptions, ...customOptions };\n\n const observerCallback = (target) => {\n states.loading(target, options);\n loadAsset(target, options);\n };\n\n const processLazyItem = (item) => {\n try {\n states.waiting(item, options);\n\n checkSupport(item);\n observer(item, observerCallback, options.observer);\n } catch (error) {\n states.error(item, options, error.message);\n }\n };\n\n try {\n const lazyItems = getElements(selector);\n if (!lazyItems.length) throw new Error('No lazy loadable element found!');\n\n lazyItems.forEach(processLazyItem);\n } catch (error) {\n console.error('Lazy error:', error.message);\n }\n};\n","/**\n * Default options for the lazy loading functionality.\n *\n * @module defaultOptions\n *\n * @property {Object} attrs - The attributes to be used for lazy loading.\n * @property {string} attrs.src - The attribute for the source of the media.\n * @property {string} attrs.srcset - The attribute for the source set of the media.\n * @property {string} attrs.poster - The attribute for the poster of the media.\n *\n * @property {Object} observer - The options for the Intersection Observer.\n * @property {Element} observer.root - The root element for the Intersection Observer.\n * @property {number} observer.threshold - The threshold for the Intersection Observer.\n * @property {string} observer.rootMargin - The root margin for the Intersection Observer.\n *\n * @property {Function} onLoaded - The callback to be executed when the media is loaded.\n * @property {Function} onLoading - The callback to be executed when the media is loading.\n * @property {Function} onError - The callback to be executed when there is an error loading the media.\n */\nexport default {\n attrs: {\n src: 'lazy',\n srcset: 'lazy-srcset',\n poster: 'lazy-poster',\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n onLoaded: () => {},\n onLoading: () => {},\n onError: (element, error) => console.error('Error on:', element, error),\n};\n","/**\n * Set attributes on the given HTML element based on the provided options.\n *\n * @module assetLoader\n *\n * @param {HTMLElement} element - The HTML element to set attributes on.\n * @param {Object} options - Options for attribute names.\n * @param {Object} options.attrs - Attribute names.\n * @param {string} [options.attrs.src] - Attribute name for 'src'.\n * @param {string} [options.attrs.srcset] - Attribute name for 'srcset'.\n * @param {string} [options.attrs.poster] - Attribute name for 'poster'.\n */\nexport default (element, options) => {\n const assets = {\n src: element.getAttribute(options.attrs.src),\n srcset: element.getAttribute(options.attrs.srcset),\n poster: element.getAttribute(options.attrs.poster),\n };\n\n if (assets.src) element.setAttribute('src', assets.src);\n if (assets.srcset) element.setAttribute('srcset', assets.srcset);\n if (assets.poster) element.setAttribute('poster', assets.poster);\n};\n","import settings from '../utils/settings.js';\n\n/**\n * Object managing different states.\n *\n * @module states\n *\n * @property {function} loading - Function handling loading state operations.\n * @property {function} loaded - Function handling loaded state operations.\n * @property {function} error - Function handling error state operations.\n */\nconst states = {\n waiting: (element) => {\n element.setAttribute(settings.stateAttr, settings.states.waiting);\n },\n\n loading: (element, options) => {\n const handleLoad = () => {\n states.loaded(element, options);\n };\n const handleError = () => {\n states.error(element, options, 'loading media.');\n };\n\n element.addEventListener('load', handleLoad, { once: true });\n element.addEventListener('error', handleError, { once: true });\n\n element.setAttribute(settings.stateAttr, settings.states.loading);\n options.onLoading(element);\n },\n\n loaded: (element, options) => {\n element.setAttribute(settings.stateAttr, settings.states.loaded);\n\n element.removeAttribute(options.attrs.src);\n element.removeAttribute(options.attrs.srcset);\n element.removeAttribute(options.attrs.poster);\n\n options.onLoaded(element);\n },\n\n error: (element, options, error) => {\n element.setAttribute(settings.stateAttr, settings.states.error);\n\n options.onError(element, error);\n },\n};\n\nexport default states;\n","/**\n * Default settings for the lazy loading functionality.\n *\n * @module settings\n *\n * @property {string} stateAttr - The attribute to store the state of the lazy loading process.\n * @property {Object} states - The possible states of the lazy loading process.\n * @property {string} states.waiting - The state when the element is waiting to be loaded.\n * @property {string} states.loading - The state when the element is currently loading.\n * @property {string} states.loaded - The state when the element has finished loading.\n * @property {string} states.error - The state when there was an error loading the element.\n * @property {Array.} supportedElements - The types of elements that are supported for lazy loading.\n */\nexport default {\n stateAttr: 'lazy-state',\n states: {\n waiting: 'waiting',\n loading: 'loading',\n loaded: 'loaded',\n error: 'error',\n },\n supportedElements: ['img', 'picture', 'video', 'embed', 'object'],\n};\n","import settings from '../utils/settings.js';\n\n/**\n * Checks if the given HTML element is of a supported type.\n *\n * @module checkSupport\n *\n * @param {HTMLElement} element - The HTML element to be checked.\n * @throws {Error} Throws an error if the element type is not supported.\n * @returns {boolean} Returns true if the element type is supported.\n */\nexport default (element) => {\n const elementType = element.tagName.toLowerCase();\n const isSupported = settings.supportedElements.includes(elementType);\n\n if (isSupported) return true;\n\n throw new Error(`Element type ${elementType} is not supported!`);\n};\n","/**\n * Creates an Intersection Observer and starts observing the given item.\n *\n * @module observer\n *\n * @param {Element} item - The DOM element to be observed.\n * @param {Function} callback - The function to be called when the item is intersecting.\n * @param {Object} settings - The options for the Intersection Observer.\n */\nexport default (item, callback, settings) => {\n const handleIntersection = (entries, observer) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n\n callback(entry.target);\n observer.unobserve(entry.target);\n });\n };\n\n const observer = new IntersectionObserver(handleIntersection, settings);\n\n observer.observe(item);\n};\n","/**\n * Select elements based on a given selector within a specified root element.\n *\n * @module getElements\n *\n * @param {string | Element | NodeList | Array} selector - The selector to match elements.\n * @returns {NodeList} - The NodeList containing the selected elements.\n */\nexport default (selector) => {\n if (selector instanceof Element) return [selector];\n if (selector instanceof NodeList) return selector;\n if (selector instanceof Array) return selector;\n\n return document.querySelectorAll(selector);\n};\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file diff --git a/src/app.js b/src/app.js index bc97ec8..f4ce935 100644 --- a/src/app.js +++ b/src/app.js @@ -8,12 +8,12 @@ * @see {@link https://github.com/drementer/lazy-load.js} */ -import defaultOptions from './defaultOptions.js'; -import states from './states.js'; -import loadAsset from './assetLoader.js'; -import checkSupport from './checkSupport.js'; -import observer from './observer.js'; -import getElements from './getElements.js'; +import defaultOptions from './utils/defaultOptions.js'; +import loadAsset from './helpers/assetLoader.js'; +import states from './helpers/states.js'; +import checkSupport from './helpers/checkSupport.js'; +import observer from './helpers/observer.js'; +import getElements from './helpers/getElements.js'; export default (selector, customOptions = {}) => { const options = { ...defaultOptions, ...customOptions }; diff --git a/src/assetLoader.js b/src/helpers/assetLoader.js similarity index 100% rename from src/assetLoader.js rename to src/helpers/assetLoader.js diff --git a/src/checkSupport.js b/src/helpers/checkSupport.js similarity index 92% rename from src/checkSupport.js rename to src/helpers/checkSupport.js index ac2d9ad..04a0d64 100644 --- a/src/checkSupport.js +++ b/src/helpers/checkSupport.js @@ -1,4 +1,4 @@ -import settings from './settings.js'; +import settings from '../utils/settings.js'; /** * Checks if the given HTML element is of a supported type. diff --git a/src/getElements.js b/src/helpers/getElements.js similarity index 100% rename from src/getElements.js rename to src/helpers/getElements.js diff --git a/src/observer.js b/src/helpers/observer.js similarity index 100% rename from src/observer.js rename to src/helpers/observer.js diff --git a/src/states.js b/src/helpers/states.js similarity index 96% rename from src/states.js rename to src/helpers/states.js index 08cc90e..1f28e4e 100644 --- a/src/states.js +++ b/src/helpers/states.js @@ -1,4 +1,4 @@ -import settings from './settings.js'; +import settings from '../utils/settings.js'; /** * Object managing different states. diff --git a/src/defaultOptions.js b/src/utils/defaultOptions.js similarity index 100% rename from src/defaultOptions.js rename to src/utils/defaultOptions.js diff --git a/src/settings.js b/src/utils/settings.js similarity index 100% rename from src/settings.js rename to src/utils/settings.js From 24b6b621d8c98a5feee261d64e15b4ac1345b80d Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Fri, 8 Mar 2024 22:54:49 +0300 Subject: [PATCH 145/185] Add supportedElements to settings.js --- src/utils/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/settings.js b/src/utils/settings.js index d011428..bd72a69 100644 --- a/src/utils/settings.js +++ b/src/utils/settings.js @@ -13,11 +13,11 @@ */ export default { stateAttr: 'lazy-state', + supportedElements: ['img', 'picture', 'video', 'embed', 'object'], states: { waiting: 'waiting', loading: 'loading', loaded: 'loaded', error: 'error', }, - supportedElements: ['img', 'picture', 'video', 'embed', 'object'], }; From 53d5b177cb95edd9df80ea2dad7f98f97286f796 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 30 Mar 2024 17:10:14 +0300 Subject: [PATCH 146/185] Refactor assetLoader.js to use dynamic attribute assignment --- dist/lazy-load.js | 81 ++++++++++++++++++-------------------- src/helpers/assetLoader.js | 17 +++----- 2 files changed, 44 insertions(+), 54 deletions(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index 8212295..83c74d6 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -24,7 +24,7 @@ * @property {Function} onLoaded - The callback to be executed when the media is loaded. * @property {Function} onLoading - The callback to be executed when the media is loading. * @property {Function} onError - The callback to be executed when there is an error loading the media. - */ var $e4e7a73bee6a4aee$export$2e2bcd8739ae039 = { + */ var $fcdb79bf76efe51c$export$2e2bcd8739ae039 = { attrs: { src: "lazy", srcset: "lazy-srcset", @@ -48,19 +48,13 @@ * * @param {HTMLElement} element - The HTML element to set attributes on. * @param {Object} options - Options for attribute names. - * @param {Object} options.attrs - Attribute names. - * @param {string} [options.attrs.src] - Attribute name for 'src'. - * @param {string} [options.attrs.srcset] - Attribute name for 'srcset'. - * @param {string} [options.attrs.poster] - Attribute name for 'poster'. - */ var $55aebfb21ba6071b$export$2e2bcd8739ae039 = (element, options)=>{ - const assets = { - src: element.getAttribute(options.attrs.src), - srcset: element.getAttribute(options.attrs.srcset), - poster: element.getAttribute(options.attrs.poster) + */ var $005d6bb149cc301b$export$2e2bcd8739ae039 = (element, options)=>{ + const attributes = Object.entries(options.attrs); + const loadAttr = ([assetAttr, lazyAttr])=>{ + const assetPath = element.getAttribute(lazyAttr); + if (assetPath) element.setAttribute(assetAttr, assetPath); }; - if (assets.src) element.setAttribute("src", assets.src); - if (assets.srcset) element.setAttribute("srcset", assets.srcset); - if (assets.poster) element.setAttribute("poster", assets.poster); + attributes.forEach(loadAttr); }; @@ -76,21 +70,21 @@ * @property {string} states.loaded - The state when the element has finished loading. * @property {string} states.error - The state when there was an error loading the element. * @property {Array.} supportedElements - The types of elements that are supported for lazy loading. - */ var $2e06dbd9a7176757$export$2e2bcd8739ae039 = { + */ var $28fa4f35244940de$export$2e2bcd8739ae039 = { stateAttr: "lazy-state", - states: { - waiting: "waiting", - loading: "loading", - loaded: "loaded", - error: "error" - }, supportedElements: [ "img", "picture", "video", "embed", "object" - ] + ], + states: { + waiting: "waiting", + loading: "loading", + loaded: "loaded", + error: "error" + } }; @@ -102,16 +96,16 @@ * @property {function} loading - Function handling loading state operations. * @property {function} loaded - Function handling loaded state operations. * @property {function} error - Function handling error state operations. - */ const $be4bb12be4dd9f4e$var$states = { + */ const $fc4b3df073dcc3fa$var$states = { waiting: (element)=>{ - element.setAttribute((0, $2e06dbd9a7176757$export$2e2bcd8739ae039).stateAttr, (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).states.waiting); + element.setAttribute((0, $28fa4f35244940de$export$2e2bcd8739ae039).stateAttr, (0, $28fa4f35244940de$export$2e2bcd8739ae039).states.waiting); }, loading: (element, options)=>{ const handleLoad = ()=>{ - $be4bb12be4dd9f4e$var$states.loaded(element, options); + $fc4b3df073dcc3fa$var$states.loaded(element, options); }; const handleError = ()=>{ - $be4bb12be4dd9f4e$var$states.error(element, options, "loading media."); + $fc4b3df073dcc3fa$var$states.error(element, options, "loading media."); }; element.addEventListener("load", handleLoad, { once: true @@ -119,22 +113,22 @@ element.addEventListener("error", handleError, { once: true }); - element.setAttribute((0, $2e06dbd9a7176757$export$2e2bcd8739ae039).stateAttr, (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).states.loading); + element.setAttribute((0, $28fa4f35244940de$export$2e2bcd8739ae039).stateAttr, (0, $28fa4f35244940de$export$2e2bcd8739ae039).states.loading); options.onLoading(element); }, loaded: (element, options)=>{ - element.setAttribute((0, $2e06dbd9a7176757$export$2e2bcd8739ae039).stateAttr, (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).states.loaded); + element.setAttribute((0, $28fa4f35244940de$export$2e2bcd8739ae039).stateAttr, (0, $28fa4f35244940de$export$2e2bcd8739ae039).states.loaded); element.removeAttribute(options.attrs.src); element.removeAttribute(options.attrs.srcset); element.removeAttribute(options.attrs.poster); options.onLoaded(element); }, error: (element, options, error)=>{ - element.setAttribute((0, $2e06dbd9a7176757$export$2e2bcd8739ae039).stateAttr, (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).states.error); + element.setAttribute((0, $28fa4f35244940de$export$2e2bcd8739ae039).stateAttr, (0, $28fa4f35244940de$export$2e2bcd8739ae039).states.error); options.onError(element, error); } }; -var $be4bb12be4dd9f4e$export$2e2bcd8739ae039 = $be4bb12be4dd9f4e$var$states; +var $fc4b3df073dcc3fa$export$2e2bcd8739ae039 = $fc4b3df073dcc3fa$var$states; @@ -146,9 +140,9 @@ var /** * @param {HTMLElement} element - The HTML element to be checked. * @throws {Error} Throws an error if the element type is not supported. * @returns {boolean} Returns true if the element type is supported. - */ $67c2ab11c12b7b4c$export$2e2bcd8739ae039 = (element)=>{ + */ $9eb20e71c19fcebc$export$2e2bcd8739ae039 = (element)=>{ const elementType = element.tagName.toLowerCase(); - const isSupported = (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).supportedElements.includes(elementType); + const isSupported = (0, $28fa4f35244940de$export$2e2bcd8739ae039).supportedElements.includes(elementType); if (isSupported) return true; throw new Error(`Element type ${elementType} is not supported!`); }; @@ -162,7 +156,7 @@ var /** * @param {Element} item - The DOM element to be observed. * @param {Function} callback - The function to be called when the item is intersecting. * @param {Object} settings - The options for the Intersection Observer. - */ var $afbda835b72f3fa2$export$2e2bcd8739ae039 = (item, callback, settings)=>{ + */ var $c9d82c8f03cb7648$export$2e2bcd8739ae039 = (item, callback, settings)=>{ const handleIntersection = (entries, observer)=>{ entries.forEach((entry)=>{ if (!entry.isIntersecting) return; @@ -182,7 +176,7 @@ var /** * * @param {string | Element | NodeList | Array} selector - The selector to match elements. * @returns {NodeList} - The NodeList containing the selected elements. - */ var $286db38838bca09d$export$2e2bcd8739ae039 = (selector)=>{ + */ var $d7580633941bee6a$export$2e2bcd8739ae039 = (selector)=>{ if (selector instanceof Element) return [ selector ]; @@ -192,26 +186,26 @@ var /** }; -var $3e2aed16982f049f$export$2e2bcd8739ae039 = (selector, customOptions = {})=>{ +var $e05782b8f6baf6a3$export$2e2bcd8739ae039 = (selector, customOptions = {})=>{ const options = { - ...(0, $e4e7a73bee6a4aee$export$2e2bcd8739ae039), + ...(0, $fcdb79bf76efe51c$export$2e2bcd8739ae039), ...customOptions }; const observerCallback = (target)=>{ - (0, $be4bb12be4dd9f4e$export$2e2bcd8739ae039).loading(target, options); - (0, $55aebfb21ba6071b$export$2e2bcd8739ae039)(target, options); + (0, $fc4b3df073dcc3fa$export$2e2bcd8739ae039).loading(target, options); + (0, $005d6bb149cc301b$export$2e2bcd8739ae039)(target, options); }; const processLazyItem = (item)=>{ try { - (0, $be4bb12be4dd9f4e$export$2e2bcd8739ae039).waiting(item, options); - (0, $67c2ab11c12b7b4c$export$2e2bcd8739ae039)(item); - (0, $afbda835b72f3fa2$export$2e2bcd8739ae039)(item, observerCallback, options.observer); + (0, $fc4b3df073dcc3fa$export$2e2bcd8739ae039).waiting(item, options); + (0, $9eb20e71c19fcebc$export$2e2bcd8739ae039)(item); + (0, $c9d82c8f03cb7648$export$2e2bcd8739ae039)(item, observerCallback, options.observer); } catch (error) { - (0, $be4bb12be4dd9f4e$export$2e2bcd8739ae039).error(item, options, error.message); + (0, $fc4b3df073dcc3fa$export$2e2bcd8739ae039).error(item, options, error.message); } }; try { - const lazyItems = (0, $286db38838bca09d$export$2e2bcd8739ae039)(selector); + const lazyItems = (0, $d7580633941bee6a$export$2e2bcd8739ae039)(selector); if (!lazyItems.length) throw new Error("No lazy loadable element found!"); lazyItems.forEach(processLazyItem); } catch (error) { @@ -220,4 +214,5 @@ var $3e2aed16982f049f$export$2e2bcd8739ae039 = (selector, customOptions = {})=>{ }; -export {$3e2aed16982f049f$export$2e2bcd8739ae039 as default}; +export {$e05782b8f6baf6a3$export$2e2bcd8739ae039 as default}; +//# sourceMappingURL=lazy-load.js.map diff --git a/src/helpers/assetLoader.js b/src/helpers/assetLoader.js index cc9d5c2..b14f4dd 100644 --- a/src/helpers/assetLoader.js +++ b/src/helpers/assetLoader.js @@ -5,19 +5,14 @@ * * @param {HTMLElement} element - The HTML element to set attributes on. * @param {Object} options - Options for attribute names. - * @param {Object} options.attrs - Attribute names. - * @param {string} [options.attrs.src] - Attribute name for 'src'. - * @param {string} [options.attrs.srcset] - Attribute name for 'srcset'. - * @param {string} [options.attrs.poster] - Attribute name for 'poster'. */ export default (element, options) => { - const assets = { - src: element.getAttribute(options.attrs.src), - srcset: element.getAttribute(options.attrs.srcset), - poster: element.getAttribute(options.attrs.poster), + const attributes = Object.entries(options.attrs); + + const loadAttr = ([assetAttr, lazyAttr]) => { + const assetPath = element.getAttribute(lazyAttr); + if (assetPath) element.setAttribute(assetAttr, assetPath); }; - if (assets.src) element.setAttribute('src', assets.src); - if (assets.srcset) element.setAttribute('srcset', assets.srcset); - if (assets.poster) element.setAttribute('poster', assets.poster); + attributes.forEach(loadAttr); }; From 681021fd2faacdedeccfd22e128727c5d693cee4 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 30 Mar 2024 17:19:32 +0300 Subject: [PATCH 147/185] Refactor states.js for better code organization --- dist/lazy-load.js | 9 ++++----- src/helpers/states.js | 4 +--- 2 files changed, 5 insertions(+), 8 deletions(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index 83c74d6..a851a91 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -88,7 +88,7 @@ }; -/** +var /** * Object managing different states. * * @module states @@ -96,16 +96,16 @@ * @property {function} loading - Function handling loading state operations. * @property {function} loaded - Function handling loaded state operations. * @property {function} error - Function handling error state operations. - */ const $fc4b3df073dcc3fa$var$states = { + */ $fc4b3df073dcc3fa$export$2e2bcd8739ae039 = { waiting: (element)=>{ element.setAttribute((0, $28fa4f35244940de$export$2e2bcd8739ae039).stateAttr, (0, $28fa4f35244940de$export$2e2bcd8739ae039).states.waiting); }, loading: (element, options)=>{ const handleLoad = ()=>{ - $fc4b3df073dcc3fa$var$states.loaded(element, options); + states.loaded(element, options); }; const handleError = ()=>{ - $fc4b3df073dcc3fa$var$states.error(element, options, "loading media."); + states.error(element, options, "loading media."); }; element.addEventListener("load", handleLoad, { once: true @@ -128,7 +128,6 @@ options.onError(element, error); } }; -var $fc4b3df073dcc3fa$export$2e2bcd8739ae039 = $fc4b3df073dcc3fa$var$states; diff --git a/src/helpers/states.js b/src/helpers/states.js index 1f28e4e..886a5f4 100644 --- a/src/helpers/states.js +++ b/src/helpers/states.js @@ -9,7 +9,7 @@ import settings from '../utils/settings.js'; * @property {function} loaded - Function handling loaded state operations. * @property {function} error - Function handling error state operations. */ -const states = { +export default { waiting: (element) => { element.setAttribute(settings.stateAttr, settings.states.waiting); }, @@ -45,5 +45,3 @@ const states = { options.onError(element, error); }, }; - -export default states; From 33938134df71c94ce91ec02d83a6cb12187fe318 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 1 Apr 2024 00:27:08 +0300 Subject: [PATCH 148/185] Refactor lazyLoad function to accept custom options --- README.md | 24 ++++++++++++++++-------- 1 file changed, 16 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index ab3d5d8..9bc4a4d 100644 --- a/README.md +++ b/README.md @@ -4,24 +4,32 @@ Lazy Load Images is a JavaScript utility that allows you to lazy load visual con ## Usage -To use Lazy Load Images, include the `lazyLoad` function in your JavaScript code. The function takes two optional parameters: +To use Lazy Load Images, include the `lazyLoad` function in your code. The function takes two optional parameters: -- `selector` (string, default: 'lazy'): CSS selector for lazy load items. -- `observerOptions` (object): Options for the Intersection Observer. +- `selector` (string, array, default: 'lazy'): CSS selector for lazy load items. +- `customOptions` (object): Options for the `lazyLoad`. If no selector is provided, the default selector 'lazy' will be used. If no observer options are provided, default options will be used. ```javascript lazyLoad('lazy', { - root: null, - threshold: 1, - rootMargin: '300px 0px', + attrs: { + src: 'lazy', + srcset: 'lazy-srcset', + poster: 'lazy-poster', + }, + observer: { + root: null, + threshold: 1, + rootMargin: '100% 0px', + }, + onLoaded: () => {}, + onLoading: () => {}, + onError: (element, error) => console.error('Error on:', element, error), }); ``` -The lazy load functionality will be applied to all elements that match the specified selector. When an element comes into view, its 'lazy' attribute will be used as the source for the 'src' attribute, and the element will be marked as loaded by adding the '-loaded' class. - ## License [MIT License](https://choosealicense.com/licenses/mit/). From fcf4237d4850177a954ba9a8a475482f9c4d3507 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 1 Apr 2024 22:27:19 +0300 Subject: [PATCH 149/185] Refactor states object and export it as a named constant --- dist/lazy-load.js | 9 +++++---- src/helpers/states.js | 4 +++- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index a851a91..83c74d6 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -88,7 +88,7 @@ }; -var /** +/** * Object managing different states. * * @module states @@ -96,16 +96,16 @@ var /** * @property {function} loading - Function handling loading state operations. * @property {function} loaded - Function handling loaded state operations. * @property {function} error - Function handling error state operations. - */ $fc4b3df073dcc3fa$export$2e2bcd8739ae039 = { + */ const $fc4b3df073dcc3fa$var$states = { waiting: (element)=>{ element.setAttribute((0, $28fa4f35244940de$export$2e2bcd8739ae039).stateAttr, (0, $28fa4f35244940de$export$2e2bcd8739ae039).states.waiting); }, loading: (element, options)=>{ const handleLoad = ()=>{ - states.loaded(element, options); + $fc4b3df073dcc3fa$var$states.loaded(element, options); }; const handleError = ()=>{ - states.error(element, options, "loading media."); + $fc4b3df073dcc3fa$var$states.error(element, options, "loading media."); }; element.addEventListener("load", handleLoad, { once: true @@ -128,6 +128,7 @@ var /** options.onError(element, error); } }; +var $fc4b3df073dcc3fa$export$2e2bcd8739ae039 = $fc4b3df073dcc3fa$var$states; diff --git a/src/helpers/states.js b/src/helpers/states.js index 886a5f4..1f28e4e 100644 --- a/src/helpers/states.js +++ b/src/helpers/states.js @@ -9,7 +9,7 @@ import settings from '../utils/settings.js'; * @property {function} loaded - Function handling loaded state operations. * @property {function} error - Function handling error state operations. */ -export default { +const states = { waiting: (element) => { element.setAttribute(settings.stateAttr, settings.states.waiting); }, @@ -45,3 +45,5 @@ export default { options.onError(element, error); }, }; + +export default states; From d7448a342d785397bf6862e451ec85d618e3b9ac Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 1 Apr 2024 22:28:39 +0300 Subject: [PATCH 150/185] Add error handling for no lazy loadable elements --- src/app.js | 1 - src/helpers/getElements.js | 5 ++++- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/src/app.js b/src/app.js index f4ce935..fc77597 100644 --- a/src/app.js +++ b/src/app.js @@ -36,7 +36,6 @@ export default (selector, customOptions = {}) => { try { const lazyItems = getElements(selector); - if (!lazyItems.length) throw new Error('No lazy loadable element found!'); lazyItems.forEach(processLazyItem); } catch (error) { diff --git a/src/helpers/getElements.js b/src/helpers/getElements.js index 1965a76..122e01b 100644 --- a/src/helpers/getElements.js +++ b/src/helpers/getElements.js @@ -11,5 +11,8 @@ export default (selector) => { if (selector instanceof NodeList) return selector; if (selector instanceof Array) return selector; - return document.querySelectorAll(selector); + const elements = document.querySelectorAll(selector); + if (!elements.length) throw new Error('No lazy loadable element found!'); + + return elements; }; From ccc52f6d4692d70a429b94fdc89e9497ac0f4f5b Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 1 Apr 2024 22:34:46 +0300 Subject: [PATCH 151/185] Fix error handling in lazy-load.js and checkSupport.js --- dist/lazy-load.js | 8 +++++--- src/helpers/checkSupport.js | 5 ++--- src/helpers/getElements.js | 2 +- 3 files changed, 8 insertions(+), 7 deletions(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index 83c74d6..a06c190 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -143,8 +143,8 @@ var /** */ $9eb20e71c19fcebc$export$2e2bcd8739ae039 = (element)=>{ const elementType = element.tagName.toLowerCase(); const isSupported = (0, $28fa4f35244940de$export$2e2bcd8739ae039).supportedElements.includes(elementType); - if (isSupported) return true; - throw new Error(`Element type ${elementType} is not supported!`); + if (isSupported) throw new Error(`${elementType} Element is not supported!`); + return true; }; @@ -182,7 +182,9 @@ var /** ]; if (selector instanceof NodeList) return selector; if (selector instanceof Array) return selector; - return document.querySelectorAll(selector); + const elements = document.querySelectorAll(selector); + if (!elements.length) throw new Error("No lazy loadable element found!"); + return elements; }; diff --git a/src/helpers/checkSupport.js b/src/helpers/checkSupport.js index 04a0d64..01a5919 100644 --- a/src/helpers/checkSupport.js +++ b/src/helpers/checkSupport.js @@ -13,7 +13,6 @@ export default (element) => { const elementType = element.tagName.toLowerCase(); const isSupported = settings.supportedElements.includes(elementType); - if (isSupported) return true; - - throw new Error(`Element type ${elementType} is not supported!`); + if (isSupported) throw new Error(`${elementType} Element is not supported!`); + return true; }; diff --git a/src/helpers/getElements.js b/src/helpers/getElements.js index 122e01b..019315b 100644 --- a/src/helpers/getElements.js +++ b/src/helpers/getElements.js @@ -12,7 +12,7 @@ export default (selector) => { if (selector instanceof Array) return selector; const elements = document.querySelectorAll(selector); - if (!elements.length) throw new Error('No lazy loadable element found!'); + if (!elements.length) throw new Error('No lazy loadable element found!'); return elements; }; From c40a7a1c1ff9a822b3f59b680ec8364e67218219 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Mon, 1 Apr 2024 23:04:40 +0300 Subject: [PATCH 152/185] Update error logging in lazy-load.js --- dist/lazy-load.js | 5 ++--- src/helpers/checkSupport.js | 2 +- src/utils/defaultOptions.js | 2 +- 3 files changed, 4 insertions(+), 5 deletions(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index a06c190..a99ea12 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -37,7 +37,7 @@ }, onLoaded: ()=>{}, onLoading: ()=>{}, - onError: (element, error)=>console.error("Error on:", element, error) + onError: (element, error)=>console.warn("Error on:", element, error) }; @@ -143,7 +143,7 @@ var /** */ $9eb20e71c19fcebc$export$2e2bcd8739ae039 = (element)=>{ const elementType = element.tagName.toLowerCase(); const isSupported = (0, $28fa4f35244940de$export$2e2bcd8739ae039).supportedElements.includes(elementType); - if (isSupported) throw new Error(`${elementType} Element is not supported!`); + if (!isSupported) throw new Error(`${elementType} Element is not supported!`); return true; }; @@ -208,7 +208,6 @@ var $e05782b8f6baf6a3$export$2e2bcd8739ae039 = (selector, customOptions = {})=>{ }; try { const lazyItems = (0, $d7580633941bee6a$export$2e2bcd8739ae039)(selector); - if (!lazyItems.length) throw new Error("No lazy loadable element found!"); lazyItems.forEach(processLazyItem); } catch (error) { console.error("Lazy error:", error.message); diff --git a/src/helpers/checkSupport.js b/src/helpers/checkSupport.js index 01a5919..0ce3b5c 100644 --- a/src/helpers/checkSupport.js +++ b/src/helpers/checkSupport.js @@ -13,6 +13,6 @@ export default (element) => { const elementType = element.tagName.toLowerCase(); const isSupported = settings.supportedElements.includes(elementType); - if (isSupported) throw new Error(`${elementType} Element is not supported!`); + if (!isSupported) throw new Error(`${elementType} Element is not supported!`); return true; }; diff --git a/src/utils/defaultOptions.js b/src/utils/defaultOptions.js index a95a873..ceb70c0 100644 --- a/src/utils/defaultOptions.js +++ b/src/utils/defaultOptions.js @@ -30,5 +30,5 @@ export default { }, onLoaded: () => {}, onLoading: () => {}, - onError: (element, error) => console.error('Error on:', element, error), + onError: (element, error) => console.warn('Error on:', element, error), }; From 82ee7c94317741fdb7153ae85ee3a309238c328b Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 13 Apr 2024 17:01:56 +0300 Subject: [PATCH 153/185] Refactored states.js and app.js to use clearer function names --- src/app.js | 6 +++--- src/helpers/states.js | 19 ++++++++++--------- 2 files changed, 13 insertions(+), 12 deletions(-) diff --git a/src/app.js b/src/app.js index fc77597..d60d234 100644 --- a/src/app.js +++ b/src/app.js @@ -19,18 +19,18 @@ export default (selector, customOptions = {}) => { const options = { ...defaultOptions, ...customOptions }; const observerCallback = (target) => { - states.loading(target, options); + states.setLoading(target, options); loadAsset(target, options); }; const processLazyItem = (item) => { try { - states.waiting(item, options); + states.setWaiting(item, options); checkSupport(item); observer(item, observerCallback, options.observer); } catch (error) { - states.error(item, options, error.message); + states.setError(item, options, error.message); } }; diff --git a/src/helpers/states.js b/src/helpers/states.js index 1f28e4e..600d80b 100644 --- a/src/helpers/states.js +++ b/src/helpers/states.js @@ -5,21 +5,22 @@ import settings from '../utils/settings.js'; * * @module states * - * @property {function} loading - Function handling loading state operations. - * @property {function} loaded - Function handling loaded state operations. - * @property {function} error - Function handling error state operations. + * @property {function} setWaitingState - Function handling waiting state operations. + * @property {function} setLoadingState - Function handling loading state operations. + * @property {function} setLoadedState - Function handling loaded state operations. + * @property {function} setErrorState - Function handling error state operations. */ const states = { - waiting: (element) => { + setWaiting: (element) => { element.setAttribute(settings.stateAttr, settings.states.waiting); }, - loading: (element, options) => { + setLoading: (element, options) => { const handleLoad = () => { - states.loaded(element, options); + states.setLoaded(element, options); }; const handleError = () => { - states.error(element, options, 'loading media.'); + states.setError(element, options, 'loading media.'); }; element.addEventListener('load', handleLoad, { once: true }); @@ -29,7 +30,7 @@ const states = { options.onLoading(element); }, - loaded: (element, options) => { + setLoaded: (element, options) => { element.setAttribute(settings.stateAttr, settings.states.loaded); element.removeAttribute(options.attrs.src); @@ -39,7 +40,7 @@ const states = { options.onLoaded(element); }, - error: (element, options, error) => { + setError: (element, options, error) => { element.setAttribute(settings.stateAttr, settings.states.error); options.onError(element, error); From cbeab11f9289dba4457c11f8566d58a6cdb0e0af Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 13 Apr 2024 18:29:38 +0300 Subject: [PATCH 154/185] Refactor lazy loading code and handle media load and error events --- src/app.js | 10 ++++++++++ src/helpers/states.js | 18 +++--------------- 2 files changed, 13 insertions(+), 15 deletions(-) diff --git a/src/app.js b/src/app.js index d60d234..19e6dd4 100644 --- a/src/app.js +++ b/src/app.js @@ -24,11 +24,21 @@ export default (selector, customOptions = {}) => { }; const processLazyItem = (item) => { + const handleLoad = () => { + states.setLoaded(item, options); + }; + const handleError = () => { + throw new Error('Loading media.'); + }; + try { states.setWaiting(item, options); checkSupport(item); observer(item, observerCallback, options.observer); + + item.addEventListener('load', handleLoad, { once: true }); + item.addEventListener('error', handleError, { once: true }); } catch (error) { states.setError(item, options, error.message); } diff --git a/src/helpers/states.js b/src/helpers/states.js index 600d80b..a1392c0 100644 --- a/src/helpers/states.js +++ b/src/helpers/states.js @@ -16,27 +16,15 @@ const states = { }, setLoading: (element, options) => { - const handleLoad = () => { - states.setLoaded(element, options); - }; - const handleError = () => { - states.setError(element, options, 'loading media.'); - }; - - element.addEventListener('load', handleLoad, { once: true }); - element.addEventListener('error', handleError, { once: true }); - element.setAttribute(settings.stateAttr, settings.states.loading); options.onLoading(element); }, setLoaded: (element, options) => { - element.setAttribute(settings.stateAttr, settings.states.loaded); - - element.removeAttribute(options.attrs.src); - element.removeAttribute(options.attrs.srcset); - element.removeAttribute(options.attrs.poster); + const assetAttr = Object.entries(options.attrs); + element.setAttribute(settings.stateAttr, settings.states.loaded); + assetAttr.forEach(([attr]) => element.removeAttribute(attr)); options.onLoaded(element); }, From e215ac9bc397b029e10c62133438b62541a70f99 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 13 Apr 2024 19:18:10 +0300 Subject: [PATCH 155/185] Remove 'picture' from supportedElements array in settings.js --- src/utils/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/settings.js b/src/utils/settings.js index bd72a69..30ad458 100644 --- a/src/utils/settings.js +++ b/src/utils/settings.js @@ -13,7 +13,7 @@ */ export default { stateAttr: 'lazy-state', - supportedElements: ['img', 'picture', 'video', 'embed', 'object'], + supportedElements: ['img', 'video', 'embed', 'object'], states: { waiting: 'waiting', loading: 'loading', From 6eb7eaeff90942b1ea3d10c3cf6aa1f01ba06efe Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 13 Apr 2024 20:42:11 +0300 Subject: [PATCH 156/185] Add support for iframe and audio elements in settings.js --- src/utils/settings.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/utils/settings.js b/src/utils/settings.js index 30ad458..0e41429 100644 --- a/src/utils/settings.js +++ b/src/utils/settings.js @@ -13,7 +13,7 @@ */ export default { stateAttr: 'lazy-state', - supportedElements: ['img', 'video', 'embed', 'object'], + supportedElements: ['img', 'video', 'embed', 'object', 'iframe', 'audio'], states: { waiting: 'waiting', loading: 'loading', From 3a8b863c92696c49300e2e254bc4f8adddde7af6 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 13 Apr 2024 20:42:25 +0300 Subject: [PATCH 157/185] Refactor lazy loading logic in app.js --- src/app.js | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/app.js b/src/app.js index 19e6dd4..a533e43 100644 --- a/src/app.js +++ b/src/app.js @@ -18,27 +18,28 @@ import getElements from './helpers/getElements.js'; export default (selector, customOptions = {}) => { const options = { ...defaultOptions, ...customOptions }; - const observerCallback = (target) => { - states.setLoading(target, options); - loadAsset(target, options); - }; - - const processLazyItem = (item) => { + const handleLoading = (target) => { const handleLoad = () => { - states.setLoaded(item, options); + states.setLoaded(target, options); }; + const handleError = () => { - throw new Error('Loading media.'); + states.setError(target, options, 'Loading media.'); }; + states.setLoading(target, options); + loadAsset(target, options); + + target.addEventListener('load', handleLoad, { once: true }); + target.addEventListener('error', handleError, { once: true }); + }; + + const processLazyItem = (item) => { try { states.setWaiting(item, options); checkSupport(item); - observer(item, observerCallback, options.observer); - - item.addEventListener('load', handleLoad, { once: true }); - item.addEventListener('error', handleError, { once: true }); + observer(item, handleLoading, options.observer); } catch (error) { states.setError(item, options, error.message); } From 4ddcc7aab0cf3f0a15ee53e5a0c5e1b92b3860a5 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 13 Apr 2024 20:42:36 +0300 Subject: [PATCH 158/185] Refactor states.js to export default object --- src/helpers/states.js | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/src/helpers/states.js b/src/helpers/states.js index a1392c0..f68db1a 100644 --- a/src/helpers/states.js +++ b/src/helpers/states.js @@ -10,7 +10,7 @@ import settings from '../utils/settings.js'; * @property {function} setLoadedState - Function handling loaded state operations. * @property {function} setErrorState - Function handling error state operations. */ -const states = { +export default { setWaiting: (element) => { element.setAttribute(settings.stateAttr, settings.states.waiting); }, @@ -24,15 +24,12 @@ const states = { const assetAttr = Object.entries(options.attrs); element.setAttribute(settings.stateAttr, settings.states.loaded); - assetAttr.forEach(([attr]) => element.removeAttribute(attr)); + assetAttr.forEach(([attr, lazyAttr]) => element.removeAttribute(lazyAttr)); options.onLoaded(element); }, setError: (element, options, error) => { element.setAttribute(settings.stateAttr, settings.states.error); - options.onError(element, error); }, }; - -export default states; From e4b3342800e7dac07c969a81040094d55b3027b5 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 14 Apr 2024 03:47:39 +0300 Subject: [PATCH 159/185] Update setWaiting function to include onWaiting callback --- src/helpers/states.js | 3 ++- src/utils/defaultOptions.js | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/helpers/states.js b/src/helpers/states.js index f68db1a..c9eeafc 100644 --- a/src/helpers/states.js +++ b/src/helpers/states.js @@ -11,8 +11,9 @@ import settings from '../utils/settings.js'; * @property {function} setErrorState - Function handling error state operations. */ export default { - setWaiting: (element) => { + setWaiting: (element, options) => { element.setAttribute(settings.stateAttr, settings.states.waiting); + options.onWaiting(element); }, setLoading: (element, options) => { diff --git a/src/utils/defaultOptions.js b/src/utils/defaultOptions.js index ceb70c0..65158f9 100644 --- a/src/utils/defaultOptions.js +++ b/src/utils/defaultOptions.js @@ -28,6 +28,7 @@ export default { threshold: 1, rootMargin: '100% 0px', }, + onWaiting: () => {}, onLoaded: () => {}, onLoading: () => {}, onError: (element, error) => console.warn('Error on:', element, error), From 8a6c53ed7be94ba82c6efd169ceb4ca6dd02bcd0 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 14 Apr 2024 03:48:17 +0300 Subject: [PATCH 160/185] Update error handling in states.js and defaultOptions.js --- src/helpers/states.js | 1 + src/utils/defaultOptions.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/helpers/states.js b/src/helpers/states.js index c9eeafc..6237766 100644 --- a/src/helpers/states.js +++ b/src/helpers/states.js @@ -30,6 +30,7 @@ export default { }, setError: (element, options, error) => { + console.warn('Error on:', element, error); element.setAttribute(settings.stateAttr, settings.states.error); options.onError(element, error); }, diff --git a/src/utils/defaultOptions.js b/src/utils/defaultOptions.js index 65158f9..2ce1d89 100644 --- a/src/utils/defaultOptions.js +++ b/src/utils/defaultOptions.js @@ -31,5 +31,5 @@ export default { onWaiting: () => {}, onLoaded: () => {}, onLoading: () => {}, - onError: (element, error) => console.warn('Error on:', element, error), + onError: () => {}, }; From 6f2eafcfe4e584b5d216e9855b530bd8cf64ffcd Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 14 Apr 2024 03:48:31 +0300 Subject: [PATCH 161/185] Refactor app.js to set waiting state before checking support --- src/app.js | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/app.js b/src/app.js index a533e43..2ef3f2e 100644 --- a/src/app.js +++ b/src/app.js @@ -36,9 +36,8 @@ export default (selector, customOptions = {}) => { const processLazyItem = (item) => { try { - states.setWaiting(item, options); - checkSupport(item); + states.setWaiting(item, options); observer(item, handleLoading, options.observer); } catch (error) { states.setError(item, options, error.message); From 302cb77775e0cf27a423e6230b6694cacc401738 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 14 Apr 2024 03:49:55 +0300 Subject: [PATCH 162/185] Refactor assetLoader.js to use more descriptive variable names --- src/helpers/assetLoader.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/helpers/assetLoader.js b/src/helpers/assetLoader.js index b14f4dd..ef1b100 100644 --- a/src/helpers/assetLoader.js +++ b/src/helpers/assetLoader.js @@ -9,9 +9,9 @@ export default (element, options) => { const attributes = Object.entries(options.attrs); - const loadAttr = ([assetAttr, lazyAttr]) => { + const loadAttr = ([attr, lazyAttr]) => { const assetPath = element.getAttribute(lazyAttr); - if (assetPath) element.setAttribute(assetAttr, assetPath); + if (assetPath) element.setAttribute(attr, assetPath); }; attributes.forEach(loadAttr); From 316356fa8573125a0e8315c158d8a2261f21dab0 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 14 Apr 2024 03:55:43 +0300 Subject: [PATCH 163/185] Refactor defaultOptions and settings modules --- src/utils/defaultOptions.js | 8 -------- src/utils/settings.js | 6 +----- 2 files changed, 1 insertion(+), 13 deletions(-) diff --git a/src/utils/defaultOptions.js b/src/utils/defaultOptions.js index 2ce1d89..384c41c 100644 --- a/src/utils/defaultOptions.js +++ b/src/utils/defaultOptions.js @@ -4,15 +4,7 @@ * @module defaultOptions * * @property {Object} attrs - The attributes to be used for lazy loading. - * @property {string} attrs.src - The attribute for the source of the media. - * @property {string} attrs.srcset - The attribute for the source set of the media. - * @property {string} attrs.poster - The attribute for the poster of the media. - * * @property {Object} observer - The options for the Intersection Observer. - * @property {Element} observer.root - The root element for the Intersection Observer. - * @property {number} observer.threshold - The threshold for the Intersection Observer. - * @property {string} observer.rootMargin - The root margin for the Intersection Observer. - * * @property {Function} onLoaded - The callback to be executed when the media is loaded. * @property {Function} onLoading - The callback to be executed when the media is loading. * @property {Function} onError - The callback to be executed when there is an error loading the media. diff --git a/src/utils/settings.js b/src/utils/settings.js index 0e41429..d84eea7 100644 --- a/src/utils/settings.js +++ b/src/utils/settings.js @@ -4,12 +4,8 @@ * @module settings * * @property {string} stateAttr - The attribute to store the state of the lazy loading process. + * @property {Array} supportedElements - The types of elements that are supported for lazy loading. * @property {Object} states - The possible states of the lazy loading process. - * @property {string} states.waiting - The state when the element is waiting to be loaded. - * @property {string} states.loading - The state when the element is currently loading. - * @property {string} states.loaded - The state when the element has finished loading. - * @property {string} states.error - The state when there was an error loading the element. - * @property {Array.} supportedElements - The types of elements that are supported for lazy loading. */ export default { stateAttr: 'lazy-state', From 947a962121e4a26b0fab1957cd10263b3ba73918 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 14 Apr 2024 03:56:21 +0300 Subject: [PATCH 164/185] Refactor code for improved performance --- dist/lazy-load.js | 122 +++++++++++++++++++----------------------- dist/lazy-load.js.map | 2 +- 2 files changed, 57 insertions(+), 67 deletions(-) diff --git a/dist/lazy-load.js b/dist/lazy-load.js index a99ea12..924fd80 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -12,19 +12,11 @@ * @module defaultOptions * * @property {Object} attrs - The attributes to be used for lazy loading. - * @property {string} attrs.src - The attribute for the source of the media. - * @property {string} attrs.srcset - The attribute for the source set of the media. - * @property {string} attrs.poster - The attribute for the poster of the media. - * * @property {Object} observer - The options for the Intersection Observer. - * @property {Element} observer.root - The root element for the Intersection Observer. - * @property {number} observer.threshold - The threshold for the Intersection Observer. - * @property {string} observer.rootMargin - The root margin for the Intersection Observer. - * * @property {Function} onLoaded - The callback to be executed when the media is loaded. * @property {Function} onLoading - The callback to be executed when the media is loading. * @property {Function} onError - The callback to be executed when there is an error loading the media. - */ var $fcdb79bf76efe51c$export$2e2bcd8739ae039 = { + */ var $e4e7a73bee6a4aee$export$2e2bcd8739ae039 = { attrs: { src: "lazy", srcset: "lazy-srcset", @@ -35,9 +27,10 @@ threshold: 1, rootMargin: "100% 0px" }, + onWaiting: ()=>{}, onLoaded: ()=>{}, onLoading: ()=>{}, - onError: (element, error)=>console.warn("Error on:", element, error) + onError: ()=>{} }; @@ -48,11 +41,11 @@ * * @param {HTMLElement} element - The HTML element to set attributes on. * @param {Object} options - Options for attribute names. - */ var $005d6bb149cc301b$export$2e2bcd8739ae039 = (element, options)=>{ + */ var $55aebfb21ba6071b$export$2e2bcd8739ae039 = (element, options)=>{ const attributes = Object.entries(options.attrs); - const loadAttr = ([assetAttr, lazyAttr])=>{ + const loadAttr = ([attr, lazyAttr])=>{ const assetPath = element.getAttribute(lazyAttr); - if (assetPath) element.setAttribute(assetAttr, assetPath); + if (assetPath) element.setAttribute(attr, assetPath); }; attributes.forEach(loadAttr); }; @@ -64,20 +57,17 @@ * @module settings * * @property {string} stateAttr - The attribute to store the state of the lazy loading process. + * @property {Array} supportedElements - The types of elements that are supported for lazy loading. * @property {Object} states - The possible states of the lazy loading process. - * @property {string} states.waiting - The state when the element is waiting to be loaded. - * @property {string} states.loading - The state when the element is currently loading. - * @property {string} states.loaded - The state when the element has finished loading. - * @property {string} states.error - The state when there was an error loading the element. - * @property {Array.} supportedElements - The types of elements that are supported for lazy loading. - */ var $28fa4f35244940de$export$2e2bcd8739ae039 = { + */ var $2e06dbd9a7176757$export$2e2bcd8739ae039 = { stateAttr: "lazy-state", supportedElements: [ "img", - "picture", "video", "embed", - "object" + "object", + "iframe", + "audio" ], states: { waiting: "waiting", @@ -88,47 +78,36 @@ }; -/** +var /** * Object managing different states. * * @module states * - * @property {function} loading - Function handling loading state operations. - * @property {function} loaded - Function handling loaded state operations. - * @property {function} error - Function handling error state operations. - */ const $fc4b3df073dcc3fa$var$states = { - waiting: (element)=>{ - element.setAttribute((0, $28fa4f35244940de$export$2e2bcd8739ae039).stateAttr, (0, $28fa4f35244940de$export$2e2bcd8739ae039).states.waiting); + * @property {function} setWaitingState - Function handling waiting state operations. + * @property {function} setLoadingState - Function handling loading state operations. + * @property {function} setLoadedState - Function handling loaded state operations. + * @property {function} setErrorState - Function handling error state operations. + */ $be4bb12be4dd9f4e$export$2e2bcd8739ae039 = { + setWaiting: (element, options)=>{ + element.setAttribute((0, $2e06dbd9a7176757$export$2e2bcd8739ae039).stateAttr, (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).states.waiting); + options.onWaiting(element); }, - loading: (element, options)=>{ - const handleLoad = ()=>{ - $fc4b3df073dcc3fa$var$states.loaded(element, options); - }; - const handleError = ()=>{ - $fc4b3df073dcc3fa$var$states.error(element, options, "loading media."); - }; - element.addEventListener("load", handleLoad, { - once: true - }); - element.addEventListener("error", handleError, { - once: true - }); - element.setAttribute((0, $28fa4f35244940de$export$2e2bcd8739ae039).stateAttr, (0, $28fa4f35244940de$export$2e2bcd8739ae039).states.loading); + setLoading: (element, options)=>{ + element.setAttribute((0, $2e06dbd9a7176757$export$2e2bcd8739ae039).stateAttr, (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).states.loading); options.onLoading(element); }, - loaded: (element, options)=>{ - element.setAttribute((0, $28fa4f35244940de$export$2e2bcd8739ae039).stateAttr, (0, $28fa4f35244940de$export$2e2bcd8739ae039).states.loaded); - element.removeAttribute(options.attrs.src); - element.removeAttribute(options.attrs.srcset); - element.removeAttribute(options.attrs.poster); + setLoaded: (element, options)=>{ + const assetAttr = Object.entries(options.attrs); + element.setAttribute((0, $2e06dbd9a7176757$export$2e2bcd8739ae039).stateAttr, (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).states.loaded); + assetAttr.forEach(([attr, lazyAttr])=>element.removeAttribute(lazyAttr)); options.onLoaded(element); }, - error: (element, options, error)=>{ - element.setAttribute((0, $28fa4f35244940de$export$2e2bcd8739ae039).stateAttr, (0, $28fa4f35244940de$export$2e2bcd8739ae039).states.error); + setError: (element, options, error)=>{ + console.warn("Error on:", element, error); + element.setAttribute((0, $2e06dbd9a7176757$export$2e2bcd8739ae039).stateAttr, (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).states.error); options.onError(element, error); } }; -var $fc4b3df073dcc3fa$export$2e2bcd8739ae039 = $fc4b3df073dcc3fa$var$states; @@ -140,9 +119,9 @@ var /** * @param {HTMLElement} element - The HTML element to be checked. * @throws {Error} Throws an error if the element type is not supported. * @returns {boolean} Returns true if the element type is supported. - */ $9eb20e71c19fcebc$export$2e2bcd8739ae039 = (element)=>{ + */ $67c2ab11c12b7b4c$export$2e2bcd8739ae039 = (element)=>{ const elementType = element.tagName.toLowerCase(); - const isSupported = (0, $28fa4f35244940de$export$2e2bcd8739ae039).supportedElements.includes(elementType); + const isSupported = (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).supportedElements.includes(elementType); if (!isSupported) throw new Error(`${elementType} Element is not supported!`); return true; }; @@ -156,7 +135,7 @@ var /** * @param {Element} item - The DOM element to be observed. * @param {Function} callback - The function to be called when the item is intersecting. * @param {Object} settings - The options for the Intersection Observer. - */ var $c9d82c8f03cb7648$export$2e2bcd8739ae039 = (item, callback, settings)=>{ + */ var $afbda835b72f3fa2$export$2e2bcd8739ae039 = (item, callback, settings)=>{ const handleIntersection = (entries, observer)=>{ entries.forEach((entry)=>{ if (!entry.isIntersecting) return; @@ -176,7 +155,7 @@ var /** * * @param {string | Element | NodeList | Array} selector - The selector to match elements. * @returns {NodeList} - The NodeList containing the selected elements. - */ var $d7580633941bee6a$export$2e2bcd8739ae039 = (selector)=>{ + */ var $286db38838bca09d$export$2e2bcd8739ae039 = (selector)=>{ if (selector instanceof Element) return [ selector ]; @@ -188,26 +167,38 @@ var /** }; -var $e05782b8f6baf6a3$export$2e2bcd8739ae039 = (selector, customOptions = {})=>{ +var $3e2aed16982f049f$export$2e2bcd8739ae039 = (selector, customOptions = {})=>{ const options = { - ...(0, $fcdb79bf76efe51c$export$2e2bcd8739ae039), + ...(0, $e4e7a73bee6a4aee$export$2e2bcd8739ae039), ...customOptions }; - const observerCallback = (target)=>{ - (0, $fc4b3df073dcc3fa$export$2e2bcd8739ae039).loading(target, options); - (0, $005d6bb149cc301b$export$2e2bcd8739ae039)(target, options); + const handleLoading = (target)=>{ + const handleLoad = ()=>{ + (0, $be4bb12be4dd9f4e$export$2e2bcd8739ae039).setLoaded(target, options); + }; + const handleError = ()=>{ + (0, $be4bb12be4dd9f4e$export$2e2bcd8739ae039).setError(target, options, "Loading media."); + }; + (0, $be4bb12be4dd9f4e$export$2e2bcd8739ae039).setLoading(target, options); + (0, $55aebfb21ba6071b$export$2e2bcd8739ae039)(target, options); + target.addEventListener("load", handleLoad, { + once: true + }); + target.addEventListener("error", handleError, { + once: true + }); }; const processLazyItem = (item)=>{ try { - (0, $fc4b3df073dcc3fa$export$2e2bcd8739ae039).waiting(item, options); - (0, $9eb20e71c19fcebc$export$2e2bcd8739ae039)(item); - (0, $c9d82c8f03cb7648$export$2e2bcd8739ae039)(item, observerCallback, options.observer); + (0, $67c2ab11c12b7b4c$export$2e2bcd8739ae039)(item); + (0, $be4bb12be4dd9f4e$export$2e2bcd8739ae039).setWaiting(item, options); + (0, $afbda835b72f3fa2$export$2e2bcd8739ae039)(item, handleLoading, options.observer); } catch (error) { - (0, $fc4b3df073dcc3fa$export$2e2bcd8739ae039).error(item, options, error.message); + (0, $be4bb12be4dd9f4e$export$2e2bcd8739ae039).setError(item, options, error.message); } }; try { - const lazyItems = (0, $d7580633941bee6a$export$2e2bcd8739ae039)(selector); + const lazyItems = (0, $286db38838bca09d$export$2e2bcd8739ae039)(selector); lazyItems.forEach(processLazyItem); } catch (error) { console.error("Lazy error:", error.message); @@ -215,5 +206,4 @@ var $e05782b8f6baf6a3$export$2e2bcd8739ae039 = (selector, customOptions = {})=>{ }; -export {$e05782b8f6baf6a3$export$2e2bcd8739ae039 as default}; -//# sourceMappingURL=lazy-load.js.map +export {$3e2aed16982f049f$export$2e2bcd8739ae039 as default}; diff --git a/dist/lazy-load.js.map b/dist/lazy-load.js.map index 00a6fb6..e40bcf3b 100644 --- a/dist/lazy-load.js.map +++ b/dist/lazy-load.js.map @@ -1 +1 @@ -{"mappings":"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","sources":["src/app.js","src/utils/defaultOptions.js","src/helpers/assetLoader.js","src/helpers/states.js","src/utils/settings.js","src/helpers/checkSupport.js","src/helpers/observer.js","src/helpers/getElements.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.7\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './utils/defaultOptions.js';\nimport loadAsset from './helpers/assetLoader.js';\nimport states from './helpers/states.js';\nimport checkSupport from './helpers/checkSupport.js';\nimport observer from './helpers/observer.js';\nimport getElements from './helpers/getElements.js';\n\nexport default (selector, customOptions = {}) => {\n const options = { ...defaultOptions, ...customOptions };\n\n const observerCallback = (target) => {\n states.loading(target, options);\n loadAsset(target, options);\n };\n\n const processLazyItem = (item) => {\n try {\n states.waiting(item, options);\n\n checkSupport(item);\n observer(item, observerCallback, options.observer);\n } catch (error) {\n states.error(item, options, error.message);\n }\n };\n\n try {\n const lazyItems = getElements(selector);\n if (!lazyItems.length) throw new Error('No lazy loadable element found!');\n\n lazyItems.forEach(processLazyItem);\n } catch (error) {\n console.error('Lazy error:', error.message);\n }\n};\n","/**\n * Default options for the lazy loading functionality.\n *\n * @module defaultOptions\n *\n * @property {Object} attrs - The attributes to be used for lazy loading.\n * @property {string} attrs.src - The attribute for the source of the media.\n * @property {string} attrs.srcset - The attribute for the source set of the media.\n * @property {string} attrs.poster - The attribute for the poster of the media.\n *\n * @property {Object} observer - The options for the Intersection Observer.\n * @property {Element} observer.root - The root element for the Intersection Observer.\n * @property {number} observer.threshold - The threshold for the Intersection Observer.\n * @property {string} observer.rootMargin - The root margin for the Intersection Observer.\n *\n * @property {Function} onLoaded - The callback to be executed when the media is loaded.\n * @property {Function} onLoading - The callback to be executed when the media is loading.\n * @property {Function} onError - The callback to be executed when there is an error loading the media.\n */\nexport default {\n attrs: {\n src: 'lazy',\n srcset: 'lazy-srcset',\n poster: 'lazy-poster',\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n onLoaded: () => {},\n onLoading: () => {},\n onError: (element, error) => console.error('Error on:', element, error),\n};\n","/**\n * Set attributes on the given HTML element based on the provided options.\n *\n * @module assetLoader\n *\n * @param {HTMLElement} element - The HTML element to set attributes on.\n * @param {Object} options - Options for attribute names.\n * @param {Object} options.attrs - Attribute names.\n * @param {string} [options.attrs.src] - Attribute name for 'src'.\n * @param {string} [options.attrs.srcset] - Attribute name for 'srcset'.\n * @param {string} [options.attrs.poster] - Attribute name for 'poster'.\n */\nexport default (element, options) => {\n const assets = {\n src: element.getAttribute(options.attrs.src),\n srcset: element.getAttribute(options.attrs.srcset),\n poster: element.getAttribute(options.attrs.poster),\n };\n\n if (assets.src) element.setAttribute('src', assets.src);\n if (assets.srcset) element.setAttribute('srcset', assets.srcset);\n if (assets.poster) element.setAttribute('poster', assets.poster);\n};\n","import settings from '../utils/settings.js';\n\n/**\n * Object managing different states.\n *\n * @module states\n *\n * @property {function} loading - Function handling loading state operations.\n * @property {function} loaded - Function handling loaded state operations.\n * @property {function} error - Function handling error state operations.\n */\nconst states = {\n waiting: (element) => {\n element.setAttribute(settings.stateAttr, settings.states.waiting);\n },\n\n loading: (element, options) => {\n const handleLoad = () => {\n states.loaded(element, options);\n };\n const handleError = () => {\n states.error(element, options, 'loading media.');\n };\n\n element.addEventListener('load', handleLoad, { once: true });\n element.addEventListener('error', handleError, { once: true });\n\n element.setAttribute(settings.stateAttr, settings.states.loading);\n options.onLoading(element);\n },\n\n loaded: (element, options) => {\n element.setAttribute(settings.stateAttr, settings.states.loaded);\n\n element.removeAttribute(options.attrs.src);\n element.removeAttribute(options.attrs.srcset);\n element.removeAttribute(options.attrs.poster);\n\n options.onLoaded(element);\n },\n\n error: (element, options, error) => {\n element.setAttribute(settings.stateAttr, settings.states.error);\n\n options.onError(element, error);\n },\n};\n\nexport default states;\n","/**\n * Default settings for the lazy loading functionality.\n *\n * @module settings\n *\n * @property {string} stateAttr - The attribute to store the state of the lazy loading process.\n * @property {Object} states - The possible states of the lazy loading process.\n * @property {string} states.waiting - The state when the element is waiting to be loaded.\n * @property {string} states.loading - The state when the element is currently loading.\n * @property {string} states.loaded - The state when the element has finished loading.\n * @property {string} states.error - The state when there was an error loading the element.\n * @property {Array.} supportedElements - The types of elements that are supported for lazy loading.\n */\nexport default {\n stateAttr: 'lazy-state',\n states: {\n waiting: 'waiting',\n loading: 'loading',\n loaded: 'loaded',\n error: 'error',\n },\n supportedElements: ['img', 'picture', 'video', 'embed', 'object'],\n};\n","import settings from '../utils/settings.js';\n\n/**\n * Checks if the given HTML element is of a supported type.\n *\n * @module checkSupport\n *\n * @param {HTMLElement} element - The HTML element to be checked.\n * @throws {Error} Throws an error if the element type is not supported.\n * @returns {boolean} Returns true if the element type is supported.\n */\nexport default (element) => {\n const elementType = element.tagName.toLowerCase();\n const isSupported = settings.supportedElements.includes(elementType);\n\n if (isSupported) return true;\n\n throw new Error(`Element type ${elementType} is not supported!`);\n};\n","/**\n * Creates an Intersection Observer and starts observing the given item.\n *\n * @module observer\n *\n * @param {Element} item - The DOM element to be observed.\n * @param {Function} callback - The function to be called when the item is intersecting.\n * @param {Object} settings - The options for the Intersection Observer.\n */\nexport default (item, callback, settings) => {\n const handleIntersection = (entries, observer) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n\n callback(entry.target);\n observer.unobserve(entry.target);\n });\n };\n\n const observer = new IntersectionObserver(handleIntersection, settings);\n\n observer.observe(item);\n};\n","/**\n * Select elements based on a given selector within a specified root element.\n *\n * @module getElements\n *\n * @param {string | Element | NodeList | Array} selector - The selector to match elements.\n * @returns {NodeList} - The NodeList containing the selected elements.\n */\nexport default (selector) => {\n if (selector instanceof Element) return [selector];\n if (selector instanceof NodeList) return selector;\n if (selector instanceof Array) return selector;\n\n return document.querySelectorAll(selector);\n};\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file +{"mappings":"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","sources":["src/app.js","src/utils/defaultOptions.js","src/helpers/assetLoader.js","src/helpers/states.js","src/utils/settings.js","src/helpers/checkSupport.js","src/helpers/observer.js","src/helpers/getElements.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.7\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './utils/defaultOptions.js';\nimport loadAsset from './helpers/assetLoader.js';\nimport states from './helpers/states.js';\nimport checkSupport from './helpers/checkSupport.js';\nimport observer from './helpers/observer.js';\nimport getElements from './helpers/getElements.js';\n\nexport default (selector, customOptions = {}) => {\n const options = { ...defaultOptions, ...customOptions };\n\n const observerCallback = (target) => {\n states.loading(target, options);\n loadAsset(target, options);\n };\n\n const processLazyItem = (item) => {\n try {\n states.waiting(item, options);\n\n checkSupport(item);\n observer(item, observerCallback, options.observer);\n } catch (error) {\n states.error(item, options, error.message);\n }\n };\n\n try {\n const lazyItems = getElements(selector);\n if (!lazyItems.length) throw new Error('No lazy loadable element found!');\n\n lazyItems.forEach(processLazyItem);\n } catch (error) {\n console.error('Lazy error:', error.message);\n }\n};\n","/**\n * Default options for the lazy loading functionality.\n *\n * @module defaultOptions\n *\n * @property {Object} attrs - The attributes to be used for lazy loading.\n * @property {string} attrs.src - The attribute for the source of the media.\n * @property {string} attrs.srcset - The attribute for the source set of the media.\n * @property {string} attrs.poster - The attribute for the poster of the media.\n *\n * @property {Object} observer - The options for the Intersection Observer.\n * @property {Element} observer.root - The root element for the Intersection Observer.\n * @property {number} observer.threshold - The threshold for the Intersection Observer.\n * @property {string} observer.rootMargin - The root margin for the Intersection Observer.\n *\n * @property {Function} onLoaded - The callback to be executed when the media is loaded.\n * @property {Function} onLoading - The callback to be executed when the media is loading.\n * @property {Function} onError - The callback to be executed when there is an error loading the media.\n */\nexport default {\n attrs: {\n src: 'lazy',\n srcset: 'lazy-srcset',\n poster: 'lazy-poster',\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n onLoaded: () => {},\n onLoading: () => {},\n onError: (element, error) => console.error('Error on:', element, error),\n};\n","/**\n * Set attributes on the given HTML element based on the provided options.\n *\n * @module assetLoader\n *\n * @param {HTMLElement} element - The HTML element to set attributes on.\n * @param {Object} options - Options for attribute names.\n */\nexport default (element, options) => {\n const attributes = Object.entries(options.attrs);\n\n const loadAttr = ([assetAttr, lazyAttr]) => {\n const assetPath = element.getAttribute(lazyAttr);\n if (assetPath) element.setAttribute(assetAttr, assetPath);\n };\n\n attributes.forEach(loadAttr);\n};\n","import settings from '../utils/settings.js';\n\n/**\n * Object managing different states.\n *\n * @module states\n *\n * @property {function} setWaitingState - Function handling waiting state operations.\n * @property {function} setLoadingState - Function handling loading state operations.\n * @property {function} setLoadedState - Function handling loaded state operations.\n * @property {function} setErrorState - Function handling error state operations.\n */\nconst states = {\n setWaiting: (element) => {\n element.setAttribute(settings.stateAttr, settings.states.waiting);\n },\n\n setLoading: (element, options) => {\n element.setAttribute(settings.stateAttr, settings.states.loading);\n options.onLoading(element);\n },\n\n setLoaded: (element, options) => {\n const assetAttr = Object.entries(options.attrs);\n\n console.log('📌 ~ assetAttr ->', assetAttr)\n\n\n element.setAttribute(settings.stateAttr, settings.states.loaded);\n assetAttr.forEach(([attr]) => element.removeAttribute(attr));\n options.onLoaded(element);\n },\n\n setError: (element, options, error) => {\n element.setAttribute(settings.stateAttr, settings.states.error);\n\n options.onError(element, error);\n },\n};\n\nexport default states;\n","/**\n * Default settings for the lazy loading functionality.\n *\n * @module settings\n *\n * @property {string} stateAttr - The attribute to store the state of the lazy loading process.\n * @property {Object} states - The possible states of the lazy loading process.\n * @property {string} states.waiting - The state when the element is waiting to be loaded.\n * @property {string} states.loading - The state when the element is currently loading.\n * @property {string} states.loaded - The state when the element has finished loading.\n * @property {string} states.error - The state when there was an error loading the element.\n * @property {Array.} supportedElements - The types of elements that are supported for lazy loading.\n */\nexport default {\n stateAttr: 'lazy-state',\n supportedElements: ['img', 'video', 'embed', 'object'],\n states: {\n waiting: 'waiting',\n loading: 'loading',\n loaded: 'loaded',\n error: 'error',\n },\n};\n","import settings from '../utils/settings.js';\n\n/**\n * Checks if the given HTML element is of a supported type.\n *\n * @module checkSupport\n *\n * @param {HTMLElement} element - The HTML element to be checked.\n * @throws {Error} Throws an error if the element type is not supported.\n * @returns {boolean} Returns true if the element type is supported.\n */\nexport default (element) => {\n const elementType = element.tagName.toLowerCase();\n const isSupported = settings.supportedElements.includes(elementType);\n\n if (isSupported) return true;\n\n throw new Error(`Element type ${elementType} is not supported!`);\n};\n","/**\n * Creates an Intersection Observer and starts observing the given item.\n *\n * @module observer\n *\n * @param {Element} item - The DOM element to be observed.\n * @param {Function} callback - The function to be called when the item is intersecting.\n * @param {Object} settings - The options for the Intersection Observer.\n */\nexport default (item, callback, settings) => {\n const handleIntersection = (entries, observer) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n\n callback(entry.target);\n observer.unobserve(entry.target);\n });\n };\n\n const observer = new IntersectionObserver(handleIntersection, settings);\n\n observer.observe(item);\n};\n","/**\n * Select elements based on a given selector within a specified root element.\n *\n * @module getElements\n *\n * @param {string | Element | NodeList | Array} selector - The selector to match elements.\n * @returns {NodeList} - The NodeList containing the selected elements.\n */\nexport default (selector) => {\n if (selector instanceof Element) return [selector];\n if (selector instanceof NodeList) return selector;\n if (selector instanceof Array) return selector;\n\n return document.querySelectorAll(selector);\n};\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file From 7e73387cdaf52dee0669f176e8628f4849773bf5 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 14 Apr 2024 04:35:03 +0300 Subject: [PATCH 165/185] docs: add Todo message --- src/helpers/states.js | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/helpers/states.js b/src/helpers/states.js index 6237766..b66044c 100644 --- a/src/helpers/states.js +++ b/src/helpers/states.js @@ -29,6 +29,9 @@ export default { options.onLoaded(element); }, + /* + TODO: [] Update error logging to handle top level of app. + */ setError: (element, options, error) => { console.warn('Error on:', element, error); element.setAttribute(settings.stateAttr, settings.states.error); From e93cba113f2e8ecf62db6f97b5e32724ea7a4d34 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 20 Apr 2025 01:06:32 +0300 Subject: [PATCH 166/185] Update: Licance year --- LICENSE | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/LICENSE b/LICENSE index df75975..3f00b61 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ MIT License -Copyright (c) 2022 - 2024 drementer +Copyright (c) 2022 - 2025 drementer Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal From 96c51a07a27ee9b1f3e087e37fb92bc9ac0d4567 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 20 Apr 2025 01:08:01 +0300 Subject: [PATCH 167/185] Delete: unused Test folder --- test/app.js | 4 ---- test/index.html | 28 ---------------------------- test/style.css | 24 ------------------------ 3 files changed, 56 deletions(-) delete mode 100644 test/app.js delete mode 100644 test/index.html delete mode 100644 test/style.css diff --git a/test/app.js b/test/app.js deleted file mode 100644 index a73feff..0000000 --- a/test/app.js +++ /dev/null @@ -1,4 +0,0 @@ -import lazyLoad from '/dist/lazy-load.js'; - -const initLazyLoad = () => lazyLoad('[lazy]'); -window.addEventListener('load', initLazyLoad, { once: true }); diff --git a/test/index.html b/test/index.html deleted file mode 100644 index 1b0acb7..0000000 --- a/test/index.html +++ /dev/null @@ -1,28 +0,0 @@ - - - - - - - Lazy-load.js - - - - - - - - -
- - Random Image - Random Image - Random Image - Random Image - Random Image - Random Image - Random Image - Random Image - - - \ No newline at end of file diff --git a/test/style.css b/test/style.css deleted file mode 100644 index 1be855d..0000000 --- a/test/style.css +++ /dev/null @@ -1,24 +0,0 @@ -img { - position: relative; - display: block; - - margin: 1rem auto; - width: 400px; - height: auto; - max-width: 100%; - aspect-ratio: 1 / 1; - - border-radius: 10px; -} -img::after { - z-index: -1; - content: ''; - - position: absolute; - inset: 0; - - width: 100%; - height: 100%; - - background-color: #e4e4e4; -} From 6b39ccdd0187ce4c0b78709f8e50ae2d0bfdac20 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 20 Apr 2025 01:09:40 +0300 Subject: [PATCH 168/185] Refactor observer.js to improve entry handling in IntersectionObserver --- src/helpers/observer.js | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/helpers/observer.js b/src/helpers/observer.js index a3f7531..4d607d4 100644 --- a/src/helpers/observer.js +++ b/src/helpers/observer.js @@ -9,12 +9,13 @@ */ export default (item, callback, settings) => { const handleIntersection = (entries, observer) => { - entries.forEach((entry) => { + const handleEntry = (entry) => { if (!entry.isIntersecting) return; callback(entry.target); observer.unobserve(entry.target); - }); + }; + entries.forEach(handleEntry); }; const observer = new IntersectionObserver(handleIntersection, settings); From 4cc8256c8c7aaea42bc4773ee248c2bf927561b9 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 20 Apr 2025 01:10:22 +0300 Subject: [PATCH 169/185] Refactor app.js to set default selector and streamline error handling --- src/app.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/app.js b/src/app.js index 2ef3f2e..e0fe502 100644 --- a/src/app.js +++ b/src/app.js @@ -44,11 +44,6 @@ export default (selector, customOptions = {}) => { } }; - try { const lazyItems = getElements(selector); - lazyItems.forEach(processLazyItem); - } catch (error) { - console.error('Lazy error:', error.message); - } }; From d38b63a1240fa147c70c9b2367800013d9068587 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 20 Apr 2025 01:10:49 +0300 Subject: [PATCH 170/185] Refactor app.js to set default selector and improve code formatting --- src/app.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/app.js b/src/app.js index e0fe502..7c24811 100644 --- a/src/app.js +++ b/src/app.js @@ -15,7 +15,7 @@ import checkSupport from './helpers/checkSupport.js'; import observer from './helpers/observer.js'; import getElements from './helpers/getElements.js'; -export default (selector, customOptions = {}) => { +export default (selector = '[lazy]', customOptions = {}) => { const options = { ...defaultOptions, ...customOptions }; const handleLoading = (target) => { From d80bc2838b5e5acbe1675111868ce2f77116f744 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 20 Apr 2025 13:55:27 +0300 Subject: [PATCH 171/185] Update: Error handling logic at states --- src/helpers/states.js | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/helpers/states.js b/src/helpers/states.js index b66044c..07705b8 100644 --- a/src/helpers/states.js +++ b/src/helpers/states.js @@ -29,12 +29,16 @@ export default { options.onLoaded(element); }, - /* - TODO: [] Update error logging to handle top level of app. - */ setError: (element, options, error) => { - console.warn('Error on:', element, error); + const errorDetails = { + element, + message: error, + timestamp: new Date().toISOString(), + elementType: element.tagName.toLowerCase(), + }; + + console.warn('Lazy-load error:', errorDetails); element.setAttribute(settings.stateAttr, settings.states.error); - options.onError(element, error); + options.onError(element, errorDetails); }, }; From 579a92b70ecb234b648cedd5356ecc1542f62a38 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 20 Apr 2025 14:03:46 +0300 Subject: [PATCH 172/185] Update: Migrate from Parcel to Rollup for build process and downgrage version to 0.0.8 --- .gitignore | 1 - dist/lazy-load.js | 208 +----------------------------------------- dist/lazy-load.js.map | 1 - package.json | 11 ++- rollup.config.js | 29 ++++++ src/app.js | 14 +-- 6 files changed, 41 insertions(+), 223 deletions(-) delete mode 100644 dist/lazy-load.js.map create mode 100644 rollup.config.js diff --git a/.gitignore b/.gitignore index e91ed5b..b69c673 100644 --- a/.gitignore +++ b/.gitignore @@ -4,5 +4,4 @@ # Project node_modules/ -.parcel-cache/ package-lock.json \ No newline at end of file diff --git a/dist/lazy-load.js b/dist/lazy-load.js index 924fd80..938fb95 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -2,208 +2,8 @@ * Lazy-load.js * * @author drementer - * @module lazyLoad - * @version 1.0.7 + * @version 0.0.8 * @license MIT - * @see {@link https://github.com/drementer/lazy-load.js} - */ /** - * Default options for the lazy loading functionality. - * - * @module defaultOptions - * - * @property {Object} attrs - The attributes to be used for lazy loading. - * @property {Object} observer - The options for the Intersection Observer. - * @property {Function} onLoaded - The callback to be executed when the media is loaded. - * @property {Function} onLoading - The callback to be executed when the media is loading. - * @property {Function} onError - The callback to be executed when there is an error loading the media. - */ var $e4e7a73bee6a4aee$export$2e2bcd8739ae039 = { - attrs: { - src: "lazy", - srcset: "lazy-srcset", - poster: "lazy-poster" - }, - observer: { - root: null, - threshold: 1, - rootMargin: "100% 0px" - }, - onWaiting: ()=>{}, - onLoaded: ()=>{}, - onLoading: ()=>{}, - onError: ()=>{} -}; - - -/** - * Set attributes on the given HTML element based on the provided options. - * - * @module assetLoader - * - * @param {HTMLElement} element - The HTML element to set attributes on. - * @param {Object} options - Options for attribute names. - */ var $55aebfb21ba6071b$export$2e2bcd8739ae039 = (element, options)=>{ - const attributes = Object.entries(options.attrs); - const loadAttr = ([attr, lazyAttr])=>{ - const assetPath = element.getAttribute(lazyAttr); - if (assetPath) element.setAttribute(attr, assetPath); - }; - attributes.forEach(loadAttr); -}; - - -/** - * Default settings for the lazy loading functionality. - * - * @module settings - * - * @property {string} stateAttr - The attribute to store the state of the lazy loading process. - * @property {Array} supportedElements - The types of elements that are supported for lazy loading. - * @property {Object} states - The possible states of the lazy loading process. - */ var $2e06dbd9a7176757$export$2e2bcd8739ae039 = { - stateAttr: "lazy-state", - supportedElements: [ - "img", - "video", - "embed", - "object", - "iframe", - "audio" - ], - states: { - waiting: "waiting", - loading: "loading", - loaded: "loaded", - error: "error" - } -}; - - -var /** - * Object managing different states. - * - * @module states - * - * @property {function} setWaitingState - Function handling waiting state operations. - * @property {function} setLoadingState - Function handling loading state operations. - * @property {function} setLoadedState - Function handling loaded state operations. - * @property {function} setErrorState - Function handling error state operations. - */ $be4bb12be4dd9f4e$export$2e2bcd8739ae039 = { - setWaiting: (element, options)=>{ - element.setAttribute((0, $2e06dbd9a7176757$export$2e2bcd8739ae039).stateAttr, (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).states.waiting); - options.onWaiting(element); - }, - setLoading: (element, options)=>{ - element.setAttribute((0, $2e06dbd9a7176757$export$2e2bcd8739ae039).stateAttr, (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).states.loading); - options.onLoading(element); - }, - setLoaded: (element, options)=>{ - const assetAttr = Object.entries(options.attrs); - element.setAttribute((0, $2e06dbd9a7176757$export$2e2bcd8739ae039).stateAttr, (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).states.loaded); - assetAttr.forEach(([attr, lazyAttr])=>element.removeAttribute(lazyAttr)); - options.onLoaded(element); - }, - setError: (element, options, error)=>{ - console.warn("Error on:", element, error); - element.setAttribute((0, $2e06dbd9a7176757$export$2e2bcd8739ae039).stateAttr, (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).states.error); - options.onError(element, error); - } -}; - - - -var /** - * Checks if the given HTML element is of a supported type. - * - * @module checkSupport - * - * @param {HTMLElement} element - The HTML element to be checked. - * @throws {Error} Throws an error if the element type is not supported. - * @returns {boolean} Returns true if the element type is supported. - */ $67c2ab11c12b7b4c$export$2e2bcd8739ae039 = (element)=>{ - const elementType = element.tagName.toLowerCase(); - const isSupported = (0, $2e06dbd9a7176757$export$2e2bcd8739ae039).supportedElements.includes(elementType); - if (!isSupported) throw new Error(`${elementType} Element is not supported!`); - return true; -}; - - -/** - * Creates an Intersection Observer and starts observing the given item. - * - * @module observer - * - * @param {Element} item - The DOM element to be observed. - * @param {Function} callback - The function to be called when the item is intersecting. - * @param {Object} settings - The options for the Intersection Observer. - */ var $afbda835b72f3fa2$export$2e2bcd8739ae039 = (item, callback, settings)=>{ - const handleIntersection = (entries, observer)=>{ - entries.forEach((entry)=>{ - if (!entry.isIntersecting) return; - callback(entry.target); - observer.unobserve(entry.target); - }); - }; - const observer = new IntersectionObserver(handleIntersection, settings); - observer.observe(item); -}; - - -/** - * Select elements based on a given selector within a specified root element. - * - * @module getElements - * - * @param {string | Element | NodeList | Array} selector - The selector to match elements. - * @returns {NodeList} - The NodeList containing the selected elements. - */ var $286db38838bca09d$export$2e2bcd8739ae039 = (selector)=>{ - if (selector instanceof Element) return [ - selector - ]; - if (selector instanceof NodeList) return selector; - if (selector instanceof Array) return selector; - const elements = document.querySelectorAll(selector); - if (!elements.length) throw new Error("No lazy loadable element found!"); - return elements; -}; - - -var $3e2aed16982f049f$export$2e2bcd8739ae039 = (selector, customOptions = {})=>{ - const options = { - ...(0, $e4e7a73bee6a4aee$export$2e2bcd8739ae039), - ...customOptions - }; - const handleLoading = (target)=>{ - const handleLoad = ()=>{ - (0, $be4bb12be4dd9f4e$export$2e2bcd8739ae039).setLoaded(target, options); - }; - const handleError = ()=>{ - (0, $be4bb12be4dd9f4e$export$2e2bcd8739ae039).setError(target, options, "Loading media."); - }; - (0, $be4bb12be4dd9f4e$export$2e2bcd8739ae039).setLoading(target, options); - (0, $55aebfb21ba6071b$export$2e2bcd8739ae039)(target, options); - target.addEventListener("load", handleLoad, { - once: true - }); - target.addEventListener("error", handleError, { - once: true - }); - }; - const processLazyItem = (item)=>{ - try { - (0, $67c2ab11c12b7b4c$export$2e2bcd8739ae039)(item); - (0, $be4bb12be4dd9f4e$export$2e2bcd8739ae039).setWaiting(item, options); - (0, $afbda835b72f3fa2$export$2e2bcd8739ae039)(item, handleLoading, options.observer); - } catch (error) { - (0, $be4bb12be4dd9f4e$export$2e2bcd8739ae039).setError(item, options, error.message); - } - }; - try { - const lazyItems = (0, $286db38838bca09d$export$2e2bcd8739ae039)(selector); - lazyItems.forEach(processLazyItem); - } catch (error) { - console.error("Lazy error:", error.message); - } -}; - - -export {$3e2aed16982f049f$export$2e2bcd8739ae039 as default}; + * @link https://github.com/drementer/lazy-load.js + */ +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).lazyLoad=t()}(this,(function(){"use strict";var e={attrs:{src:"lazy",srcset:"lazy-srcset",poster:"lazy-poster"},observer:{root:null,threshold:1,rootMargin:"100% 0px"},onWaiting:()=>{},onLoaded:()=>{},onLoading:()=>{},onError:()=>{}},t={stateAttr:"lazy-state",supportedElements:["img","video","embed","object","iframe","audio"],states:{waiting:"waiting",loading:"loading",loaded:"loaded",error:"error"}},r=(e,r)=>{e.setAttribute(t.stateAttr,t.states.waiting),r.onWaiting(e)},o=(e,r)=>{e.setAttribute(t.stateAttr,t.states.loading),r.onLoading(e)},n=(e,r)=>{const o=Object.entries(r.attrs);e.setAttribute(t.stateAttr,t.states.loaded),o.forEach((([t,r])=>e.removeAttribute(r))),r.onLoaded(e)},s=(e,r,o)=>{const n={element:e,message:o,timestamp:(new Date).toISOString(),elementType:e.tagName.toLowerCase()};console.warn("Lazy-load error:",n),e.setAttribute(t.stateAttr,t.states.error),r.onError(e,n)};return(a="[lazy]",i={})=>{const d={...e,...i},l=e=>{o(e,d),((e,t)=>{Object.entries(t.attrs).forEach((([t,r])=>{const o=e.getAttribute(r);o&&e.setAttribute(t,o)}))})(e,d),e.addEventListener("load",(()=>{n(e,d)}),{once:!0}),e.addEventListener("error",(()=>{s(e,d,"Loading media.")}),{once:!0})},c=(e=>{if(e instanceof Element)return[e];if(e instanceof NodeList)return e;if(e instanceof Array)return e;const t=document.querySelectorAll(e);if(!t.length)throw new Error("No lazy loadable element found!");return t})(a);c.forEach((e=>{try{(e=>{const r=e.tagName.toLowerCase();if(!t.supportedElements.includes(r))throw new Error(`${r} Element is not supported!`)})(e),r(e,d),((e,t,r)=>{new IntersectionObserver(((e,r)=>{e.forEach((e=>{e.isIntersecting&&(t(e.target),r.unobserve(e.target))}))}),r).observe(e)})(e,l,d.observer)}catch(t){s(e,d,t.message)}}))}})); diff --git a/dist/lazy-load.js.map b/dist/lazy-load.js.map deleted file mode 100644 index e40bcf3b..0000000 --- a/dist/lazy-load.js.map +++ /dev/null @@ -1 +0,0 @@ -{"mappings":"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","sources":["src/app.js","src/utils/defaultOptions.js","src/helpers/assetLoader.js","src/helpers/states.js","src/utils/settings.js","src/helpers/checkSupport.js","src/helpers/observer.js","src/helpers/getElements.js"],"sourcesContent":["/**\n * Lazy-load.js\n *\n * @author drementer\n * @module lazyLoad\n * @version 1.0.7\n * @license MIT\n * @see {@link https://github.com/drementer/lazy-load.js}\n */\n\nimport defaultOptions from './utils/defaultOptions.js';\nimport loadAsset from './helpers/assetLoader.js';\nimport states from './helpers/states.js';\nimport checkSupport from './helpers/checkSupport.js';\nimport observer from './helpers/observer.js';\nimport getElements from './helpers/getElements.js';\n\nexport default (selector, customOptions = {}) => {\n const options = { ...defaultOptions, ...customOptions };\n\n const observerCallback = (target) => {\n states.loading(target, options);\n loadAsset(target, options);\n };\n\n const processLazyItem = (item) => {\n try {\n states.waiting(item, options);\n\n checkSupport(item);\n observer(item, observerCallback, options.observer);\n } catch (error) {\n states.error(item, options, error.message);\n }\n };\n\n try {\n const lazyItems = getElements(selector);\n if (!lazyItems.length) throw new Error('No lazy loadable element found!');\n\n lazyItems.forEach(processLazyItem);\n } catch (error) {\n console.error('Lazy error:', error.message);\n }\n};\n","/**\n * Default options for the lazy loading functionality.\n *\n * @module defaultOptions\n *\n * @property {Object} attrs - The attributes to be used for lazy loading.\n * @property {string} attrs.src - The attribute for the source of the media.\n * @property {string} attrs.srcset - The attribute for the source set of the media.\n * @property {string} attrs.poster - The attribute for the poster of the media.\n *\n * @property {Object} observer - The options for the Intersection Observer.\n * @property {Element} observer.root - The root element for the Intersection Observer.\n * @property {number} observer.threshold - The threshold for the Intersection Observer.\n * @property {string} observer.rootMargin - The root margin for the Intersection Observer.\n *\n * @property {Function} onLoaded - The callback to be executed when the media is loaded.\n * @property {Function} onLoading - The callback to be executed when the media is loading.\n * @property {Function} onError - The callback to be executed when there is an error loading the media.\n */\nexport default {\n attrs: {\n src: 'lazy',\n srcset: 'lazy-srcset',\n poster: 'lazy-poster',\n },\n observer: {\n root: null,\n threshold: 1,\n rootMargin: '100% 0px',\n },\n onLoaded: () => {},\n onLoading: () => {},\n onError: (element, error) => console.error('Error on:', element, error),\n};\n","/**\n * Set attributes on the given HTML element based on the provided options.\n *\n * @module assetLoader\n *\n * @param {HTMLElement} element - The HTML element to set attributes on.\n * @param {Object} options - Options for attribute names.\n */\nexport default (element, options) => {\n const attributes = Object.entries(options.attrs);\n\n const loadAttr = ([assetAttr, lazyAttr]) => {\n const assetPath = element.getAttribute(lazyAttr);\n if (assetPath) element.setAttribute(assetAttr, assetPath);\n };\n\n attributes.forEach(loadAttr);\n};\n","import settings from '../utils/settings.js';\n\n/**\n * Object managing different states.\n *\n * @module states\n *\n * @property {function} setWaitingState - Function handling waiting state operations.\n * @property {function} setLoadingState - Function handling loading state operations.\n * @property {function} setLoadedState - Function handling loaded state operations.\n * @property {function} setErrorState - Function handling error state operations.\n */\nconst states = {\n setWaiting: (element) => {\n element.setAttribute(settings.stateAttr, settings.states.waiting);\n },\n\n setLoading: (element, options) => {\n element.setAttribute(settings.stateAttr, settings.states.loading);\n options.onLoading(element);\n },\n\n setLoaded: (element, options) => {\n const assetAttr = Object.entries(options.attrs);\n\n console.log('📌 ~ assetAttr ->', assetAttr)\n\n\n element.setAttribute(settings.stateAttr, settings.states.loaded);\n assetAttr.forEach(([attr]) => element.removeAttribute(attr));\n options.onLoaded(element);\n },\n\n setError: (element, options, error) => {\n element.setAttribute(settings.stateAttr, settings.states.error);\n\n options.onError(element, error);\n },\n};\n\nexport default states;\n","/**\n * Default settings for the lazy loading functionality.\n *\n * @module settings\n *\n * @property {string} stateAttr - The attribute to store the state of the lazy loading process.\n * @property {Object} states - The possible states of the lazy loading process.\n * @property {string} states.waiting - The state when the element is waiting to be loaded.\n * @property {string} states.loading - The state when the element is currently loading.\n * @property {string} states.loaded - The state when the element has finished loading.\n * @property {string} states.error - The state when there was an error loading the element.\n * @property {Array.} supportedElements - The types of elements that are supported for lazy loading.\n */\nexport default {\n stateAttr: 'lazy-state',\n supportedElements: ['img', 'video', 'embed', 'object'],\n states: {\n waiting: 'waiting',\n loading: 'loading',\n loaded: 'loaded',\n error: 'error',\n },\n};\n","import settings from '../utils/settings.js';\n\n/**\n * Checks if the given HTML element is of a supported type.\n *\n * @module checkSupport\n *\n * @param {HTMLElement} element - The HTML element to be checked.\n * @throws {Error} Throws an error if the element type is not supported.\n * @returns {boolean} Returns true if the element type is supported.\n */\nexport default (element) => {\n const elementType = element.tagName.toLowerCase();\n const isSupported = settings.supportedElements.includes(elementType);\n\n if (isSupported) return true;\n\n throw new Error(`Element type ${elementType} is not supported!`);\n};\n","/**\n * Creates an Intersection Observer and starts observing the given item.\n *\n * @module observer\n *\n * @param {Element} item - The DOM element to be observed.\n * @param {Function} callback - The function to be called when the item is intersecting.\n * @param {Object} settings - The options for the Intersection Observer.\n */\nexport default (item, callback, settings) => {\n const handleIntersection = (entries, observer) => {\n entries.forEach((entry) => {\n if (!entry.isIntersecting) return;\n\n callback(entry.target);\n observer.unobserve(entry.target);\n });\n };\n\n const observer = new IntersectionObserver(handleIntersection, settings);\n\n observer.observe(item);\n};\n","/**\n * Select elements based on a given selector within a specified root element.\n *\n * @module getElements\n *\n * @param {string | Element | NodeList | Array} selector - The selector to match elements.\n * @returns {NodeList} - The NodeList containing the selected elements.\n */\nexport default (selector) => {\n if (selector instanceof Element) return [selector];\n if (selector instanceof NodeList) return selector;\n if (selector instanceof Array) return selector;\n\n return document.querySelectorAll(selector);\n};\n"],"names":[],"version":3,"file":"lazy-load.js.map","sourceRoot":"../"} \ No newline at end of file diff --git a/package.json b/package.json index 3892a7d..a1c34a8 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,7 @@ { "name": "lazy-load.js", - "version": "2.0.0", + "version": "0.0.8", + "type": "module", "homepage": "https://github.com/drementer/lazy-load.js", "description": "Another, another and another Lazy Load Library", "source": "src/app.js", @@ -9,8 +10,8 @@ "dist" ], "scripts": { - "watch": "parcel watch", - "build": "parcel build --no-source-maps --no-cache", + "watch": "rollup -c -w", + "build": "rollup -c", "jasmine": "jasmine-browser-runner serve" }, "keywords": [ @@ -39,10 +40,10 @@ }, "license": "MIT", "devDependencies": { - "@parcel/resolver-glob": "^2.9.3", + "@rollup/plugin-terser": "^0.4.4", "jasmine": "^5.1.0", "jasmine-browser-runner": "^2.3.0", "jasmine-core": "^5.1.2", - "parcel": "^2.9.3" + "rollup": "^4.39.0" } } diff --git a/rollup.config.js b/rollup.config.js new file mode 100644 index 0000000..8ea46fa --- /dev/null +++ b/rollup.config.js @@ -0,0 +1,29 @@ +import terser from '@rollup/plugin-terser'; + +export default { + input: 'src/app.js', + output: { + file: 'dist/lazy-load.js', + format: 'umd', + name: 'lazyLoad', + exports: 'auto', + banner: `/** + * Lazy-load.js + * + * @author drementer + * @version 0.0.8 + * @license MIT + * @link https://github.com/drementer/lazy-load.js + */`, + }, + plugins: [ + terser({ + format: { + comments: 'some' + }, + mangle: { + reserved: ['lazyLoad'] + } + }), + ], +}; diff --git a/src/app.js b/src/app.js index 7c24811..dc87562 100644 --- a/src/app.js +++ b/src/app.js @@ -1,13 +1,3 @@ -/** - * Lazy-load.js - * - * @author drementer - * @module lazyLoad - * @version 1.0.7 - * @license MIT - * @see {@link https://github.com/drementer/lazy-load.js} - */ - import defaultOptions from './utils/defaultOptions.js'; import loadAsset from './helpers/assetLoader.js'; import states from './helpers/states.js'; @@ -44,6 +34,6 @@ export default (selector = '[lazy]', customOptions = {}) => { } }; - const lazyItems = getElements(selector); - lazyItems.forEach(processLazyItem); + const lazyItems = getElements(selector); + lazyItems.forEach(processLazyItem); }; From 0f0393432b42053f5f379775ffdb786a0a286e4e Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sun, 20 Apr 2025 15:09:35 +0300 Subject: [PATCH 173/185] Refactor: rename helpers to utils and utils to config --- src/{utils => config}/defaultOptions.js | 0 src/{utils => config}/settings.js | 0 src/{helpers => utils}/assetLoader.js | 0 src/{helpers => utils}/checkSupport.js | 0 src/{helpers => utils}/getElements.js | 0 src/{helpers => utils}/observer.js | 0 src/{helpers => utils}/states.js | 0 7 files changed, 0 insertions(+), 0 deletions(-) rename src/{utils => config}/defaultOptions.js (100%) rename src/{utils => config}/settings.js (100%) rename src/{helpers => utils}/assetLoader.js (100%) rename src/{helpers => utils}/checkSupport.js (100%) rename src/{helpers => utils}/getElements.js (100%) rename src/{helpers => utils}/observer.js (100%) rename src/{helpers => utils}/states.js (100%) diff --git a/src/utils/defaultOptions.js b/src/config/defaultOptions.js similarity index 100% rename from src/utils/defaultOptions.js rename to src/config/defaultOptions.js diff --git a/src/utils/settings.js b/src/config/settings.js similarity index 100% rename from src/utils/settings.js rename to src/config/settings.js diff --git a/src/helpers/assetLoader.js b/src/utils/assetLoader.js similarity index 100% rename from src/helpers/assetLoader.js rename to src/utils/assetLoader.js diff --git a/src/helpers/checkSupport.js b/src/utils/checkSupport.js similarity index 100% rename from src/helpers/checkSupport.js rename to src/utils/checkSupport.js diff --git a/src/helpers/getElements.js b/src/utils/getElements.js similarity index 100% rename from src/helpers/getElements.js rename to src/utils/getElements.js diff --git a/src/helpers/observer.js b/src/utils/observer.js similarity index 100% rename from src/helpers/observer.js rename to src/utils/observer.js diff --git a/src/helpers/states.js b/src/utils/states.js similarity index 100% rename from src/helpers/states.js rename to src/utils/states.js From ad6e664808b6c13aac82c61f19b9e5c49b8affaa Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 31 May 2025 22:24:45 +0300 Subject: [PATCH 174/185] Massive dangerous changes --- README.md | 132 +++++++++-- dist/lazy-load.js | 6 +- index.html | 304 +++++++++++++++++++++++++ package.json | 9 +- rollup.config.js | 6 +- spec/eventEmitter.spec.mjs | 42 ++++ spec/helpers/checkState.mjs | 3 - spec/helpers/createImage.mjs | 6 - spec/support/jasmine-browser.json | 17 -- spec/support/jasmine.json | 7 + spec/unit-test.spec.mjs | 33 --- src/app.js | 39 ---- src/config/defaultOptions.js | 15 -- src/config/settings.js | 19 -- src/core/eventEmitter.js | 60 +++++ src/core/lazyLoader.js | 62 +++++ src/index.js | 5 + src/{utils => services}/assetLoader.js | 8 - src/utils/checkSupport.js | 20 +- src/utils/getElements.js | 9 - src/utils/observer.js | 11 - src/utils/states.js | 44 ---- 22 files changed, 614 insertions(+), 243 deletions(-) create mode 100644 index.html create mode 100644 spec/eventEmitter.spec.mjs delete mode 100644 spec/helpers/checkState.mjs delete mode 100644 spec/helpers/createImage.mjs delete mode 100644 spec/support/jasmine-browser.json create mode 100644 spec/support/jasmine.json delete mode 100644 spec/unit-test.spec.mjs delete mode 100644 src/app.js delete mode 100644 src/config/settings.js create mode 100644 src/core/eventEmitter.js create mode 100644 src/core/lazyLoader.js create mode 100644 src/index.js rename src/{utils => services}/assetLoader.js (54%) delete mode 100644 src/utils/states.js diff --git a/README.md b/README.md index 9bc4a4d..38aa4d5 100644 --- a/README.md +++ b/README.md @@ -1,19 +1,119 @@ -# Lazy Load Images +# Lazy-load.js -Lazy Load Images is a JavaScript utility that allows you to lazy load visual content when it approaches the visible area of the screen. This technique helps improve page loading speed by deferring the loading of images until they are actually needed. +A lightweight lazy loading library for modern browsers. -## Usage +## Features -To use Lazy Load Images, include the `lazyLoad` function in your code. The function takes two optional parameters: +- Simple and lightweight structure +- Configurable options +- Uses IntersectionObserver API +- Support for various media types (img, video, iframe, etc.) +- Performance tracking +- Error handling and fallback images -- `selector` (string, array, default: 'lazy'): CSS selector for lazy load items. -- `customOptions` (object): Options for the `lazyLoad`. +## Installation -If no selector is provided, the default selector 'lazy' will be used. -If no observer options are provided, default options will be used. +```bash +# with npm +npm install lazy-load.js + +# or with yarn +yarn add lazy-load.js +``` + +## Basic Usage + +HTML: +```html +Lazy loaded image + + +``` + +JavaScript: +```javascript +import lazyLoad from 'lazy-load.js'; + +// Start with default settings +const loader = lazyLoad(); + +// Listen to events +loader.on('loaded', (element) => { + console.log('Element loaded:', element); +}); + +loader.on('error', (element, error) => { + console.error('Loading error:', error, element); +}); + +// or with custom options +const customLoader = lazyLoad('[lazy]', { + observer: { + rootMargin: '200px 0px', + threshold: 0.1 + }, + // Traditional callback options still work + onLoaded: (element) => { + console.log('Loaded via options:', element); + }, +}); + +// You can also add event listeners this way +customLoader.on('waiting', (element) => { + console.log('Element waiting to be visible:', element); +}); + +// One-time event listener +customLoader.once('loaded', (element) => { + console.log('This will only be called once for the first loaded element'); +}); + +// Remove specific event listener +const myHandler = (element) => console.log('Element loaded:', element); +customLoader.on('loaded', myHandler); +customLoader.off('loaded', myHandler); + +// Remove all listeners for an event +customLoader.removeAllListeners('loaded'); +``` + +## Custom Attributes + +- `lazy`: Main lazy loading attribute for src +- `lazy-srcset`: For srcset in img elements +- `lazy-poster`: For poster in video elements + +## State Information + +The library adds a `lazy-state` attribute to elements at each stage of the loading process: + +- `waiting`: Element is not yet visible +- `loading`: Element is visible and loading +- `loaded`: Element has loaded successfully +- `error`: An error occurred during loading + +You can apply CSS styles based on this attribute: + +```css +[lazy-state="loading"] { + filter: blur(5px); + transition: filter 0.3s; +} + +[lazy-state="loaded"] { + filter: blur(0); +} + +[lazy-state="error"] { + opacity: 0.5; + filter: grayscale(100%); +} +``` + +## All Settings ```javascript -lazyLoad('lazy', { +{ attrs: { src: 'lazy', srcset: 'lazy-srcset', @@ -24,12 +124,16 @@ lazyLoad('lazy', { threshold: 1, rootMargin: '100% 0px', }, - onLoaded: () => {}, - onLoading: () => {}, - onError: (element, error) => console.error('Error on:', element, error), -}); + onWaiting: (element) => {}, + onLoaded: (element) => {}, + onLoading: (element) => {}, + onError: (element, error) => {}, + errorFallback: 'fallback-image.jpg', + enablePerformanceMetrics: false, + onPerformanceMeasure: (metrics) => {} +} ``` ## License -[MIT License](https://choosealicense.com/licenses/mit/). +MIT diff --git a/dist/lazy-load.js b/dist/lazy-load.js index 938fb95..a470c03 100644 --- a/dist/lazy-load.js +++ b/dist/lazy-load.js @@ -1,9 +1,7 @@ /** - * Lazy-load.js - * - * @author drementer + * lazy-load.js * @version 0.0.8 * @license MIT * @link https://github.com/drementer/lazy-load.js */ -!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).lazyLoad=t()}(this,(function(){"use strict";var e={attrs:{src:"lazy",srcset:"lazy-srcset",poster:"lazy-poster"},observer:{root:null,threshold:1,rootMargin:"100% 0px"},onWaiting:()=>{},onLoaded:()=>{},onLoading:()=>{},onError:()=>{}},t={stateAttr:"lazy-state",supportedElements:["img","video","embed","object","iframe","audio"],states:{waiting:"waiting",loading:"loading",loaded:"loaded",error:"error"}},r=(e,r)=>{e.setAttribute(t.stateAttr,t.states.waiting),r.onWaiting(e)},o=(e,r)=>{e.setAttribute(t.stateAttr,t.states.loading),r.onLoading(e)},n=(e,r)=>{const o=Object.entries(r.attrs);e.setAttribute(t.stateAttr,t.states.loaded),o.forEach((([t,r])=>e.removeAttribute(r))),r.onLoaded(e)},s=(e,r,o)=>{const n={element:e,message:o,timestamp:(new Date).toISOString(),elementType:e.tagName.toLowerCase()};console.warn("Lazy-load error:",n),e.setAttribute(t.stateAttr,t.states.error),r.onError(e,n)};return(a="[lazy]",i={})=>{const d={...e,...i},l=e=>{o(e,d),((e,t)=>{Object.entries(t.attrs).forEach((([t,r])=>{const o=e.getAttribute(r);o&&e.setAttribute(t,o)}))})(e,d),e.addEventListener("load",(()=>{n(e,d)}),{once:!0}),e.addEventListener("error",(()=>{s(e,d,"Loading media.")}),{once:!0})},c=(e=>{if(e instanceof Element)return[e];if(e instanceof NodeList)return e;if(e instanceof Array)return e;const t=document.querySelectorAll(e);if(!t.length)throw new Error("No lazy loadable element found!");return t})(a);c.forEach((e=>{try{(e=>{const r=e.tagName.toLowerCase();if(!t.supportedElements.includes(r))throw new Error(`${r} Element is not supported!`)})(e),r(e,d),((e,t,r)=>{new IntersectionObserver(((e,r)=>{e.forEach((e=>{e.isIntersecting&&(t(e.target),r.unobserve(e.target))}))}),r).observe(e)})(e,l,d.observer)}catch(t){s(e,d,t.message)}}))}})); +!function(e,t){"object"==typeof exports&&"undefined"!=typeof module?module.exports=t():"function"==typeof define&&define.amd?define(t):(e="undefined"!=typeof globalThis?globalThis:e||self).lazyLoad=t()}(this,(function(){"use strict";var e={attrs:{src:"lazy",srcset:"lazy-srcset",poster:"lazy-poster"},observer:{root:null,threshold:1,rootMargin:"100% 0px"}};class t{#e=new Map;on(e,t){return this.#e.has(e)||this.#e.set(e,[]),this.#e.get(e).push(t),this}off(e,t){if(!this.#e.has(e))return;const s=this.#e.get(e);return this.#e.set(e,((e,t)=>e.filter((e=>e!==t)))(s,t)),this}once(e,t){const s=(...r)=>{t(...r),this.off(e,s)};return this.on(e,s)}emit(e,...t){const s=this.#e.get(e)||[];return!!s.length&&(s.forEach((e=>e(...t))),!0)}get events(){return this.#e}}const s=["img","video","embed","object","iframe","audio"];class r extends t{#t;#s;constructor(t,s){super(),this.#t=t,this.#s={...e,...s},this.init()}#r(e){Object.entries(this.#s.attrs).forEach((([t,s])=>e.removeAttribute(s)))}#n(e){try{(e=>{const t=e.tagName.toLowerCase();if(!s.includes(t))throw new Error(`${t} Element is not supported!`)})(e),this.emit("waiting",e),((e,t,s)=>{new IntersectionObserver(((e,s)=>{e.forEach((e=>{e.isIntersecting&&(t(e.target),s.unobserve(e.target))}))}),s).observe(e)})(e,this.#o,this.#s.observer)}catch(t){console.warn("Lazy-load error:",e)}}#o(e){var t,s;this.emit("loading",e),t=e,s=this.#s,Object.entries(s.attrs).forEach((([e,s])=>{const r=t.getAttribute(s);r&&t.setAttribute(e,r)})),e.addEventListener("load",(()=>{this.#r(e),this.emit("loaded",e)}),{once:!0}),e.addEventListener("error",(()=>{this.emit("error",e,"Loading media failed"),console.warn("Lazy-load error:",e)}),{once:!0})}init(){return(e=>{if(e instanceof Element)return[e];if(e instanceof NodeList)return e;if(e instanceof Array)return e;const t=document.querySelectorAll(e);if(!t.length)throw new Error("No lazy loadable element found!");return t})(this.#t).forEach((e=>this.#n(e))),this}}return(e="[lazy]",t={})=>new r(e,t)})); diff --git a/index.html b/index.html new file mode 100644 index 0000000..31248f8 --- /dev/null +++ b/index.html @@ -0,0 +1,304 @@ + + + + + + + Lazy-load.js - Simple and Lightweight Lazy Loading Library + + + + + + + + + +
+
+

Lazy-load.js

+

Lightweight, fast and customizable lazy loading library

+ View on GitHub +
+
+ +
+
+
+

Features

+

What can you do with Lazy-load.js?

+
+ +
+
+

Fast & Lightweight

+

+ Delivers maximum performance with minimal code size. Significantly reduces page loading times. +

+
+ +
+

Easy to Use

+

+ Extremely easy to implement and configure. You can lazy load all elements on your page with just one line of code. +

+
+ +
+

Multiple Media Support

+

+ Provides support for images, videos, iframes and more. Optimize all your media elements with the same library. +

+
+
+
+
+ +
+
+
+

How to Use

+

Start with just a few lines of code

+
+ +
+ + <!-- HTML -->
+ <img lazy="image.jpg" alt="Description">

+ + <!-- JS -->
+ <script src="lazy-load.js"></script>
+ <script>
+   lazyLoad();
+ </script> +
+
+ +

Live Demo

+

Scroll down to trigger lazy loading

+ + Demo Image 1 + Demo Image 1 + Demo Image 2 + Demo Image 3 + Demo Image 4 + Demo Image 5 + Demo Image 6 + Demo Image 7 +
+
+ + + + + diff --git a/package.json b/package.json index a1c34a8..a2572ce 100644 --- a/package.json +++ b/package.json @@ -4,15 +4,14 @@ "type": "module", "homepage": "https://github.com/drementer/lazy-load.js", "description": "Another, another and another Lazy Load Library", - "source": "src/app.js", "module": "dist/lazy-load.js", "files": [ "dist" ], "scripts": { - "watch": "rollup -c -w", + "dev": "rollup -c -w", "build": "rollup -c", - "jasmine": "jasmine-browser-runner serve" + "test": "jasmine" }, "keywords": [ "lazy", @@ -41,9 +40,7 @@ "license": "MIT", "devDependencies": { "@rollup/plugin-terser": "^0.4.4", - "jasmine": "^5.1.0", - "jasmine-browser-runner": "^2.3.0", - "jasmine-core": "^5.1.2", + "jasmine": "^5.7.1", "rollup": "^4.39.0" } } diff --git a/rollup.config.js b/rollup.config.js index 8ea46fa..a2f8c4b 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -1,16 +1,14 @@ import terser from '@rollup/plugin-terser'; export default { - input: 'src/app.js', + input: 'src/index.js', output: { file: 'dist/lazy-load.js', format: 'umd', name: 'lazyLoad', exports: 'auto', banner: `/** - * Lazy-load.js - * - * @author drementer + * lazy-load.js * @version 0.0.8 * @license MIT * @link https://github.com/drementer/lazy-load.js diff --git a/spec/eventEmitter.spec.mjs b/spec/eventEmitter.spec.mjs new file mode 100644 index 0000000..5f29b32 --- /dev/null +++ b/spec/eventEmitter.spec.mjs @@ -0,0 +1,42 @@ +import EventEmitter from '../src/core/eventEmitter.js'; +const { log } = console; + +describe('Event Emitter Test', () => { + let emitter; + + beforeEach(() => (emitter = new EventEmitter())); + + it('Should add events', () => { + emitter.on('Test Event', () => true); + expect(emitter.events['Test Event']).toBeDefined(); + }); + + it('Should add multiple callbacks to same event', () => { + emitter.on('Test Event', () => true); + emitter.on('Test Event', () => true); + expect(emitter.events['Test Event'].length).toBe(2); + }); + + it('Should remove specific callback from event', () => { + const callback1 = () => 'Callback 1'; + const callback2 = () => 'Callback 2'; + + emitter.on('Test Event', callback1); + emitter.on('Test Event', callback2); + emitter.off('Test Event', callback1); + + expect(emitter.events['Test Event'].length).toBe(1); + expect(emitter.events['Test Event']).toContain(callback2); + }); + + it('Should run once callback only one time', () => { + let count = 0; + emitter.once('Test Event', () => count++); + + emitter.emit('Test Event'); + emitter.emit('Test Event'); + emitter.emit('Test Event'); + + expect(count).toBe(1); + }); +}); diff --git a/spec/helpers/checkState.mjs b/spec/helpers/checkState.mjs deleted file mode 100644 index cd88311..0000000 --- a/spec/helpers/checkState.mjs +++ /dev/null @@ -1,3 +0,0 @@ -export default (image, state) => { - return image.getAttribute('lazy-state') == state; -}; diff --git a/spec/helpers/createImage.mjs b/spec/helpers/createImage.mjs deleted file mode 100644 index 8bb2d30..0000000 --- a/spec/helpers/createImage.mjs +++ /dev/null @@ -1,6 +0,0 @@ -export default (src) => { - const image = new Image(); - image.setAttribute('lazy', `${src}?random=${Math.random()}`); - - return document.body.appendChild(image); -}; diff --git a/spec/support/jasmine-browser.json b/spec/support/jasmine-browser.json deleted file mode 100644 index 3ee52de..0000000 --- a/spec/support/jasmine-browser.json +++ /dev/null @@ -1,17 +0,0 @@ -{ - "srcDir": ".", - "srcFiles": [], - "specDir": ".", - "esmFilenameExtension": ".mjs", - "enableTopLevelAwait": false, - "specFiles": ["spec/**/*[sS]pec.?(m)js"], - "helpers": ["spec/helpers/**/*.?(m)js"], - "env": { - "stopSpecOnExpectationFailure": false, - "stopOnSpecFailure": false, - "random": true - }, - "browser": { - "name": "firefox" - } -} diff --git a/spec/support/jasmine.json b/spec/support/jasmine.json new file mode 100644 index 0000000..c442a51 --- /dev/null +++ b/spec/support/jasmine.json @@ -0,0 +1,7 @@ +{ + "spec_dir": "spec", + "spec_files": ["**/*[sS]pec.mjs"], + "helpers": ["helpers/**/*.mjs"], + "stopSpecOnExpectationFailure": false, + "random": true +} diff --git a/spec/unit-test.spec.mjs b/spec/unit-test.spec.mjs deleted file mode 100644 index 398a78c..0000000 --- a/spec/unit-test.spec.mjs +++ /dev/null @@ -1,33 +0,0 @@ -import lazyLoad from '../dist/lazy-load.js'; -import createImage from './helpers/createImage.mjs'; -import checkState from './helpers/checkState.mjs'; - -const states = { - waiting: 'waiting', - loading: 'loading', - loaded: 'loaded', - error: 'error', -}; - -describe('Lazy Load Test', () => { - beforeEach(function () { - this.image = createImage('https://unsplash.it/400/400?gravity=center'); - lazyLoad(this.image); - }, 1000); - - it('Was lazy load started?', function (done) { - const isWaiting = checkState(this.image, states.waiting); - - expect(isWaiting).toBe(true); - done(); - }); - - it('Was image loaded?', function (done) { - this.image.onload = () => { - const isLoaded = checkState(this.image, states.loaded); - - expect(isLoaded).toBe(true); - done(); - }; - }); -}); diff --git a/src/app.js b/src/app.js deleted file mode 100644 index dc87562..0000000 --- a/src/app.js +++ /dev/null @@ -1,39 +0,0 @@ -import defaultOptions from './utils/defaultOptions.js'; -import loadAsset from './helpers/assetLoader.js'; -import states from './helpers/states.js'; -import checkSupport from './helpers/checkSupport.js'; -import observer from './helpers/observer.js'; -import getElements from './helpers/getElements.js'; - -export default (selector = '[lazy]', customOptions = {}) => { - const options = { ...defaultOptions, ...customOptions }; - - const handleLoading = (target) => { - const handleLoad = () => { - states.setLoaded(target, options); - }; - - const handleError = () => { - states.setError(target, options, 'Loading media.'); - }; - - states.setLoading(target, options); - loadAsset(target, options); - - target.addEventListener('load', handleLoad, { once: true }); - target.addEventListener('error', handleError, { once: true }); - }; - - const processLazyItem = (item) => { - try { - checkSupport(item); - states.setWaiting(item, options); - observer(item, handleLoading, options.observer); - } catch (error) { - states.setError(item, options, error.message); - } - }; - - const lazyItems = getElements(selector); - lazyItems.forEach(processLazyItem); -}; diff --git a/src/config/defaultOptions.js b/src/config/defaultOptions.js index 384c41c..f116a52 100644 --- a/src/config/defaultOptions.js +++ b/src/config/defaultOptions.js @@ -1,14 +1,3 @@ -/** - * Default options for the lazy loading functionality. - * - * @module defaultOptions - * - * @property {Object} attrs - The attributes to be used for lazy loading. - * @property {Object} observer - The options for the Intersection Observer. - * @property {Function} onLoaded - The callback to be executed when the media is loaded. - * @property {Function} onLoading - The callback to be executed when the media is loading. - * @property {Function} onError - The callback to be executed when there is an error loading the media. - */ export default { attrs: { src: 'lazy', @@ -20,8 +9,4 @@ export default { threshold: 1, rootMargin: '100% 0px', }, - onWaiting: () => {}, - onLoaded: () => {}, - onLoading: () => {}, - onError: () => {}, }; diff --git a/src/config/settings.js b/src/config/settings.js deleted file mode 100644 index d84eea7..0000000 --- a/src/config/settings.js +++ /dev/null @@ -1,19 +0,0 @@ -/** - * Default settings for the lazy loading functionality. - * - * @module settings - * - * @property {string} stateAttr - The attribute to store the state of the lazy loading process. - * @property {Array} supportedElements - The types of elements that are supported for lazy loading. - * @property {Object} states - The possible states of the lazy loading process. - */ -export default { - stateAttr: 'lazy-state', - supportedElements: ['img', 'video', 'embed', 'object', 'iframe', 'audio'], - states: { - waiting: 'waiting', - loading: 'loading', - loaded: 'loaded', - error: 'error', - }, -}; diff --git a/src/core/eventEmitter.js b/src/core/eventEmitter.js new file mode 100644 index 0000000..16b3050 --- /dev/null +++ b/src/core/eventEmitter.js @@ -0,0 +1,60 @@ +export default class { + #events = new Map(); + + #validateParams(eventName, callback) { + if (typeof eventName !== 'string') { + return console.warn('Event name must be a string'); + } + if (typeof callback !== 'function') { + return console.warn('Callback must be a function'); + } + } + + on(eventName, callback) { + this.#validateParams(eventName, callback); + + if (!this.#events.has(eventName)) { + this.#events.set(eventName, []); + } + this.#events.get(eventName).push(callback); + return this; + } + + off(eventName, callback) { + this.#validateParams(eventName, callback); + + if (!this.#events.has(eventName)) return this; + + const listeners = this.#events.get(eventName); + this.#events.set( + eventName, + listeners.filter((listener) => listener !== callback) + ); + return this; + } + + once(eventName, callback) { + const oneTimeListener = (...args) => { + callback(...args); + this.off(eventName, oneTimeListener); + }; + + return this.on(eventName, oneTimeListener); + } + + emit(eventName, ...args) { + if (typeof eventName !== 'string') { + return console.warn('Event name must be a string'); + } + + const handlers = this.#events.get(eventName); + if (!handlers?.length) return false; + + handlers.forEach((callback) => callback(...args)); + return true; + } + + get events() { + return Object.fromEntries(this.#events); + } +} diff --git a/src/core/lazyLoader.js b/src/core/lazyLoader.js new file mode 100644 index 0000000..dc53694 --- /dev/null +++ b/src/core/lazyLoader.js @@ -0,0 +1,62 @@ +import defaultOptions from '../config/defaultOptions.js'; +import EventEmitter from './eventEmitter.js'; +import assetLoader from '../services/assetLoader.js'; +import checkSupport from '../utils/checkSupport.js'; +import observer from '../utils/observer.js'; +import getElements from '../utils/getElements.js'; + +export default class extends EventEmitter { + #selector; + #options; + + constructor(selector, customOptions) { + super(); + this.#selector = selector; + this.#options = { ...defaultOptions, ...customOptions }; + + this.#init(); + } + + #clearAttributes(target) { + const assetAttr = Object.entries(this.#options.attrs); + assetAttr.forEach(([attr, lazyAttr]) => target.removeAttribute(lazyAttr)); + } + + #processItem(item) { + try { + checkSupport(item); + this.emit('waiting', item); + observer(item, this.#handleLoading, this.#options.observer); + } catch (error) { + console.warn('Lazy-load error:', item); + } + } + + #handleLoading(target) { + this.emit('loading', target); + assetLoader(target, this.#options); + + target.addEventListener( + 'load', + () => { + this.#clearAttributes(target); + this.emit('loaded', target); + }, + { once: true } + ); + target.addEventListener( + 'error', + () => { + this.emit('error', target, 'Loading media failed'); + console.warn('Lazy-load error:', target); + }, + { once: true } + ); + } + + #init() { + const lazyItems = getElements(this.#selector); + lazyItems.forEach((item) => this.#processItem(item)); + return this; + } +} diff --git a/src/index.js b/src/index.js new file mode 100644 index 0000000..0faaa20 --- /dev/null +++ b/src/index.js @@ -0,0 +1,5 @@ +import LazyLoader from './core/lazyLoader.js'; + +export default (selector = '[lazy]', customOptions = {}) => { + return new LazyLoader(selector, customOptions); +}; diff --git a/src/utils/assetLoader.js b/src/services/assetLoader.js similarity index 54% rename from src/utils/assetLoader.js rename to src/services/assetLoader.js index ef1b100..45cce8b 100644 --- a/src/utils/assetLoader.js +++ b/src/services/assetLoader.js @@ -1,11 +1,3 @@ -/** - * Set attributes on the given HTML element based on the provided options. - * - * @module assetLoader - * - * @param {HTMLElement} element - The HTML element to set attributes on. - * @param {Object} options - Options for attribute names. - */ export default (element, options) => { const attributes = Object.entries(options.attrs); diff --git a/src/utils/checkSupport.js b/src/utils/checkSupport.js index 0ce3b5c..1c7cd6a 100644 --- a/src/utils/checkSupport.js +++ b/src/utils/checkSupport.js @@ -1,17 +1,15 @@ -import settings from '../utils/settings.js'; +const supportedElements = [ + 'img', + 'video', + 'embed', + 'object', + 'iframe', + 'audio', +]; -/** - * Checks if the given HTML element is of a supported type. - * - * @module checkSupport - * - * @param {HTMLElement} element - The HTML element to be checked. - * @throws {Error} Throws an error if the element type is not supported. - * @returns {boolean} Returns true if the element type is supported. - */ export default (element) => { const elementType = element.tagName.toLowerCase(); - const isSupported = settings.supportedElements.includes(elementType); + const isSupported = supportedElements.includes(elementType); if (!isSupported) throw new Error(`${elementType} Element is not supported!`); return true; diff --git a/src/utils/getElements.js b/src/utils/getElements.js index 019315b..831812c 100644 --- a/src/utils/getElements.js +++ b/src/utils/getElements.js @@ -1,18 +1,9 @@ -/** - * Select elements based on a given selector within a specified root element. - * - * @module getElements - * - * @param {string | Element | NodeList | Array} selector - The selector to match elements. - * @returns {NodeList} - The NodeList containing the selected elements. - */ export default (selector) => { if (selector instanceof Element) return [selector]; if (selector instanceof NodeList) return selector; if (selector instanceof Array) return selector; const elements = document.querySelectorAll(selector); - if (!elements.length) throw new Error('No lazy loadable element found!'); return elements; }; diff --git a/src/utils/observer.js b/src/utils/observer.js index 4d607d4..5830da0 100644 --- a/src/utils/observer.js +++ b/src/utils/observer.js @@ -1,17 +1,7 @@ -/** - * Creates an Intersection Observer and starts observing the given item. - * - * @module observer - * - * @param {Element} item - The DOM element to be observed. - * @param {Function} callback - The function to be called when the item is intersecting. - * @param {Object} settings - The options for the Intersection Observer. - */ export default (item, callback, settings) => { const handleIntersection = (entries, observer) => { const handleEntry = (entry) => { if (!entry.isIntersecting) return; - callback(entry.target); observer.unobserve(entry.target); }; @@ -19,6 +9,5 @@ export default (item, callback, settings) => { }; const observer = new IntersectionObserver(handleIntersection, settings); - observer.observe(item); }; diff --git a/src/utils/states.js b/src/utils/states.js deleted file mode 100644 index 07705b8..0000000 --- a/src/utils/states.js +++ /dev/null @@ -1,44 +0,0 @@ -import settings from '../utils/settings.js'; - -/** - * Object managing different states. - * - * @module states - * - * @property {function} setWaitingState - Function handling waiting state operations. - * @property {function} setLoadingState - Function handling loading state operations. - * @property {function} setLoadedState - Function handling loaded state operations. - * @property {function} setErrorState - Function handling error state operations. - */ -export default { - setWaiting: (element, options) => { - element.setAttribute(settings.stateAttr, settings.states.waiting); - options.onWaiting(element); - }, - - setLoading: (element, options) => { - element.setAttribute(settings.stateAttr, settings.states.loading); - options.onLoading(element); - }, - - setLoaded: (element, options) => { - const assetAttr = Object.entries(options.attrs); - - element.setAttribute(settings.stateAttr, settings.states.loaded); - assetAttr.forEach(([attr, lazyAttr]) => element.removeAttribute(lazyAttr)); - options.onLoaded(element); - }, - - setError: (element, options, error) => { - const errorDetails = { - element, - message: error, - timestamp: new Date().toISOString(), - elementType: element.tagName.toLowerCase(), - }; - - console.warn('Lazy-load error:', errorDetails); - element.setAttribute(settings.stateAttr, settings.states.error); - options.onError(element, errorDetails); - }, -}; From 125c39baed8e3f248ff793fd5a76c665e85ed2aa Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 31 May 2025 22:39:16 +0300 Subject: [PATCH 175/185] Update: Bump version to 1.1.0 in package.json and rollup.config.js --- package.json | 2 +- rollup.config.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package.json b/package.json index a2572ce..32aa114 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "lazy-load.js", - "version": "0.0.8", + "version": "1.1.0", "type": "module", "homepage": "https://github.com/drementer/lazy-load.js", "description": "Another, another and another Lazy Load Library", diff --git a/rollup.config.js b/rollup.config.js index a2f8c4b..3fb9dd2 100644 --- a/rollup.config.js +++ b/rollup.config.js @@ -9,7 +9,7 @@ export default { exports: 'auto', banner: `/** * lazy-load.js - * @version 0.0.8 + * @version 1.1.0 * @license MIT * @link https://github.com/drementer/lazy-load.js */`, From 20754533dd5899b3ecd8300a3b8da836d4f86536 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 31 May 2025 22:39:48 +0300 Subject: [PATCH 176/185] Delete: nomode used feature to readme --- README.md | 37 +++++++++++++++++++------------------ 1 file changed, 19 insertions(+), 18 deletions(-) diff --git a/README.md b/README.md index 38aa4d5..86e97bf 100644 --- a/README.md +++ b/README.md @@ -8,8 +8,7 @@ A lightweight lazy loading library for modern browsers. - Configurable options - Uses IntersectionObserver API - Support for various media types (img, video, iframe, etc.) -- Performance tracking -- Error handling and fallback images +- Event system for better control ## Installation @@ -51,11 +50,7 @@ const customLoader = lazyLoad('[lazy]', { observer: { rootMargin: '200px 0px', threshold: 0.1 - }, - // Traditional callback options still work - onLoaded: (element) => { - console.log('Loaded via options:', element); - }, + } }); // You can also add event listeners this way @@ -72,9 +67,6 @@ customLoader.once('loaded', (element) => { const myHandler = (element) => console.log('Element loaded:', element); customLoader.on('loaded', myHandler); customLoader.off('loaded', myHandler); - -// Remove all listeners for an event -customLoader.removeAllListeners('loaded'); ``` ## Custom Attributes @@ -123,17 +115,26 @@ You can apply CSS styles based on this attribute: root: null, threshold: 1, rootMargin: '100% 0px', - }, - onWaiting: (element) => {}, - onLoaded: (element) => {}, - onLoading: (element) => {}, - onError: (element, error) => {}, - errorFallback: 'fallback-image.jpg', - enablePerformanceMetrics: false, - onPerformanceMeasure: (metrics) => {} + } } ``` +## Events + +The library provides an event system for better control over the loading process: + +- `waiting`: Fired when element is not yet visible +- `loading`: Fired when element starts loading +- `loaded`: Fired when element is loaded successfully +- `error`: Fired when loading fails + +## Browser Support + +- Chrome 51+ +- Firefox 55+ +- Safari 12.1+ +- Edge 79+ + ## License MIT From 00b4d8d6c7ea68e6dd6f1cc5a5dcf12f3e3caf13 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 31 May 2025 22:40:17 +0300 Subject: [PATCH 177/185] Docs: CHANGELOG.md --- CHANGELOG.md | 66 ++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 66 insertions(+) create mode 100644 CHANGELOG.md diff --git a/CHANGELOG.md b/CHANGELOG.md new file mode 100644 index 0000000..4c54f93 --- /dev/null +++ b/CHANGELOG.md @@ -0,0 +1,66 @@ +# Changelog + +## [1.1.0] - 2024-03-19 + +### Added +- Event system implementation + - `on` method for adding event listeners + - `off` method for removing event listeners + - `once` method for one-time event listeners + - `emit` method for triggering events +- IntersectionObserver API integration +- Support for multiple media types + - Images + - Videos + - Iframes + - Audio + - Embed + - Object +- State information for loading process + - `waiting`: Element not yet visible + - `loading`: Element is visible and loading + - `loaded`: Element loaded successfully + - `error`: Loading error occurred + +### Changed +- Switched from Parcel to Rollup build system +- Added ES Modules support +- Improved code organization + - Separated utils and config + - Better file structure +- Updated build configuration + - UMD format support + - Terser plugin for minification +- Enhanced documentation + - Complete README rewrite + - Added usage examples + - Added API documentation + - Added CSS examples +- Updated package.json + - Added dev dependencies + - Updated scripts + - Added module type + - Updated keywords + - Updated description + +### Removed +- Old demo HTML file +- Old lazy.js implementation +- Old build system +- Unnecessary dependencies + +### Fixed +- Event listener management +- Performance optimizations +- Error handling improvements + +### Security +- Updated license year to 2025 + +## [1.0.5] - 2023-03-19 + +### Initial Release +- Basic lazy loading functionality +- Simple implementation +- Limited media support +- Basic documentation \ No newline at end of file From 745f812648cff161e2afbbe784be5356b0f8b58c Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 31 May 2025 23:04:16 +0300 Subject: [PATCH 178/185] Refactor: Enhance assetLoader.js with structured media loading and error handling --- src/services/assetLoader.js | 51 +++++++++++++++++++++++++++++++++---- 1 file changed, 46 insertions(+), 5 deletions(-) diff --git a/src/services/assetLoader.js b/src/services/assetLoader.js index 45cce8b..6daa2fb 100644 --- a/src/services/assetLoader.js +++ b/src/services/assetLoader.js @@ -1,10 +1,51 @@ export default (element, options) => { - const attributes = Object.entries(options.attrs); + const { attrs } = options; + const elementType = element.tagName.toLowerCase(); - const loadAttr = ([attr, lazyAttr]) => { - const assetPath = element.getAttribute(lazyAttr); - if (assetPath) element.setAttribute(attr, assetPath); + const loaders = { + img: loadImage, + video: loadVideo, + iframe: loadIframe, + default: loadDefault, }; - attributes.forEach(loadAttr); + const loadAttribute = (element, attr, lazyAttr) => { + const value = element.getAttribute(lazyAttr); + + if (!value) return; + element.setAttribute(attr, value); + element.removeAttribute(lazyAttr); + }; + + const loadImage = () => { + loadAttribute(element, 'src', attrs.src); + loadAttribute(element, 'srcset', attrs.srcset); + }; + + const loadVideo = () => { + loadAttribute(element, 'src', attrs.src); + loadAttribute(element, 'poster', attrs.poster); + }; + + const loadIframe = () => { + loadAttribute(element, 'src', attrs.src); + }; + + const loadDefault = () => { + Object.entries(attrs).forEach(([attr, lazyAttr]) => { + loadAttribute(element, attr, lazyAttr); + }); + }; + + const loadMedia = () => { + const loader = loaders[elementType] || loaders.default; + return loader(); + }; + + try { + loadMedia(); + } catch (error) { + console.warn('Failed to load media:', error); + throw error; + } }; From 52a67dee3d86a2ff938b02f33e6d5f76c33d575b Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Sat, 31 May 2025 23:15:52 +0300 Subject: [PATCH 179/185] Remove unused #clearAttributes method from lazyLoader.js --- src/core/lazyLoader.js | 6 ------ 1 file changed, 6 deletions(-) diff --git a/src/core/lazyLoader.js b/src/core/lazyLoader.js index dc53694..423c328 100644 --- a/src/core/lazyLoader.js +++ b/src/core/lazyLoader.js @@ -17,11 +17,6 @@ export default class extends EventEmitter { this.#init(); } - #clearAttributes(target) { - const assetAttr = Object.entries(this.#options.attrs); - assetAttr.forEach(([attr, lazyAttr]) => target.removeAttribute(lazyAttr)); - } - #processItem(item) { try { checkSupport(item); @@ -39,7 +34,6 @@ export default class extends EventEmitter { target.addEventListener( 'load', () => { - this.#clearAttributes(target); this.emit('loaded', target); }, { once: true } From 5f25ba78c4b4bbcf6c5e4cb858a96287987c6c00 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Thu, 5 Jun 2025 19:08:04 +0300 Subject: [PATCH 180/185] Refactor: Move loaders definition to a more appropriate location in assetLoader.js --- src/services/assetLoader.js | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/services/assetLoader.js b/src/services/assetLoader.js index 6daa2fb..46ea8e0 100644 --- a/src/services/assetLoader.js +++ b/src/services/assetLoader.js @@ -2,13 +2,6 @@ export default (element, options) => { const { attrs } = options; const elementType = element.tagName.toLowerCase(); - const loaders = { - img: loadImage, - video: loadVideo, - iframe: loadIframe, - default: loadDefault, - }; - const loadAttribute = (element, attr, lazyAttr) => { const value = element.getAttribute(lazyAttr); @@ -37,6 +30,13 @@ export default (element, options) => { }); }; + const loaders = { + img: loadImage, + video: loadVideo, + iframe: loadIframe, + default: loadDefault, + }; + const loadMedia = () => { const loader = loaders[elementType] || loaders.default; return loader(); From 6db086080818dd4de44248cfc35959dfff147d0b Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Fri, 6 Jun 2025 12:37:09 +0300 Subject: [PATCH 181/185] Refactor: Update test suite description for Event Emitter --- spec/eventEmitter.spec.mjs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/eventEmitter.spec.mjs b/spec/eventEmitter.spec.mjs index 5f29b32..048fb3c 100644 --- a/spec/eventEmitter.spec.mjs +++ b/spec/eventEmitter.spec.mjs @@ -1,7 +1,7 @@ import EventEmitter from '../src/core/eventEmitter.js'; const { log } = console; -describe('Event Emitter Test', () => { +describe('Event Emitter', () => { let emitter; beforeEach(() => (emitter = new EventEmitter())); From 301516c15f0b40e4e137ca01407f1e1db0dfc205 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Fri, 6 Jun 2025 12:37:17 +0300 Subject: [PATCH 182/185] Test: Add comprehensive tests for assetLoader functionality --- spec/assetLoader.spec.mjs | 212 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 212 insertions(+) create mode 100644 spec/assetLoader.spec.mjs diff --git a/spec/assetLoader.spec.mjs b/spec/assetLoader.spec.mjs new file mode 100644 index 0000000..b5bca33 --- /dev/null +++ b/spec/assetLoader.spec.mjs @@ -0,0 +1,212 @@ +import assetLoader from '../src/services/assetLoader.js'; + +const createElement = (tagName) => { + return { + tagName: tagName.toUpperCase(), + attributes: new Map(), + getAttribute(name) { + /** + * Simulates real DOM getAttribute behavior: + * - Returns the attribute value if it exists (including empty strings) + * - Returns null if the attribute doesn't exist + */ + return this.attributes.has(name) ? this.attributes.get(name) : null; + }, + setAttribute(name, value) { + this.attributes.set(name, value); + }, + removeAttribute(name) { + this.attributes.delete(name); + }, + }; +}; + +const options = { + attrs: { + src: 'data-src', + srcset: 'data-srcset', + poster: 'data-poster', + }, +}; + +describe('loadAttribute functionality', () => { + let element; + beforeEach(() => (element = createElement('img'))); + + it('should load and remove lazy attribute when value exists', () => { + element.setAttribute('data-src', 'test-image.jpg'); + + assetLoader(element, options); + expect(element.getAttribute('src')).toBe('test-image.jpg'); + expect(element.getAttribute('data-src')).toBeNull(); + }); + + it('should not modify element when lazy attribute is empty', () => { + element.setAttribute('data-src', ''); + + assetLoader(element, options); + expect(element.getAttribute('src')).toBeNull(); + expect(element.getAttribute('data-src')).toBe(''); + }); + + it('should not modify element when lazy attribute does not exist', () => { + assetLoader(element, options); + expect(element.getAttribute('src')).toBeNull(); + expect(element.getAttribute('data-src')).toBeNull(); + }); +}); + +describe('Image loading', () => { + let element; + beforeEach(() => (element = createElement('img'))); + + it('should load src and srcset for image elements', () => { + element.setAttribute('data-src', 'image.jpg'); + element.setAttribute('data-srcset', 'image-2x.jpg 2x'); + + assetLoader(element, options); + + expect(element.getAttribute('src')).toBe('image.jpg'); + expect(element.getAttribute('srcset')).toBe('image-2x.jpg 2x'); + expect(element.getAttribute('data-src')).toBeNull(); + expect(element.getAttribute('data-srcset')).toBeNull(); + }); + + it('should handle image with only src attribute', () => { + element.setAttribute('data-src', 'single-image.jpg'); + + assetLoader(element, options); + + expect(element.getAttribute('src')).toBe('single-image.jpg'); + expect(element.getAttribute('srcset')).toBeNull(); + }); + + it('should handle image with only srcset attribute', () => { + element.setAttribute( + 'data-srcset', + 'responsive.jpg 1x, responsive-2x.jpg 2x' + ); + + assetLoader(element, options); + + expect(element.getAttribute('srcset')).toBe( + 'responsive.jpg 1x, responsive-2x.jpg 2x' + ); + expect(element.getAttribute('src')).toBeNull(); + }); +}); + +describe('Video loading', () => { + let element; + beforeEach(() => (element = createElement('video'))); + + it('should load src and poster for video elements', () => { + element.setAttribute('data-src', 'video.mp4'); + element.setAttribute('data-poster', 'poster.jpg'); + + assetLoader(element, options); + + expect(element.getAttribute('src')).toBe('video.mp4'); + expect(element.getAttribute('poster')).toBe('poster.jpg'); + expect(element.getAttribute('data-src')).toBeNull(); + expect(element.getAttribute('data-poster')).toBeNull(); + }); + + it('should handle video with only src attribute', () => { + element.setAttribute('data-src', 'video-only.mp4'); + + assetLoader(element, options); + + expect(element.getAttribute('src')).toBe('video-only.mp4'); + expect(element.getAttribute('poster')).toBeNull(); + }); +}); + +describe('Iframe loading', () => { + let element; + beforeEach(() => (element = createElement('iframe'))); + + it('should load src for iframe elements', () => { + element.setAttribute('data-src', 'https://example.com'); + + assetLoader(element, options); + + expect(element.getAttribute('src')).toBe('https://example.com'); + expect(element.getAttribute('data-src')).toBeNull(); + }); + + it('should handle iframe without src attribute', () => { + assetLoader(element, options); + expect(element.getAttribute('src')).toBeNull(); + }); +}); + +describe('Default loading', () => { + it('should handle unknown elements with default loader', () => { + const element = createElement('div'); + element.setAttribute('data-src', 'background.jpg'); + + assetLoader(element, options); + + expect(element.getAttribute('src')).toBe('background.jpg'); + expect(element.getAttribute('data-src')).toBeNull(); + }); + + it('should process all attributes for default elements', () => { + const element = createElement('section'); + element.setAttribute('data-src', 'bg.jpg'); + element.setAttribute('data-srcset', 'bg-2x.jpg 2x'); + element.setAttribute('data-poster', 'thumb.jpg'); + + assetLoader(element, options); + + expect(element.getAttribute('src')).toBe('bg.jpg'); + expect(element.getAttribute('srcset')).toBe('bg-2x.jpg 2x'); + expect(element.getAttribute('poster')).toBe('thumb.jpg'); + expect(element.getAttribute('data-src')).toBeNull(); + expect(element.getAttribute('data-srcset')).toBeNull(); + expect(element.getAttribute('data-poster')).toBeNull(); + }); +}); + +describe('Error handling', () => { + it('should log warning and re-throw error when loading fails', () => { + const element = createElement('img'); + spyOn(console, 'warn'); + + const originalGetAttribute = element.getAttribute; + element.getAttribute = jasmine + .createSpy('getAttribute') + .and.throwError('Test error'); + + expect(() => { + assetLoader(element, options); + }).toThrowError('Test error'); + + expect(console.warn).toHaveBeenCalledWith( + 'Failed to load media:', + jasmine.any(Error) + ); + + element.getAttribute = originalGetAttribute; + }); +}); + +describe('Edge cases', () => { + it('should handle elements with uppercase tagName', () => { + const element = createElement('img'); + element.setAttribute('data-src', 'uppercase.jpg'); + + assetLoader(element, options); + expect(element.getAttribute('src')).toBe('uppercase.jpg'); + }); + + it('should handle empty options', () => { + const emptyOptions = { attrs: {} }; + const element = createElement('img'); + + expect(() => { + assetLoader(element, emptyOptions); + }).not.toThrow(); + }); +}); From 3098ad776da71000c46c89c78002b1ffb0fcbcb0 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Fri, 6 Jun 2025 17:02:38 +0300 Subject: [PATCH 183/185] Fix: elementType case sensitive in error messages --- src/utils/checkSupport.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/utils/checkSupport.js b/src/utils/checkSupport.js index 1c7cd6a..81288cc 100644 --- a/src/utils/checkSupport.js +++ b/src/utils/checkSupport.js @@ -8,8 +8,8 @@ const supportedElements = [ ]; export default (element) => { - const elementType = element.tagName.toLowerCase(); - const isSupported = supportedElements.includes(elementType); + const elementType = element.tagName; + const isSupported = supportedElements.includes(elementType.toLowerCase()); if (!isSupported) throw new Error(`${elementType} Element is not supported!`); return true; From 59ff5bcc864cd9da6d07c61c3c60d3bcb4496b2f Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Fri, 6 Jun 2025 17:03:25 +0300 Subject: [PATCH 184/185] Test: Add comprehensive tests for checkSupport utility --- spec/checkSupport.spec.mjs | 196 +++++++++++++++++++++++++++++++++++++ 1 file changed, 196 insertions(+) create mode 100644 spec/checkSupport.spec.mjs diff --git a/spec/checkSupport.spec.mjs b/spec/checkSupport.spec.mjs new file mode 100644 index 0000000..4150335 --- /dev/null +++ b/spec/checkSupport.spec.mjs @@ -0,0 +1,196 @@ +import checkSupport from '../src/utils/checkSupport.js'; + +const createElement = (tagName) => ({ tagName }); + +describe('Supported Elements', () => { + const supportedElements = [ + 'img', + 'video', + 'embed', + 'object', + 'iframe', + 'audio', + ]; + + const testSupportedElement = (elementType) => { + it(`should support ${elementType} elements`, () => { + const element = createElement(elementType); + expect(() => checkSupport(element)).not.toThrow(); + expect(checkSupport(element)).toBe(true); + }); + }; + + supportedElements.forEach(testSupportedElement); +}); + +describe('Unsupported Elements', () => { + const unsupportedElements = [ + 'div', + 'span', + 'p', + 'h1', + 'h2', + 'h3', + 'section', + 'article', + 'header', + 'footer', + 'nav', + 'main', + 'aside', + ]; + + const testUnsupportedElement = (elementType) => { + it(`should not support ${elementType} elements`, () => { + const element = createElement(elementType); + + expect(() => checkSupport(element)).toThrowError( + `${element.tagName} Element is not supported!` + ); + }); + }; + + unsupportedElements.forEach(testUnsupportedElement); +}); + +describe('Case Sensitivity', () => { + it('should be case insensitive for supported elements', () => { + const testCases = [ + createElement('img'), + createElement('IMG'), + createElement('Img'), + createElement('iMg'), + ]; + + testCases.forEach((element) => { + expect(() => checkSupport(element)).not.toThrow(); + expect(checkSupport(element)).toBe(true); + }); + }); + + it('should be case insensitive for unsupported elements', () => { + const testCases = [ + createElement('div'), + createElement('DIV'), + createElement('Div'), + createElement('dIv'), + ]; + + testCases.forEach(({ tagName }) => { + const element = { tagName }; + expect(() => checkSupport(element)).toThrowError( + `${tagName} Element is not supported!` + ); + }); + }); +}); + +describe('Error Scenarios', () => { + it('should throw error when element is null', () => { + expect(() => checkSupport(null)).toThrow(); + }); + + it('should throw error when element is undefined', () => { + expect(() => checkSupport(undefined)).toThrow(); + }); + + it('should throw error when element has no tagName property', () => { + const element = {}; + + expect(() => checkSupport(element)).toThrow(); + }); + + it('should throw error when tagName is null', () => { + const element = { tagName: null }; + + expect(() => checkSupport(element)).toThrow(); + }); + + it('should throw error when tagName is undefined', () => { + const element = { tagName: undefined }; + + expect(() => checkSupport(element)).toThrow(); + }); + + it('should throw error when tagName is not a string', () => { + const element = { tagName: 123 }; + + expect(() => checkSupport(element)).toThrow(); + }); +}); + +describe('Return Values', () => { + it('should not return anything for unsupported elements (throws before return)', () => { + const element = createElement('div'); + + expect(() => { + const result = checkSupport(element); + expect(result).toBeUndefined(); + }).toThrow(); + }); +}); + +describe('Edge Cases', () => { + it('should handle elements with extra whitespace in tagName', () => { + const element = createElement(' IMG '); + + // Current implementation doesn't trim, so this should fail + expect(() => checkSupport(element)).toThrowError( + `${element.tagName} Element is not supported!` + ); + }); + + it('should handle empty tagName', () => { + const element = createElement(''); + + expect(() => checkSupport(element)).toThrowError( + `${element.tagName} Element is not supported!` + ); + }); + + it('should handle custom elements', () => { + const element = createElement('CUSTOM-ELEMENT'); + + expect(() => checkSupport(element)).toThrowError( + `${element.tagName} Element is not supported!` + ); + }); + + it('should handle web components', () => { + const element = createElement('MY-VIDEO-PLAYER'); + + expect(() => checkSupport(element)).toThrowError( + `${element.tagName} Element is not supported!` + ); + }); +}); + +describe('Performance', () => { + it('should handle multiple calls efficiently', () => { + const element = createElement('img'); + + const startTime = performance.now(); + + for (let i = 0; i < 1000; i++) { + checkSupport(element); + } + + const endTime = performance.now(); + const duration = endTime - startTime; + + expect(duration).toBeLessThan(100); + }); + + it('should handle different elements in sequence', () => { + const elements = [ + createElement('img'), + createElement('video'), + createElement('iframe'), + createElement('audio'), + ]; + + expect(() => { + elements.forEach((element) => checkSupport(element)); + }).not.toThrow(); + }); +}); From fb2794451f3b3b9e785ba969f8ac60375f43a678 Mon Sep 17 00:00:00 2001 From: drementer <48869708+drementer@users.noreply.github.com> Date: Fri, 6 Jun 2025 17:58:17 +0300 Subject: [PATCH 185/185] Fix: Bind 'this' context in lazyLoader observer method --- src/core/lazyLoader.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/core/lazyLoader.js b/src/core/lazyLoader.js index 423c328..49c5708 100644 --- a/src/core/lazyLoader.js +++ b/src/core/lazyLoader.js @@ -21,7 +21,7 @@ export default class extends EventEmitter { try { checkSupport(item); this.emit('waiting', item); - observer(item, this.#handleLoading, this.#options.observer); + observer(item, this.#handleLoading.bind(this), this.#options.observer); } catch (error) { console.warn('Lazy-load error:', item); }