Loading all images of a project into a Fancybox-slider (but only displaying the first image on the homepage)

This is an extension of a question I previously asked here in the forum. I would like to set up a slider which lets the user cycle through all the images of a project, while only the first image of each project is being displayed on the homepage itself. The slider should appear on top of the entire page (rather than loading a separate page for each project which contains the slider) once the user clicks on a project’s image.

The forum kindly recommended my a variety of slider plugins to accomplish this. I am working with the Fancybox slider (http://fancyapps.com/fancybox/3/). I have managed to set up the slider successfully, it is now part of my showcase-snippet. The part of the snippet which enables the slider looks like this:

<div class="project-wrapper">

	<div class="flex-grid-thirds">

		<?php foreach($projects as $project): ?>

		  <div class="col">

		  	<a href="#" class="project-title">
		  		<?= $project->title()->html() ?>
				</a>

				 <?php if($image = $project->images()->sortBy('sort', 'asc')->first()): $thumb = $image; ?>

				 		<a href="<?= $thumb->url() ?>" data-fancybox="images">
							<img src="<?= $thumb->url() ?>" alt="Thumbnail for <?= $project->title()->html() ?>" class="" />
				 		</a>

	        <?php endif ?>

		  </div>

		<?php endforeach ?>

	</div>

</div>

This works in so far as it loads the first image of a project, puts it into my grid (on the homepage) and lets the user click on in to open the fancybox-slider. What it doesn’t do yet, is load the other images which were put into the project in the panel. How can I do that? The homepage should continue to only display the first image of each project but with the slider the user is supposed to be able to cycle through all images of each respective project.

Just load the images with $project->images() and iterate over the collection.

Look: https://getkirby.com/docs/cheatsheet/page/images

Also a nice gallery slider… small, no dependencies (no jQuery) and mobile ready: https://feimosi.github.io/baguetteBox.js/

That will then show all images, which is not what @JoSch wants. He wants to show only the first image.

Maybe you can loop through all images, and only put the image tag in for the first image, then hide the links, or something like this.

Another option would be to load the other images via Ajax.

I don’t think we have to go through all that again, because that’s already in the post @JoSch referred to :wink:.

Hmm, render the normal Fancybox markup:

<div>
<a data-fancybox="gallery" href="big_1.jpg"><img src="small_1.jpg"></a>
<a data-fancybox="gallery" href="big_2.jpg"><img src="small_2.jpg"></a>
<a data-fancybox="gallery" href="big_3.jpg"><img src="small_3.jpg"></a>
</div>

and then hide all but not the first.

div > a:not(:first-child) {
display: none;
}

maybe you don’t need the <a href> part for all but the first one.

Hm, I think it would be better not to load all images at once and then hide them visually, but only load them if someone clicks on the link to the next image.

Thanks for the quick response, to both of you.

I did make some progress loading the images via $project->images(). I’m declaring a variable first in my snippet:

<?php
    $projectImages = $project->images();
?>

Then I use it to create links for the fancybox-slider to cycle through. I also call a thumbnail of the each project to be displayed on the homepage itself. Only issue now is, that when I open the slider by clicking on any image of any project, that slider cycles through ALL images of all projects instead of only the images of the respective project which the clicked image belongs to. This is the current version of my snippet:

<div class="flex-grid-thirds">

	<?php foreach($projects as $project): ?>

		<?php
	    $projectImages = $project->images();
    ?>

	  <div class="col">

			 <?php if($image = $project->images()->sortBy('sort', 'asc')->first()): $thumb = $image; ?>

			 		<a href="<?= $thumb->url() ?>" data-fancybox="images">
						<img src="<?= $thumb->url() ?>" alt="Thumbnail for <?= $project->title()->html() ?>" class="" />
			 		</a>

			 		<?php
    				foreach($projectImages as $image): 
  				?>

  					<a href="<?php echo $image->url() ?>" data-fancybox="images"></a>

			 	<?php endforeach ?>

        <?php endif ?>

	  </div>

	<?php endforeach ?>

</div>

Also, the slider shows the first image of every project twice, because it loads the thumbnail as well as the image the thumbnail is created from.

I think each gallery probably should have it’s own data-attribute, not sure.

you can clean up alot in your code…

<?php // no need to open up php tags many times
foreach($projects as $project):
  // what's the sense of using $projectImages once..
   $projectImages = $project->images();
 ?>

// you can just use $image right away
$thumb = $image;

// this should resolve in no display as nothing between "a" has been declared
<a href="<?php echo $image->url() ?>" data-fancybox="images"></a>

You first get the first image, then you loop through all images, so in your example above, you would have to exclude the first image from the image loop.

foreach($projectImages->not($image) as $img): 

Here is a working alternative (including a counter for each group: data-fancybox="gallery-<?= $projects->indexOf($project) ?>"):

<div class="flex-grid-thirds">
  <?php foreach($projects as $project): ?>
      <div class="col">
        <?php 
        $projectImages = $project->images();
        foreach($projectImages as $projectImage):
        ?>

        <a href="<?= $projectImage->url() ?>" data-fancybox="gallery-<?= $projects->indexOf($project) ?>">
          <?php if($projectImage == $projectImages->first()): ?>
            <img src="<?= $projectImage->url() ?>" alt="Thumbnail for <?= $project->title()->html() ?>" class="" />
          <?php endif ?>
        </a>

      <?php endforeach ?>
    </div>
  <?php endforeach ?>
  
</div>
1 Like

Wow, thanks, your alternative works super.

Only issue now is that the custom option which I had set up for the fancybox-slider don’t apply anymore to the slider which is opened upon clicking the images. I had set it up like this:

  <script type="text/javascript">

    $().fancybox({

      selector        : '[data-fancybox="images"]',

      thumbs          : false,

      hash            : false,

      loop            : true,

      keyboard        : true,

      toolbar         : false,

      animationEffect : false,

      arrows          : true,

    });

  </script>

Do you know by any chance how to simply set the options for the fancybox-slider globally for the entire site so they apply to all future sliders on the site?

EDIT: Found out that global options can be set for fancybox by calling the default settings and changing them for the entire instance, like this:

<script type="text/javascript">
	
$.fancybox.defaults.loop = "true";

</script>
  <script type="text/javascript">

   $("[data-fancybox]").fancybox({

     thumbs          : false,

     hash            : false,

     loop            : true,

     keyboard        : true,

     toolbar         : false,

     animationEffect : false,

     arrows          : true,

   });

 </script>
1 Like

Cool, thanks again. Much :heart: for all the help.

1 Like