0

I've got a custom post type setup which displays a gallery below the hero. It's setup to display the first 9 images in a gallery using the following code, when one clicks the "View All Photos" button it will display the rest of the gallery with a button to collapse the gallery back to the original 9 after that. This used to work just fine, and in fact still does on posts I created prior to updating WP. It for some reason which I can't figure out, won't work on new posts I create. Clicking the "View All Photos" button will display the whole gallery, but the first 9 images won't show up prior to clicking the button. I've attached a couple of links below the code to one working and one not working example. I really hope someone can help, I'm completely stuck.

<div class="collapse show gal" id="collapsePreview" aria-labelledby="preview" data-parent="#galleryAccordion">
                            <?php
                                if (has_block('gallery', $post->post_content)) {
                                    $post_blocks = parse_blocks($post->post_content);
                                    $ids = $post_blocks[0][attrs][ids];
                                    $count = 0;

                                    foreach ($ids as $key => $value ) { 
                                        $image_full     = wp_get_attachment_image_src( $value, 'full'); 
                                        $image_thumb    = wp_get_attachment_image_src( $value, 'small'); 

                                        if ($count < 9) {
                                            ?>
                                            <!--<div class="col-sm-4">-->
                                                <a href="<?php echo $image_full[0] ?>" data-toggle="lightbox" data-gallery="gallery">
                                                    <img src="<?php echo $image_thumb[0] ?>" class="d-block w-100" alt="...">
                                                </a>
                                            <!--</div>-->
                                            <?php 
                                        } else {
                                            break;
                                        }
                                        $count++;
                                    }

                                }
                            ?>
                        </div><!-- gal -->
                        
                        <div class="collapse full-gal" id="expandGallery" aria-labelledby="gallery" data-parent="#galleryAccordion">
                        <?php while ( have_posts() ) : the_post(); ?>

                            <?php //get_template_part( 'loop-templates/content', 'single' ); ?>

                            <?php echo the_content(); ?>
                            
                            <button class="btn btn-primary btn-block collapsed" data-toggle="collapse" data-target="#collapsePreview" aria-expanded="false" aria-controls="collapsePreview">Hide Photos</a>

                            <?php // understrap_post_nav(); ?>


                        <?php endwhile; // end of the loop. ?>
                        </div>
                        <div class="collapse show" id="collapsePreview" aria-labelledby="preview" data-parent="#galleryAccordion">
                            <button class="btn btn-info btn-block collapsed" data-toggle="collapse" data-target="#expandGallery" aria-expanded="false" aria-controls="expandGallery">View All Photos</a>
                        </div>

Working (posted on 2021/05/18): https://aif.design/listing/300-avenue-road-th4/

Not working (posted on 2023/05/23): https://aif.design/listing/64-langford-avenue/


Reply to Tom:

Thank you for the extremely detailed response, I truly appreciate it!!

There are a couple things that I would love to ask you to help me out with if possible, I'm a JS noob so please forgive my ignorance on implementation.

First, the rest of this site outside of the custom post type for real estate listings is my content delivery website for clients, so I don't want all galleries to hide >9 photos, only hiding the >9 on the custom post type 'listing', not sure how to implement that change to the functions you provided. I've taken your advise and chosen to display image size 'large' The reason for the right click disabled is due to some content delivery to clients being behind a pay wall, I can't figure out how to disable it on the 'listing' custom post type

I've replaced the code above with the following:

<div class="collapsed-gallery" id="collapsedGallery">
    <?php while ( have_posts() ) : the_post(); ?>

        <?php //get_template_part( 'loop-templates/content', 'single' ); ?>

        <?php echo the_content(); ?>
                            
        <?php // understrap_post_nav(); ?>


    <?php endwhile; // end of the loop. ?>
</div><!-- collapsed-gallery -->    
                    
<button class="btn btn-primary btn-block" data-toggle="collapsed-gallery" data-target="#collapsedGallery" aria-expanded="false" aria-controls="collapsed-gallery">Show More</a>

and added the css you provided to my stylesheet, but this alone isn't doing the trick, or I'm doing something wrong, a little extra guidance here would be very much appreciated ( sorry, I'm not a dev, just do this on the side ).

additionally, would you possibly be able to help me with showing a "Hide Photos" button when the gallery is opened instead of persistently displaying the "Show More" button?

1 Answer 1

0

There are 2 core problems here:

  1. has_block('gallery', $post->post_content) should never have worked as there is no block named gallery, the core block is named core/gallery
  2. While the gallery block used an attribute similar to the shortcodes in the past, modern gallery blocks are containers that contain image blocks

As a bonus, the code in your question loads full sized images, I was surprised to see the images load in line by line on a 1Gbit Fibre connection! ( Or that a realty site would disable right click and drag/drop when sharing photos of a property with a spouse via would be super important ).

Instead, I'm not seeing anything in the working version that can't be done via CSS to the standard gallery markup.

If the goal is to only show the first 9 photos until a button is pressed this can be done with CSS and a small amount of javascript, and a quick PHP filter in multiple ways.

E.g. adding a button on the end of the block markup:

add_filter( 'pre_render_block', 'my_pre_render_block', 10, 2 );
function my_pre_render_block( $pre_render, array $parsed_block ) {
    if ( $parsed_block['blockName'] === 'core/gallery' ) {
        return $pre_render . '<button>Show More</button>';
    }
    return $pre_render;
}

Or adding a collapsed-gallery class to the gallery blocks by default:

add_action( 'render_block_data', 'my_render_block_data', 1, 3 );
function my_render_block_data( array $parsed_block, $source_block, $parent_block ) : array {
    if ( $parsed_block['blockName'] === 'core/gallery' ) {
        if ( ! isset( $parsed_block['attrs']['className'] ) ) {
            $parsed_block['attrs']['className'] = '';
        }

        $parsed_block['attrs']['className'] = trim( $parsed_block['attrs']['className'] . ' collased-gallery' );
    }
    return $parsed_block;
}

At this point hiding everything but the first 9 items in the gallery is trivial:

.collapsed-gallery > * {
    display: none;
}

.collapsed-gallery > *:nth-child(1),
.collapsed-gallery > *:nth-child(2),
.collapsed-gallery > *:nth-child(4),
.collapsed-gallery > *:nth-child(5),
.collapsed-gallery > *:nth-child(6),
.collapsed-gallery > *:nth-child(7),
.collapsed-gallery > *:nth-child(8),
.collapsed-gallery > *:nth-child(9) {
    display: block;
}

A bit of JS to toggle the collapsed-gallery class when the button is pressed is all that's left, and this version if future-proof as it doesn't re-render the gallery blocks HTML from scratch. It even has better performance and accessibility!

This is one example but there are hundreds of other ways to do it, as well as more concise versions of the above.

3
  • Thank you Tom! I've amended my original post with some added questions, I tried to add them in the comment here but that didn't show very cleanly May 25, 2023 at 13:31
  • @ArtinFlight you should look into block styles, that would allow you to set a html class on a block using a button in the sidebar. Then you can search for that class in the my_render_block_data function I mentioned, and use the class in the CSS, and to only append the button if my_pre_render_block and $parsed_block contain that class
    – Tom J Nowell
    May 25, 2023 at 13:33
  • take a look at developer.wordpress.org/reference/functions/…, by default there's an is-style-{stylename} class that would be auto-added if used. This is how plugins like Jetpack implement Tiled galleries without adding extra blocks. Block variants is a more advanced version of this
    – Tom J Nowell
    May 25, 2023 at 13:34

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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