/** * Auto-detects image and container dimensions and applies the optimal fitting method * Works with both background images and regular img elements * @param {string} containerSelector - CSS selector for container elements * @param {Object} [options] - Optional configuration * @param {boolean} [options.debug=false] - Enable debug console logs * @param {number} [options.padding=0] - Padding inside container (in pixels) * @param {function} [options.callback] - Optional callback after processing */ function autoFitImages(containerSelector, options = {}) { // Default options const config = { debug: options.debug || false, padding: options.padding || 0, callback: options.callback || null }; // Helper function for logging const log = message => { if (config.debug) console.log(`🔍 ${message}`); }; log(`Starting autoFitImages for selector: ${containerSelector}`); // Handle both selector string and element array let containers; if (typeof containerSelector === 'string') { containers = document.querySelectorAll(containerSelector); log(`Found ${containers.length} container elements with selector: ${containerSelector}`); } else if (Array.isArray(containerSelector)) { containers = containerSelector; log(`Processing ${containers.length} provided container elements`); } else { console.warn(`⚠️ Invalid container selector type: ${typeof containerSelector}`); return; } if (!containers.length) { console.warn(`⚠️ No container elements found to process`); return; } let processedCount = 0; const totalContainers = containers.length; // Process each container containers.forEach((container, index) => { log(`Processing container ${index + 1}/${totalContainers}`); // Get container dimensions const containerRect = container.getBoundingClientRect(); const containerWidth = containerRect.width; const containerHeight = containerRect.height; if (containerWidth === 0 || containerHeight === 0) { log(`Container ${index + 1} has zero dimension. Skipping.`); processedCount++; if (processedCount === totalContainers && config.callback) { config.callback(); } return; } log(`Container dimensions: ${containerWidth}px × ${containerHeight}px`); // Check if container has background image const style = window.getComputedStyle(container); const backgroundImage = style.backgroundImage; if (backgroundImage && backgroundImage !== 'none') { // Process background image log(`Container ${index + 1} has background image: ${backgroundImage}`); // Extract image URL const imageSrc = backgroundImage.match(/url\(['"]?(.*?)['"]?\)/i)?.[1]; if (!imageSrc) { log(`No valid background image URL found for container ${index + 1}`); processedCount++; if (processedCount === totalContainers && config.callback) { config.callback(); } return; } // Load image to check dimensions const tempImage = new Image(); tempImage.onload = () => { const imgWidth = tempImage.width; const imgHeight = tempImage.height; log(`Background image dimensions: ${imgWidth}px × ${imgHeight}px`); // Apply best fitting method based on dimensions const bestFitMethod = determineBestFitMethod( imgWidth, imgHeight, containerWidth, containerHeight ); log(`Selected fit method for container ${index + 1}: ${bestFitMethod}`); // Apply the best fit method applyBackgroundFitMethod(container, bestFitMethod); processedCount++; if (processedCount === totalContainers && config.callback) { config.callback(); } }; tempImage.onerror = () => { log(`Failed to load background image for container ${index + 1}`); processedCount++; if (processedCount === totalContainers && config.callback) { config.callback(); } }; tempImage.src = imageSrc; } else { // Check for img elements inside container const imgElements = container.querySelectorAll('img'); if (imgElements.length > 0) { log(`Container ${index + 1} has ${imgElements.length} img elements`); let imgProcessedCount = 0; imgElements.forEach((img, imgIndex) => { log(`Processing img ${imgIndex + 1} in container ${index + 1}`); const processImg = () => { const imgWidth = img.naturalWidth; const imgHeight = img.naturalHeight; log(`Image dimensions: ${imgWidth}px × ${imgHeight}px`); // Apply best fitting method based on dimensions const bestFitMethod = determineBestFitMethod( imgWidth, imgHeight, containerWidth, containerHeight ); log(`Selected fit method for img ${imgIndex + 1}: ${bestFitMethod}`); // Apply the best fit method to the img element applyImgFitMethod(img, bestFitMethod, containerWidth, containerHeight); imgProcessedCount++; if (imgProcessedCount === imgElements.length) { processedCount++; if (processedCount === totalContainers && config.callback) { config.callback(); } } }; if (img.complete) { processImg(); } else { img.onload = processImg; img.onerror = () => { log(`Failed to load img ${imgIndex + 1} in container ${index + 1}`); imgProcessedCount++; if (imgProcessedCount === imgElements.length) { processedCount++; if (processedCount === totalContainers && config.callback) { config.callback(); } } }; } }); } else { log(`Container ${index + 1} has no images to process`); processedCount++; if (processedCount === totalContainers && config.callback) { config.callback(); } } } }); } /** * Determines the best fitting method based on image and container dimensions * @param {number} imgWidth - Image width * @param {number} imgHeight - Image height * @param {number} containerWidth - Container width * @param {number} containerHeight - Container height * @returns {string} - Best fitting method: 'contain', 'cover', or 'auto' */ function determineBestFitMethod(imgWidth, imgHeight, containerWidth, containerHeight) { // Calculate aspect ratios const imgRatio = imgWidth / imgHeight; const containerRatio = containerWidth / containerHeight; // Small images - use auto for crisp rendering if (imgWidth < 200 && imgHeight < 200) { return 'auto'; } // Very tall images (portrait) - use contain if (imgHeight >= 900 || imgHeight > containerHeight * 1.5) { return 'contain'; } // Medium-sized images with similar ratio to container - use cover for aesthetics if (imgWidth >= 300 && imgWidth <= 900 && imgHeight >= 350 && imgHeight <= 900 && Math.abs(imgRatio - containerRatio) < 0.2) { return 'cover'; } // Images almost matching container size - use cover if (Math.abs(imgWidth - containerWidth) < containerWidth * 0.2 && Math.abs(imgHeight - containerHeight) < containerHeight * 0.2) { return 'cover'; } // Default to contain for most cases return 'contain'; } /** * Applies the selected fit method to a background image * @param {HTMLElement} container - Container element * @param {string} fitMethod - Fitting method: 'contain', 'cover', or 'auto' */ function applyBackgroundFitMethod(container, fitMethod) { container.style.backgroundRepeat = 'no-repeat'; container.style.backgroundPosition = 'center center'; // Remove any existing classes container.classList.remove('image-bg-contain', 'image-bg-cover', 'image-bg-auto'); // Apply the appropriate class based on the fit method container.classList.add(`image-bg-${fitMethod}`); // Also set the background-size directly for immediate effect container.style.backgroundSize = fitMethod; } /** * Applies the selected fit method to an img element * @param {HTMLImageElement} img - Image element * @param {string} fitMethod - Fitting method: 'contain', 'cover', or 'auto' * @param {number} containerWidth - Container width * @param {number} containerHeight - Container height */ function applyImgFitMethod(img, fitMethod, containerWidth, containerHeight) { // Reset styles img.style.width = ''; img.style.height = ''; img.style.maxWidth = ''; img.style.maxHeight = ''; img.style.objectFit = ''; // Center the image img.style.display = 'block'; img.style.margin = 'auto'; // Handle different fit methods if (fitMethod === 'contain') { img.style.maxWidth = '100%'; img.style.maxHeight = '100%'; img.style.objectFit = 'contain'; } else if (fitMethod === 'cover') { img.style.width = '100%'; img.style.height = '100%'; img.style.objectFit = 'cover'; } else if (fitMethod === 'auto') { img.style.maxWidth = '100%'; img.style.maxHeight = '100%'; // No object-fit for auto to preserve original dimensions } } // Create CSS for background image classes if they don't exist function ensureBackgroundClasses() { // Check if styles already exist if (!document.getElementById('auto-image-fit-styles')) { const styleElement = document.createElement('style'); styleElement.id = 'auto-image-fit-styles'; styleElement.textContent = ` .image-bg-contain { background-size: contain !important; background-position: center center !important; background-repeat: no-repeat !important; } .image-bg-cover { background-size: cover !important; background-position: center center !important; background-repeat: no-repeat !important; } .image-bg-auto { background-size: auto !important; background-position: center center !important; background-repeat: no-repeat !important; } `; document.head.appendChild(styleElement); } } /** * Process all images on the page * @param {boolean} debug - Enable debug logging */ function processAllImagesOnPage(debug = false) { console.log('🖼� Processing all images on the page'); // Ensure CSS classes exist ensureBackgroundClasses(); // Find all elements with background images const allElements = document.querySelectorAll('*'); const elementsWithBgImage = Array.from(allElements).filter(el => { const style = window.getComputedStyle(el); return style.backgroundImage && style.backgroundImage !== 'none'; }); if (debug) { console.log(`Found ${elementsWithBgImage.length} elements with background images`); } // Process all elements with background images if (elementsWithBgImage.length > 0) { autoFitImages(elementsWithBgImage, { debug: debug, callback: function () { if (debug) console.log('� All background images processed'); } }); } // Find all image containers (elements that contain img tags) const imgElements = document.querySelectorAll('img'); const imgContainers = Array.from(imgElements).map(img => img.parentElement); if (debug) { console.log(`Found ${imgElements.length} img elements on the page`); } // Process all image containers if (imgContainers.length > 0) { autoFitImages(imgContainers, { debug: debug, callback: function () { if (debug) console.log('� All img elements processed'); } }); } if (debug) { console.log('� Page image processing complete'); } } // Run automatically when DOM is loaded document.addEventListener('DOMContentLoaded', function () { //processAllImagesOnPage(true); // Set to true for debug, false for production //autoFitImages('.featuredNewsH', { debug: true }) }); // For dynamic content or manual execution: // processAllImagesOnPage(true); // For specific containers (original method): // autoFitImages('.featuredNewsH', { debug: true }); window.initGradientEffect = function () { } document.addEventListener('DOMContentLoaded', function () { const extendedTableZoomElements = document.querySelectorAll('.extended-table-zoom'); if (extendedTableZoomElements && extendedTableZoomElements.length > 0) { if (!window.Stickyfill) { setTimeout(() => { window.Stickyfill.add(extendedTableZoomElements); }, 500); } else { window.Stickyfill.add(extendedTableZoomElements); } } const socialMediaSideBarContainerElement = document.querySelectorAll('.social-media-side-bar-container'); if (socialMediaSideBarContainerElement && socialMediaSideBarContainerElement.length > 0) { if (!window.Stickyfill) { setTimeout(() => { window.Stickyfill.add(socialMediaSideBarContainerElement); }, 500); } else { window.Stickyfill.add(socialMediaSideBarContainerElement); } } }, false); window.addEventListener("load", (event) => { var selectedLanguage = pnrApplicationSettings.SelectedLocale ?? 'en-US'; selectedLanguage = selectedLanguage.split('-')[0] ?? 'en'; if (window.Optanon) { window.Optanon.changeLanguage(selectedLanguage); } else { setTimeout(() => { window.Optanon?.changeLanguage(selectedLanguage); },100) } if (window.EventsCaptureEnabled) { enableGoogleAnalyticsPageEvent(); } }); function getLanguageCodeFromUrl() { try { const pathname = window.location.pathname; const parts = pathname.split("/").filter(Boolean); // Remove empty segments // Check if the first segment is a two-letter language code const languageCode = parts.length > 0 && /^[a-zA-Z]{2}$/.test(parts[0]) ? parts[0] // Return the detected language code : "en"; // Default to "en" if no valid language code is found return languageCode; } catch (e) { return 'en'; } } function getPathFromUrl() { try { const pathname = window.location.pathname; const parts = pathname.split("/").filter(Boolean); // Remove empty segments // Skip two-letter language codes (any two letters) and purely numeric segments const filteredParts = parts.filter(part => !/^[a-zA-Z]{2}$/.test(part) && // Skip any two-letter language codes !/^\d+$/.test(part) // Skip numeric segments (dates, IDs, etc.) ); return filteredParts.length > 0 ? filteredParts[0] : "home"; } catch (e) { return 'home'; } } function enableGoogleAnalyticsPageEvent() { function trackEvent(action, target, url = "N/A") { if (!target || typeof window.gtag !== "function") return; let label = target.getAttribute("data-label") || target.textContent.trim() || target.alt || target.value || target.getAttribute("name") || target.id || "Unknown"; if (label) { label = label.trim(); } let type = target.tagName.toLowerCase(); let isInternal = url.includes("globenewswire.com") ? "Yes" : "No"; let pageName = getPathFromUrl(); let contextViewName = window.pnrContextViewName ?? ""; let languageCode = getLanguageCodeFromUrl(); if (pnrApplicationSettings && pnrApplicationSettings.TrackGoogleAnalyticsLogs) { console.log(`GA Event � Action: ${action}, Label: ${label}, Type: ${type}, URL: ${url}, Internal: ${isInternal}, PageName: ${pageName}, languageCode: ${languageCode}, ViewName: ${contextViewName}`); } window.gtag('event', action, { 'event_category': type, 'event_label': label, 'navigation_url': url, 'page_name': pageName, 'internal_page': isInternal, 'view_name': contextViewName, 'language_code': languageCode }); } document.body.addEventListener("click", function (event) { let target = event.target.closest("a, button"); if (!target) return; let actionType = target.tagName.toLowerCase() === "a" ? "pnr_click_href" : "pnr_click_button"; let url = target.href || "N/A"; // Prevent default behavior for anchor tags without href if (target.tagName.toLowerCase() === "a" && !target.href) { event.preventDefault(); trackEvent(actionType, target, url); return; } trackEvent(actionType, target, url); // Delay for outbound links to ensure tracking fires if (target.tagName.toLowerCase() === "a" && !url.includes("globenewswire.com")) { event.preventDefault(); setTimeout(() => { window.location.href = url; }, 100); } }); };