v1/web/modules/contrib/blazy/js/polyfill/blazy.webp.js

145 lines
3.7 KiB
JavaScript

/**
* @file
* Provides a few disposable polyfills till IE is gone from planet earth.
*
* Supports for webp is landed at D9.2. This file relies on core/picturefill
* which is always included as core/responsive_image polifyll as per 2022/2.
* This file is a client-side solution, with advantage clean native image markup
* since it doesn't change IMG into PICTURE till required by old browsers, as
* alt for HTML/ server-side solutions:
* - https://www.drupal.org/project/webp
* - https://www.drupal.org/project/imageapi_optimize_webp
*
* @see https://www.drupal.org/node/3171135
* @see https://www.drupal.org/project/drupal/issues/3213491
* @todo remove if picturefill suffices. FWIW, IE9 works fine with picturefill
* w/o this fallback. Not tested against other oldies, Safari, etc. So included,
* but can be ditched as usual via Blazy UI if not needed at all.
*/
(function ($, _win, _doc) {
'use strict';
if ($.webp) {
return;
}
var _key = 'bwebp';
var _dataSrcset = 'data-srcset';
var _picture = 'picture';
var _mimeWebp = 'image/webp';
var _source = 'source';
var pf = _win.picturefill;
function isSupported() {
var support = true;
// Ensures not locked down when Responsive image is not present, yet.
// @todo use $.decode for better async.
if (pf) {
var check = $.storage(_key);
if (!$.isNull(check)) {
return check === 'true';
}
// Undefined means supported, due to !pf.supPicture check.
support = $.isUnd(pf._.supportsType(_mimeWebp));
$.storage(_key, support);
}
return support;
}
function markup(img, webps, nowebps, dataset) {
if (!$.isElm(img)) {
return false;
}
var picture = $.create(_picture);
var source = $.create(_source);
var sizes = $.attr(img, 'sizes');
var webpSrc = webps.join(',').trim();
var nowebpSrc = nowebps.join(',').trim();
var check = $.find(picture, _source);
if (!$.isElm(check)) {
if (dataset) {
$.attr(source, _dataSrcset, webpSrc);
$.attr(img, _dataSrcset, nowebpSrc);
}
else {
source.srcset = webpSrc;
img.srcset = nowebpSrc;
}
if (sizes) {
source.sizes = sizes;
}
source.type = _mimeWebp;
$.append(picture, source);
$.append(picture, img);
}
return picture;
}
function convert(el) {
var img = _doc.importNode(el, true);
var webps = [];
var nowebps = [];
var dataset = $.attr(img, _dataSrcset);
var scrset = $.attr(img, 'srcset');
if (scrset.length || dataset.length) {
scrset = scrset.length ? scrset : dataset;
if (scrset.length) {
$.each(scrset.split(','), function (src) {
if ($.contains(src, '.webp')) {
webps.push(src);
}
else {
nowebps.push(src);
}
});
if (webps.length) {
return markup(img, webps, nowebps, dataset.length);
}
}
}
return false;
}
$.webp = {
isSupported: isSupported,
run: function (elms) {
if (isSupported() || !elms.length) {
return;
}
$.each(elms, function (el) {
var isImg = $.equal(el, 'img');
var pic = $.closest(el, _picture);
if (isImg && $.isNull(pic)) {
var parent = $.closest(el, '.media') || el.parentNode;
var picture = convert(el, true);
if (picture) {
// Cannot use parent.replaceWith because this is for old browsers.
// Nor parent.replaceChild(picture, el); due to various features.
$.append(parent, picture);
$.remove(el);
}
}
});
}
};
})(dBlazy, this, this.document);