PluginProbe
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization / 4.2.5
Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization v4.2.5
4.2.13 4.2.12 4.2.11 4.2.10 4.2.9 4.2.8 4.2.7 4.2.6 4.2.5 2.5.5 2.5.6 2.5.7 3.0.0 3.0.1 3.1.0 3.1.1 3.1.2 3.1.3 3.10.0 3.11.0 3.11.1 3.11.2 3.11.3 3.12.0 3.12.1 All 134 releases
optimole-wp / assets / js / modules / background.js

background.js in Optimole – Optimize Images | Convert WebP & AVIF | CDN & Lazy Load | Image Optimization 4.2.5, at assets/js/modules/background.js

170 lines 6.1 KB
No matching file
Up and down to move Enter to open Esc to close
Raw Download Zip
1 /**
2 * Optimole Background Image Handler Module
3 * Handles background image detection and lazy loading observation
4 */
5
6 import { optmlLogger } from './logger.js';
7 import { optmlDomUtils } from './dom-utils.js';
8
9 /**
10 * Background image handling utilities
11 */
12 export const optmlBackground = {
13 /**
14 * Setup background image observation for lazy loading
15 * @param {Array} elements - DOM elements to observe
16 * @param {string} selector - CSS selector for the elements
17 * @param {Map} selectorMap - Map to track above-fold selectors
18 * @param {IntersectionObserver} observer - Intersection observer instance
19 * @returns {number} Number of elements waiting for lazy load
20 */
21 setupBackgroundImageObservation: function(elements, selector, selectorMap, observer) {
22 // Create a single shared observer for all elements
23 const classObserver = new MutationObserver((mutations) => {
24 for (const mutation of mutations) {
25 if (mutation.type === 'attributes' && mutation.attributeName === 'class') {
26 const element = mutation.target;
27
28 // Check if element now has the required class and a background image
29 if (element.classList.contains('optml-bg-lazyloaded') &&
30 optmlDomUtils.hasBackgroundImage(element)) {
31 // Start observing for visibility
32 observer.observe(element);
33
34 // Stop watching for class changes on this element
35 classObserver.disconnect(element);
36
37 const specificSelector = element.getAttribute('data-optml-specific-selector');
38 optmlLogger.info(`Background element "${specificSelector}" is now observable`);
39 }
40 }
41 }
42 });
43
44 // Process all elements at once
45 const elementsToWatch = [];
46
47 elements.forEach(element => {
48 // Generate a specific selector for this element
49 const specificSelector = optmlDomUtils.getUniqueSelector(element);
50
51 // Mark the element with its selectors for identification in the observer
52 element.setAttribute('data-optml-bg-selector', selector);
53 element.setAttribute('data-optml-specific-selector', specificSelector);
54
55 // If already lazyloaded with background image, observe immediately
56 if (element.classList.contains('optml-bg-lazyloaded') &&
57 optmlDomUtils.hasBackgroundImage(element)) {
58 observer.observe(element);
59 } else {
60 // Otherwise, add to the list to watch for class changes
61 elementsToWatch.push(element);
62 }
63 });
64
65 // Set up observation for class changes only on elements that need it
66 if (elementsToWatch.length > 0) {
67 elementsToWatch.forEach(element => {
68 classObserver.observe(element, { attributes: true, attributeFilter: ['class'] });
69 });
70
71 // Set a timeout to disconnect the observer after a reasonable time
72 setTimeout(() => {
73 classObserver.disconnect();
74 optmlLogger.info(`Stopped waiting for lazyload on ${selector} elements`);
75 }, 5000);
76 }
77
78 return elementsToWatch.length;
79 },
80
81 /**
82 * Extract background image URLs for elements with specific selectors
83 * @param {Array} bgSelectors - Array of CSS selectors
84 * @returns {Map} Map of selector -> Map of (specific selector -> URLs)
85 */
86 extractBackgroundImageUrls: function(bgSelectors) {
87 const bgImageUrls = new Map();
88
89 if (!bgSelectors || !Array.isArray(bgSelectors)) {
90 return bgImageUrls;
91 }
92
93 bgSelectors.forEach(selector => {
94 const selectorUrlMap = new Map();
95 bgImageUrls.set(selector, selectorUrlMap);
96
97 try {
98 document.querySelectorAll(selector).forEach(element => {
99 if (element.classList.contains('optml-bg-lazyloaded')) {
100 const bgImage = optmlDomUtils.hasBackgroundImage(element, true);
101
102 if (bgImage === false) return;
103
104 // Get the specific selector for this element
105 const specificSelector = optmlDomUtils.getUniqueSelector(element);
106
107 if (!specificSelector) return;
108
109 // Extract all URLs from the background-image property
110 const urls = optmlDomUtils.extractUrlsFromBgImage(bgImage);
111
112 if (urls && urls.length > 0) {
113 selectorUrlMap.set(specificSelector, urls);
114 optmlLogger.info(`Found background image URL(s) for "${specificSelector}":`, urls);
115 }
116 }
117 });
118 } catch (e) {
119 optmlLogger.error('Error extracting background URLs for selector:', selector, e);
120 }
121 });
122
123 return bgImageUrls;
124 },
125
126 /**
127 * Process background selectors and setup observation
128 * @param {Array} bgSelectors - Array of CSS selectors
129 * @param {IntersectionObserver} observer - Intersection observer instance
130 * @returns {Object} Object containing selectorMap and pendingElements count
131 */
132 processBackgroundSelectors: function(bgSelectors, observer) {
133 const selectorMap = new Map();
134 let pendingElements = 0;
135
136 if (!bgSelectors || !Array.isArray(bgSelectors) || bgSelectors.length === 0) {
137 return { selectorMap, pendingElements };
138 }
139
140 optmlLogger.info('Processing background selectors:', bgSelectors);
141
142 bgSelectors.forEach(selector => {
143 try {
144 const elements = document.querySelectorAll(selector);
145 if (elements.length === 0) {
146 optmlLogger.warn('No elements found for background selector:', selector);
147 return;
148 }
149
150 // Initialize this selector with an empty array for above-fold elements
151 selectorMap.set(selector, []);
152
153 // Setup observation for these elements
154 pendingElements += this.setupBackgroundImageObservation(
155 Array.from(elements),
156 selector,
157 selectorMap,
158 observer
159 );
160
161 optmlLogger.info(`Processed ${elements.length} elements for background selector: ${selector}`);
162 } catch (e) {
163 optmlLogger.error('Error processing background selector:', selector, e);
164 }
165 });
166
167 return { selectorMap, pendingElements };
168 }
169 };
170