/**
* 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