Replace image attributes for lazyload plugin on image elements with a specific class

I am using WordPress and I want to lazy load certain images only. I found a way to create the data-src attributes here and replace the src attribute with the correct image https://wordpress.stackexchange.com/questions/60792/replace-image-attributes-for-lazyload-plugin-data-src . Right now my code is applying lazy loading to all images, and I just want to apply them to images with lazy loading class.

This is how my code looks like

// Lazyload Converter
function add_lazyload($content) {

$content = mb_convert_encoding($content, 'HTML-ENTITIES', "UTF-8");
$dom = new DOMDocument();
@$dom->loadHTML($content);

$images = [];

foreach ($dom->getElementsByTagName('img') as $node) {
    $images[] = $node;
}

foreach ($images as $node) {
    $fallback = $node->cloneNode(true);

    $oldsrc = $node->getAttribute('src');
    $node->setAttribute('data-src', $oldsrc );
    $newsrc = get_template_directory_uri() . '/assets/placeholders/squares.svg';
    $node->setAttribute('src', $newsrc);

    $oldsrcset = $node->getAttribute('srcset');
    $node->setAttribute('data-srcset', $oldsrcset );
    $newsrcset = '';
    $node->setAttribute('srcset', $newsrcset);

    $noscript = $dom->createElement('noscript', '');
    $node->parentNode->insertBefore($noscript, $node);
    $noscript->appendChild($fallback);
}

$newHtml = preg_replace('/^<!DOCTYPE.+?>/', '', str_replace( array('<html>', '</html>', '<body>', '</body>'), array('', '', '', ''), $dom->saveHTML()));
return $newHtml;
}
add_filter('the_content', 'add_lazyload');
add_filter('post_thumbnail_html', 'add_lazyload');

      

how can I get an element by class instead of using a tag?

+3


source to share


1 answer


you can use (from ); xpath is a query language for selecting nodes from XML / HTML documents.

Unfortunately, the selection of elements that have a class that is a separate phrase lazy-load

is slightly collapsed with xpath; it is not as concise as you might be used to; xpath has no shorthand attribute selectors like @attr~="lazy-load"

etc.

Here's an example of how you would select all elements <img>

that have a class lazy-load

:

// create a DOMXPath instance that operates on your DOMDocument instance $dom
$xpath = new DOMXPath( $dom );

// select nodes by some criteria (returns a non-liveΒΉ DOMNodeList)
$images = $xpath->query( '//img[contains(concat(" ", normalize-space(@class), " "), " lazy-load ")]' );

// then apply the same operations to the nodes again as in your last foreach loop
foreach ($images as $node) {
  $fallback = $node->cloneNode(true);
  // etc.
}

      

1) Even though it is not officially documented anywhere (as far as I know) DOMNodeList

, the returned DOMXPath

one is not "live", and not DOMNodeList

returned DOMDocument

, I believe. So, your first one foreach()

should be unnecessary. But you should try to try.



I would suggest doing any of the following, but if you are sure that the only class those elements will have <img>

will be lazy-load

, that is, the attribute class

will always be exactly lazy-load

, without any spaces and / or other classes, you can also use this , a much simpler query:

$images = $xpath->query( '//img[@class="lazy-load"]' );

      

or, if elements <img>

can have multiple classes, but will never have other classes containing the phrase lazy-load

(for example class="thumbnail lazy-loading"

, for example), you can use:

$images = $xpath->query( '//img[contains(@class,"lazy-load")]' );

      

0


source







All Articles