0
votes

I would appreciate some help with my lazy loading scripts. For reasons that escape me, images within the plugin Master Slider don't get lazy loaded.

My JavaScript searches for all images with a data-src attribute. If an image has the attribute, it exchanges it with a regular src attribute and the image loads. If no data-src is present, the image is left alone.

Prior to this, I intended for a PHP script to get all images and exchange src with data-src, so the images can't load with the page.

It works on everything but the image slider. It's implemented via the plugin Master Slider.

I think the problem has to be within the PHP, since the slider does load - just not lazily. All src attributes work, which means JavaScript left the slider alone.

Does anyone have an idea why this is?

PHP:

add_filter( 'the_content', 'my_lazyload_content_images' );
add_filter( 'widget_text', 'my_lazyload_content_images' );
add_filter( 'wp_get_attachment_image_attributes', 'my_lazyload_attachments', 10, 2 );

// Replace the image attributes in Post/Page Content
function my_lazyload_content_images( $content ) {

  //-- Change src/srcset to data attributes.
  $content = preg_replace( '/(<img.+)(src)/Ui', '$1data-$2', $content );
  $content = preg_replace( '/(<img.+)(srcset)/Ui', '$1data-$2', $content );

  //-- Add .lazy-load class to each image that already has a class.
  $content = preg_replace('/<img(.*?)class=\"(.*?)\"(.*?)>/i', '<img$1class="$2 lazy-load"$3>', $content);

  //-- Add .lazy-load class to each image that doesn't already have a class.
  $content = preg_replace('/<img((.(?!class=))*)\/?>/i', '<img class="lazy-load"$1>', $content);

  return $content;
}

// Replace the image attributes in Post Listing, Related Posts, etc.
function my_lazyload_attachments( $atts, $attachment ) {
  $atts['data-src'] = $atts['src'];
  unset( $atts['src'] );
  
  if( isset( $atts['srcset'] ) ) {
    $atts['data-srcset'] = $atts['srcset'];
    unset( $atts['srcset'] );
  }

  return $atts;
}

JavaScript:

let lazyImgs = document.querySelectorAll("img[data-src]");

function lazyLoad(lazyImgs) {
  const imgOptions = {
    threshold: 0.25,
    rootMargin: "0%",
  };

  const imgObserver = new IntersectionObserver((entries, imgObserver) => {
    entries.forEach((entry) => {
      if (entry.intersectionRatio > 0) {
        // get currently intersecting picture element and its children (source, img)
        let lazyImage = entry.target;

        // check if the element really has the attribute data-src, which we're using for lazy loading
        // if it doesn't leave the image alone
        if (lazyImage.hasAttribute("data-src")) {
          // exchange the src
          lazyImage.src = lazyImage.dataset.src;

          // also exchange the src, if the image has one
          if (lazyImage.srcset) {
            lazyImage.srcset = lazyImage.dataset.srcset;
          }
        } else {
          return false;
        }

        lazyImage.classList.add('is-loaded');

        // end observation of image once it's loaded :)
        imgObserver.unobserve(lazyImage);
      } // end is intersecting
    });
  }, imgOptions);

  // loop through all images and observe every single one
  lazyImgs.forEach((lazyImg) => {
    imgObserver.observe(lazyImg);
  });
} // end lazyLoad();

lazyLoad(lazyImgs);


And the CSS: 

.lazy-load {
  transition: opacity .15s;
  opacity: 0;
}

.lazy-load.is-loaded {
  opacity: 1;
}
1

1 Answers

1
votes

Why are you not just using the default html5 lazy loading?

<img src="_path_to_image_" loading="lazy">

https://web.dev/native-lazy-loading/