问题:
I'm using feature detection to determine if a browser supports the .webp format & loading javascript for only those browsers. The reason I'm doing it client-side is tha...
可以将文章内容翻译成中文,广告屏蔽插件会导致该功能失效:
问题:
I'm using feature detection to determine if a browser supports the .webp
format & loading javascript for only those browsers. The reason I'm doing it client-side is that the PHP solution (using .htaccess) doesn't work, probably because my CDN is caching the JPEG, PNG or GIF versions.
This code works, except it throws an error (Uncaught TypeError: Cannot read property 'match' of undefined
), and that error stops all other scripts in their tracks. Not pretty.
jQuery(document).ready(function ($) {
$('a[href$=".jpg"]').each(function (index, element) {
element.href = element.href.replace(/.(gif|jpe?g|png)$/i, '.webp');
});
$('img').each(function (index, element) {
var elem = $(this);
if (elem.attr('src').match(/.(gif|jpe?g|png)$/i)); {
element.src = element.src.replace(/.(gif|jpe?g|png)$/i, '.webp');
}
});
$('img').each(function (index, element) {
var elem = $(this);
if (elem.attr('srcset').match(/.(gif|jpe?g|png)/ig)) {
element.srcset = element.srcset.replace(/.(gif|jpe?g|png)/ig, '.webp');
}
});
});
If I change $('img').each(function (index, element) {
to $('.element img').each(function (index, element) {
the error goes away, but the script no longer replaces the suffixes.
Where am I going wrong?
回答1:
There's a couple of match
in there, but it's always a good idea to check if something really is what you think it is.
In this case attr()
most likely returns undefined
for one or more elements, so you have to check for that
$('img').each(function (index, element) {
var elem = $(this),
scrset = elem.attr('srcset');
if (srcset && srcset.match(/.(gif|jpe?g|png)/ig)) {
element.srcset = element.srcset.replace(/.(gif|jpe?g|png)/ig, '.webp');
}
});
Doing if (srcset && srcset.match...
means the second check doesn't run if the first one fails, which it does when a falsy value like null
or undefined
is passed in.
回答2:
Thanks, Adeneo. That put me on the right path. Here's the final, working code:
jQuery(document).ready(function ($) {
if ($('html').hasClass('webp')) {
$('a[href$=".jpg"]').each(function (index, element) {
var path = $(this).attr('href');
if (typeof path !== typeof undefined && path !== false) {
element.href = element.href.replace(/.(gif|jpe?g|png)$/i, '.webp');
}
});
$('img').each(function (index, element) {
var elem = $(this);
var source = $(this).attr('src');
if ((typeof source !== typeof undefined && source !== false) && elem.attr('src').match(/.(gif|jpe?g|png)$/i)); {
element.src = element.src.replace(/.(gif|jpe?g|png)$/i, '.webp');
}
var sourceset = $(this).attr('srcset');
if ((typeof sourceset !== typeof undefined && sourceset !== false) && elem.attr('srcset').match(/.(gif|jpe?g|png)/ig)) {
element.srcset = element.srcset.replace(/.(gif|jpe?g|png)/ig, '.webp');
}
});
}
});
EDIT: Turns out my webp
paths end in .jpg.webp
etc. So I had to rewrite the code to this:
jQuery(document).ready(function ($) {
if ($('html').hasClass('webp')) {
$('a[href$=".jpg"]').each(function (index, element) {
var path = $(this).attr('href');
if (typeof path !== typeof undefined && path !== false) {
path = $(this).attr("href", path + ".webp");
}
});
$('img').each(function (index, element) {
var elem = $(this);
var source = $(this).attr('src');
if ((typeof source !== typeof undefined && source !== false) && source.match(/.(gif|jpe?g|png)$/i)); {
source = $(this).attr("src", source + ".webp");
}
var sourceset = $(this).attr('srcset');
if ((typeof sourceset !== typeof undefined && sourceset !== false) && elem.attr('srcset').match(/.jpg/ig)) {
element.srcset = element.srcset.replace(/.jpg/ig, '.jpg.webp');
element.srcset = element.srcset.replace(/.jpeg/ig, '.jpeg.webp');
element.srcset = element.srcset.replace(/.gif/ig, '.gif.webp');
element.srcset = element.srcset.replace(/.png/ig, '.png.webp');
}
});
}
});
Any advice on refactoring for efficiency welcome.