Loop thru image “srcset” attribute and replace filetype suffix

问题: 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.

  • 发表于 2019-02-19 21:54
  • 阅读 ( 264 )
  • 分类:sof

条评论

请先 登录 后评论
不写代码的码农
小编

篇文章

作家榜 »

  1. 小编 文章
返回顶部
部分文章转自于网络,若有侵权请联系我们删除