0

I want to apply lazy load to only certain images. I found here ( Replace image attributes for lazyload plugin (data-src) ) a way to create the data-src attributes and replace the src attribute with the correct image. Right now my code applies the lazy load to all the images, and I just want to apply it to the images with the class lazy-load.

This is how my code looks right now

// 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 the element by class instead of using tag?

  • what is the question? "write code for me" is not really a question, and in any case this is either php or a JS thing, not a wordpress specific one – Mark Kaplun Jun 3 '17 at 3:28
  • I'm not asking you to write code for me.The question is how can I get the element by class instead of using tag. I post it here because I found a similar answer and because is for WordPress. – alejuu Jun 3 '17 at 3:34
0

Here's a solution that only applies the lazy load processing to images with the .lazy-load class. I'm loading the HTML a little differently, but this approach has worked out reliably for me in the past. The processing of the HTML is the same as in the original code. The trick for targeting images with a particular class is this line:

// Match elements with the lazy-load class (note space around class name)
// See http://stackoverflow.com/a/26126336/3059883
$lazy_load_images = $xpath->query( "//img[ contains( concat( ' ', normalize-space( @class ), ' '), ' lazy-load ' ) ]" );

Full code:

/**
 * Lazyload Converter - Sets up images for  lazy loading:
 *  - Affects only images with the .lazy-load class.
 *  - Assigns original src value to data-src attribute
 *  - Replaces original src value with a placeholder image
 *  - Assigns original srcset value to data-srcset
 *  - Replaces original srcset value to empty string
 *  - Creates noscript tag containing fallback HTML
 * 
 * @param string $content
 * @return string
 */
add_filter( 'the_content', 'wpse_add_lazyload' );
add_filter( 'post_thumbnail_html', 'wpse_add_lazyload' ); 
function wpse_add_lazyload( $content ) {
    $placeholder = get_template_directory_uri() . '/assets/placeholders/squares.svg';

    // Create an instance of DOMDocument.
    $dom = new \DOMDocument();

    // Supress errors due to malformed HTML.
    // See http://stackoverflow.com/a/17559716/3059883
    $libxml_previous_state = libxml_use_internal_errors( true );

    // Populate $dom with $content, making sure to handle UTF-8, otherwise
    // problems will occur with UTF-8 characters.
    // Also, make sure that the doctype and HTML tags are not added to our HTML fragment. http://stackoverflow.com/a/22490902/3059883
    $dom->loadHTML( mb_convert_encoding( $content, 'HTML-ENTITIES', 'UTF-8' ), LIBXML_HTML_NOIMPLIED | LIBXML_HTML_NODEFDTD );

    // Restore previous state of libxml_use_internal_errors() now that we're done.
    libxml_use_internal_errors( $libxml_previous_state );

    // Create an instance of DOMXpath.
    $xpath = new \DOMXpath( $dom );

    // Match elements with the lazy-load class (note space around class name)
    // See http://stackoverflow.com/a/26126336/3059883
    $lazy_load_images = $xpath->query( "//img[ contains( concat( ' ', normalize-space( @class ), ' '), ' lazy-load ' ) ]" );

    // Process image HTML
    foreach ( $lazy_load_images as $node ) {
        $fallback = $node->cloneNode( true );

        $oldsrc = $node->getAttribute( 'src' );
        $node->setAttribute( 'data-src', $oldsrc );
        $newsrc = $placeholder;
        $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 );    
    }

    // Save and return updated HTML.
    $new_content = $dom->saveHTML(); 
    return  $new_content;
}

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.