1/** 2 * EU AI Label â badge wrapper layout guard. 3 * 4 * Themes commonly render cards at a fixed aspect ratio: a container gets a 5 * `padding-top` ratio box and the image is absolutely positioned to fill it. 6 * Our badge wrapper then becomes that image's containing block while holding 7 * no in-flow content, so it collapses to zero size and the image â resolving 8 * `inset: 0` / `height: 100%` against nothing â disappears. 9 * 10 * Stretching the wrapper over the same box restores the original geometry: an 11 * absolutely positioned wrapper resolves against the exact ancestor the image 12 * used before, so the image keeps its dimensions and the badge still overlays 13 * it. badge.css hard-codes this for the layouts we know by name (Flatsome, 14 * Elementor); this guard catches every other theme that does the same thing. 15 */ 16( function () { 17 'use strict'; 18 19 var WRAP_SELECTOR = '.eu-ai-label-wrap'; 20 var STRETCH_CLASS = 'eu-ai-label-wrap--stretch'; 21 22 /** 23 * Return the wrapped image, ignoring the badge and tooltip siblings. 24 * 25 * @param {Element} wrap Badge wrapper. 26 * @return {Element|null} Image element. 27 */ 28 function wrappedImage( wrap ) { 29 for ( var child = wrap.firstElementChild; child; child = child.nextElementSibling ) { 30 if ( 'IMG' === child.tagName ) { 31 return child; 32 } 33 } 34 35 return null; 36 } 37 38 /** 39 * Stretch a wrapper whose image the theme takes out of flow. 40 * 41 * @param {Element} wrap Badge wrapper. 42 * @return {void} 43 */ 44 function guard( wrap ) { 45 if ( wrap.classList.contains( STRETCH_CLASS ) ) { 46 return; 47 } 48 49 var image = wrappedImage( wrap ); 50 if ( ! image ) { 51 return; 52 } 53 54 var position = window.getComputedStyle( image ).position; 55 if ( 'absolute' === position || 'fixed' === position ) { 56 wrap.classList.add( STRETCH_CLASS ); 57 } 58 } 59 60 /** 61 * Check a subtree, including the root itself. 62 * 63 * @param {Node} root Element or document to scan. 64 * @return {void} 65 */ 66 function scan( root ) { 67 if ( ! root || ! root.querySelectorAll ) { 68 return; 69 } 70 71 if ( root.matches && root.matches( WRAP_SELECTOR ) ) { 72 guard( root ); 73 } 74 75 Array.prototype.forEach.call( root.querySelectorAll( WRAP_SELECTOR ), guard ); 76 } 77 78 var scheduled = false; 79 80 /** 81 * Coalesce repeated requests into a single pass before the next paint. 82 * 83 * @return {void} 84 */ 85 function scheduleScan() { 86 if ( scheduled ) { 87 return; 88 } 89 90 scheduled = true; 91 window.requestAnimationFrame( function () { 92 scheduled = false; 93 scan( document ); 94 } ); 95 } 96 97 function start() { 98 scan( document ); 99 100 // Stylesheets loaded after the first pass, and lazy-loaded or 101 // Ajax-injected images (Loop Grids, product filters, infinite scroll), 102 // can both change the answer, so re-check when the DOM settles. 103 window.addEventListener( 'load', scheduleScan ); 104 105 new MutationObserver( function ( mutations ) { 106 for ( var i = 0; i < mutations.length; i++ ) { 107 if ( mutations[ i ].addedNodes.length ) { 108 scheduleScan(); 109 return; 110 } 111 } 112 } ).observe( document.documentElement, { childList: true, subtree: true } ); 113 } 114 115 if ( 'loading' === document.readyState ) { 116 document.addEventListener( 'DOMContentLoaded', start ); 117 } else { 118 start(); 119 } 120}() );
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.