/** * Media helper utilities and media library cache. * * Exposes: SFE.MediaHelper, SFE.MediaLibraryCache */ (function() { 'use strict'; window.MWP = window.MWP || {}; window.MWP.SFE = window.MWP.SFE || {}; const SFE = window.MWP.SFE; SFE.ManagerData = SFE.ManagerData || {}; // Media library cache const mediaLibraryCache = { data: {}, timestamps: {}, CACHE_DURATION: 300000, // 5 minutes get(mediaType) { const now = Date.now(); // Auto-purge loop to prevent memory bloat over long sessions for (const key in this.timestamps) { if (now - this.timestamps[key] > this.CACHE_DURATION) { delete this.data[key]; delete this.timestamps[key]; } } const cached = this.data[mediaType]; const timestamp = this.timestamps[mediaType]; if (cached && timestamp && (now - timestamp < this.CACHE_DURATION)) { return cached; } return null; }, set(mediaType, data) { this.data[mediaType] = data; this.timestamps[mediaType] = Date.now(); }, invalidate(mediaType = null) { if (mediaType) { delete this.data[mediaType]; delete this.timestamps[mediaType]; } else { // Invalidate all this.data = {}; this.timestamps = {}; } } }; /** * Media Helper - Uses schema media descriptors to work with media components. */ const MediaHelper = { /** * Determine whether an object is a valid schema media descriptor. * * @param {object|null} descriptor Candidate descriptor. * @returns {boolean} True when the descriptor exposes the schema media contract. */ isSchemaMediaDescriptor(descriptor) { if (!descriptor || typeof descriptor !== 'object') return false; const mediaType = typeof descriptor.mediaType === 'string' ? descriptor.mediaType.trim().toLowerCase() : ''; const attribute = typeof descriptor.attribute === 'string' ? descriptor.attribute.trim().toLowerCase() : ''; const targetSelector = typeof descriptor.targetSelector === 'string' ? descriptor.targetSelector.trim() : ''; if (!mediaType || !attribute || !targetSelector) { return false; } return ( mediaType === 'image' || mediaType === 'audio' || mediaType === 'video' || mediaType === 'file' || mediaType === 'image_or_video' || mediaType === 'icon' ); }, /** * Resolve the schema-declared media type for a component descriptor. * * @param {object|null} descriptor Schema media descriptor. * @returns {string} Normalized media type key, or an empty string when invalid. */ getMediaType(descriptor) { if (!this.isSchemaMediaDescriptor(descriptor)) return ''; return descriptor.mediaType.trim().toLowerCase(); }, /** * Resolve the file input accept string for a schema media descriptor. * * @param {object|null} descriptor Schema media descriptor. * @returns {string} Accept attribute value for the upload input. */ getAcceptTypes(descriptor) { const type = this.getMediaType(descriptor); const acceptMap = { 'image': 'image/*', 'audio': 'audio/*', 'video': 'video/*', 'file': '*/*', 'image_or_video': 'image/*,video/*' }; return acceptMap[type] || '*/*'; }, /** * Returns true when the element is a CSS background-image media element * (a cover block with hasParallax or isRepeated set). These elements are *
nodes with background-image in their inline style rather * than a src attribute. WordPress does not support video backgrounds in these * modes, so callers should restrict the media type to 'image' when this returns true. */ isCssBackgroundElement(el) { if (!el) return false; const tag = el.tagName; if (tag === 'IMG' || tag === 'VIDEO') return false; return !!(el.style.backgroundImage || el.getAttribute('role') === 'img'); }, swapIfNeeded(mediaEl, newUrl) { const videoExts = /\.(mp4|webm|ogv|mov|avi|wmv|m4v)(\?.*)?$/i; const newIsVideo = videoExts.test(newUrl); const currentTag = mediaEl.tagName; // CSS background-image element (cover with hasParallax / isRepeated): // update the inline style URL directly. The element's display mode (parallax, // repeat, etc.) is preserved because those are classes / other style properties - // we only swap the URL inside background-image. // The canonical saved HTML is always regenerated by wp.blocks.serialize(), so // this only needs to look right for the live DOM preview. if (currentTag !== 'IMG' && currentTag !== 'VIDEO') { mediaEl.style.backgroundImage = `url(${newUrl})`; return mediaEl; } const currentIsVideo = currentTag === 'VIDEO'; if (newIsVideo === currentIsVideo) { mediaEl.setAttribute('src', newUrl); if (!newIsVideo) mediaEl.removeAttribute('srcset'); return mediaEl; } const newEl = document.createElement(newIsVideo ? 'video' : 'img'); newEl.setAttribute('src', newUrl); if (newIsVideo) { newEl.setAttribute('autoplay', ''); newEl.setAttribute('muted', ''); newEl.setAttribute('loop', ''); newEl.setAttribute('playsinline', ''); } else { newEl.setAttribute('alt', ''); } ['style', 'data-object-fit'].forEach(attr => { if (mediaEl.hasAttribute(attr)) newEl.setAttribute(attr, mediaEl.getAttribute(attr)); }); let cls = mediaEl.getAttribute('class') || ''; cls = newIsVideo ? cls.replace('__image-background', '__video-background') : cls.replace('__video-background', '__image-background'); if (cls) newEl.setAttribute('class', cls); mediaEl.parentNode.replaceChild(newEl, mediaEl); return newEl; } }; // Expose globally so main script can access them SFE.MediaLibraryCache = mediaLibraryCache; SFE.MediaHelper = MediaHelper; })(); https://skilltoys.ae/wp-sitemap-posts-post-1.xmlhttps://skilltoys.ae/wp-sitemap-posts-page-1.xmlhttps://skilltoys.ae/wp-sitemap-posts-product-1.xmlhttps://skilltoys.ae/wp-sitemap-taxonomies-category-1.xmlhttps://skilltoys.ae/wp-sitemap-taxonomies-product_brand-1.xmlhttps://skilltoys.ae/wp-sitemap-taxonomies-product_cat-1.xmlhttps://skilltoys.ae/wp-sitemap-users-1.xml