1/** 2 * EmbedPress Lazy Load 3 * 4 * Custom lazy loading implementation for iframe embeds using Intersection Observer API 5 * Only loads iframes when they're about to enter the viewport 6 * 7 * @package EmbedPress 8 * @since 4.0.0 9 */ 10 11(function() { 12 'use strict'; 13 14 // Check if Intersection Observer is supported 15 if (!('IntersectionObserver' in window)) { 16 console.warn('EmbedPress Lazy Load: IntersectionObserver not supported, loading all iframes immediately'); 17 loadAllIframes(); 18 return; 19 } 20 21 /** 22 * Get dynamic root margin based on viewport height 23 * This prevents lazy loading from triggering immediately on short pages 24 * Uses 50% of viewport height or 200px, whichever is smaller 25 */ 26 function getObserverConfig() { 27 const viewportHeight = window.innerHeight; 28 const margin = Math.min(200, Math.max(50, viewportHeight * 0.25)); 29 30 return { 31 rootMargin: margin + 'px 0px', 32 threshold: 0.01 33 }; 34 } 35 36 const observerConfig = getObserverConfig(); 37 38 /** 39 * Callback function when iframe placeholder enters viewport 40 */ 41 function onIntersection(entries, observer) { 42 entries.forEach(function(entry) { 43 if (entry.isIntersecting) { 44 const placeholder = entry.target; 45 loadIframe(placeholder); 46 observer.unobserve(placeholder); 47 } 48 }); 49 } 50 51 /** 52 * Load the actual iframe from placeholder 53 */ 54 function loadIframe(placeholder) { 55 const iframeSrc = placeholder.getAttribute('data-ep-lazy-src'); 56 57 if (!iframeSrc) { 58 console.warn('EmbedPress Lazy Load: No data-ep-lazy-src found on placeholder'); 59 return; 60 } 61 62 // Create iframe element 63 const iframe = document.createElement('iframe'); 64 iframe.src = iframeSrc; 65 66 // Copy style 67 const iframeStyle = placeholder.getAttribute('data-ep-iframe-style'); 68 if (iframeStyle) { 69 iframe.setAttribute('style', iframeStyle); 70 } 71 72 // Copy all data-ep-iframe-* attributes 73 Array.from(placeholder.attributes).forEach(function(attr) { 74 if (attr.name.startsWith('data-ep-iframe-')) { 75 const iframeAttr = attr.name.replace('data-ep-iframe-', ''); 76 if (iframeAttr !== 'style') { 77 iframe.setAttribute(iframeAttr, attr.value); 78 } 79 } 80 }); 81 82 // Copy class (remove placeholder class) 83 if (placeholder.hasAttribute('class')) { 84 const classes = placeholder.getAttribute('class').replace(/ep-lazy-iframe-placeholder/g, '').trim(); 85 if (classes) { 86 iframe.setAttribute('class', classes); 87 } 88 } 89 90 // Copy other important attributes 91 ['data-emid', 'data-embedpress-content', 'data-embed-type', 'title'].forEach(function(attr) { 92 if (placeholder.hasAttribute(attr)) { 93 iframe.setAttribute(attr, placeholder.getAttribute(attr)); 94 } 95 }); 96 97 // Replace placeholder with iframe 98 if (placeholder.parentNode) { 99 placeholder.parentNode.replaceChild(iframe, placeholder); 100 } 101 } 102 103 /** 104 * Fallback: Load all iframes immediately (for unsupported browsers) 105 */ 106 function loadAllIframes() { 107 const placeholders = document.querySelectorAll('.ep-lazy-iframe-placeholder'); 108 placeholders.forEach(function(placeholder) { 109 // Add 2 second delay before loading iframe 110 loadIframe(placeholder); 111 }); 112 } 113 114 /** 115 * Initialize lazy loading 116 */ 117 function initLazyLoad() { 118 const placeholders = document.querySelectorAll('.ep-lazy-iframe-placeholder'); 119 120 if (placeholders.length === 0) { 121 return; 122 } 123 124 // Create observer 125 const observer = new IntersectionObserver(onIntersection, observerConfig); 126 127 // Observe all placeholders 128 placeholders.forEach(function(placeholder) { 129 observer.observe(placeholder); 130 }); 131 } 132 133 /** 134 * Run on DOM ready 135 */ 136 if (document.readyState === 'loading') { 137 // Add 2 second delay before initializing lazy load 138 setTimeout(initLazyLoad, 1000); 139 } else { 140 setTimeout(initLazyLoad, 1000); 141 } 142 143 /** 144 * Re-initialize for dynamically added content (e.g., AJAX loaded content) 145 */ 146 window.epReinitLazyLoad = initLazyLoad; 147 148})(); 149
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.