Best way to make an inline gallery with a custom kirbytag?

Hi there! I have been trying to figure out how to make inline galleries that appear within the main content area. I would love it if they could be as simple to make (while using the panel) as inserting a single image is. This solution needs to be applicable for any blog article page, and I do not know how many galleries will be needed for each article: some many need several, others none. But they will always need to appear within the text area, with text before and after them. For this reason I prefer a kirbytag-like approach over a page-builder style approach.

As far as file organization goes, I am have two ideas, and am equally partial to either at the moment:

  1. Store all the gallery images adjacent to the actual blog article page so they appear in sidebar’s file area. Then use a custom kirbytag to call specific images per slideshow, and somehow splice them into an array based on comma-separation. So using the custom kirbytag within the panel text may look like (gallery-tag: image1, image 2, image3) and then later in the text, another gallery might be called as such (gallery-tag: image4, image5, image6, image7, image8).

  2. …or… Create a subpage per gallery, as children of that blog article page. Each gallery subpage will hold its own images. The custom kirbytag will reference the name of the gallery subpage when invoked, and within the kirbytag code, know to access the images as an array. In this case, using the custom kirbytag within the panel text would be more like (gallery-tag: Gallery1) which would still result in all 3 of the associated images being called.

My problem is building a kirbytag that does either of these! In the documentation, it only shows how to build a kirbytag that acts as a link. I haven’t been able to figure this out, or find other forum questions specifically citing how to do an inline gallery from scratch, so am hoping it’s possible! Can anyone help or point me in the right direction?

Many thanks in advance!

Here is an example, don’t know if it is still working , but it may be helpful as a starting point.

I think your approach is very error prone not just for the end user but also for you when you want to program this functionality.
If you ask me I would suggest you the modules plugin. This approach comes really near to your #2 solution.

@texnixe Thanks, I had looked at that example earlier, I will delve in to it deeper, maybe it will work.

@Andi-Lo Which “modules plugin” exactly do you mean? Is there a place I can find it? Thanks!

You can find the Modules plugin on GitHub. Let me know if you have any questions.

@lukasbestle Thanks for this! The Modules plugin seems like it will work to solve my problem. However, I can’t get it to work properly for me. I also would like to use the Modules Field Plugin which is mentioned in the readme, but first I am just trying to get the Modules plugin to work on its own.

I tried both ways the readme suggests in the “Creating modular content in the Panel”. I tried the second approach first, as it said it was “recommended”, but it resulted in showing none of my existing fields whatsoever in the panel for what should be the parent of the Modules subpage.

So I then tried the first approach listed in the readme, which involved changing only one blueprint file, with just adding two lines. Trying to troubleshoot, I figured there would be less chance of errors. This approach involves adding the modules to the list of available templates for subpages. I followed the instructions exactly, and would then expect to be able to add new subpages, and choose a template for them that would be one of the module templates I referenced. However, it is not giving me these module templates as options when I want to create a new subpage.

Below is the part of the blogarticle.yml file where I list the modules as sub-page templates, exactly as explained in the readme’s first approach. I only ever need modules in pages using my “blogarticle” blueprint/template, so am only interested in referencing/adding them there. (I also include the code in that I wrote for automatically building a certain sub-page for each blogarticle page called “Definitions”. I only include this in case it is a known issue that gets in the way of modules. I tried removing it though, and it did nothing to fix my modules issues.)

//subpage settings
pages: 
  template: 
    - module.text
    - module.gallery
  build:
    - title: Definitions
      uid: definitions
      template: definitions
      num: 1

In my blogarticle.php I have inserted the code for calling the modules, where I want them to appear between other parts of the page (populated by fields in the panel):

<?php echo kirbytext($page->intro()) ?>

<?php $page->modules() ?>

<?php echo kirbytext($page->text()) ?>

I also have created and placed all the files called for in the readme. I am attaching a screenshot of my file structure. I am using the exact files from the Module Plugin Demo branch on GitHub, both for troubleshooting with, and because I hopefully can just use them (since all I need for the purpose of modules is switching between text and galleries!).

I am not sure what to do next, I would expect that newly created pages using the blogarticle’s template would allow me to create subpages for text and galleries within the panel… Is this in fact the expected behavior? If not, how to use modules? Or if so, any idea what is happening to prevent this?

Many thanks!

Yes, if everything is correct, you should be able to create subpages of both module types. It should not interfere with the subpage builder.

Have you added the modules plugin in the plugins folder and made sure to call it modules?

I have actually decided to continue pursuing my original plan of calling the images for each gallery from individual subpages of the blogarticle page I want the gallery to appear in. I started writing a kirbytag to be able to call them inline. I based it off of the “downloads” example in the documentation.

Here is my code:

<?php

kirbytext::$tags['gallery'] = array(
  'html' => function($tag) {

    $gallerypage = $tag->attr('gallery');

    $html .= '<ul>';

    foreach($tag->page()->children($gallerypage)->images() as $slide) {
      $html .= '<li>';
      $html .= '<img src="' . $slide->url() . '">';
      $html .= '</li>';
    }

    $html .= '</ul>';

    return $html;

  }
);

However, it isn’t paying attention to the actual subpage I tell it to get the images from. In my text in the panel I can enter (gallery: Doodles) and it will just fetch all the images associated to any subpage. And when I add a second gallery, e.g. (gallery: Paintings) it will do the exact same, resulting in two sets of all the images.

I know I read about others having a similar problem with the Kirby Gallery Field, here:
https://forum.getkirby.com/t/kirby-gallery-field/4636/18

…so I am hoping this can be solved some way! The Kirby official documentation for How to create custom kirbytags even says “of course you can extend this to generate entire galleries…” so there must be a way. Any help with this issue is VERY APPRECIATED!!! Thanks so much in advance! :heart_eyes:

children() does not accept a parameter, you can use find() instead:

foreach($tag->page()->children()->find($gallerypage)->images() as $slide) {
...
}

Thanks @texnixe for your help, but that just broke it… When I add that code instead, it is not showing any images whatsoever.

My latest approach has been trying the first of my approaches mentioned in my original question: listing the images inline per gallery. Whenever I called the gallery tag within the panel text, though, it produced every image in the page’s sidebar. I found this suggestion to split them:

$images = explode(",", $tag->attr('image_gallery'));

as described here:
https://forum.getkirby.com/t/kirbytext-inline-gallery/510/7

If I only try to call the names of images, this works to pull just the images that were actually mentioned in the tag! However, I can’t figure out how to get it to to show the images themselves! I tried I have tried adding ->toFile() to either place that $slide appears, but both changes resulted in nothing showing from the fields that the gallery tags were called.

Here is my full code with (without ->toFile() anywhere since it was breaking things):

<?php kirbytext::$tags['gallery'] = array( 'html' => function($tag) { $images = explode(",", $tag->attr('gallery')); foreach ($images as $slide) { $html .= '
  • '; $html .= $slide; $html .= '
  • '; } return $html; } ); Any ideas how I can use the `explode ( ... )` suggestion (or another way) but get images to show instead of text? Thanks so much for all your help with this everyone!

    If you are still interested in the original tag above, it just needs some modifications:

    <?php
    
    kirbytext::$tags['gallery'] = array(
      'html' => function($tag) {
    
        $gallerypage = $tag->attr('gallery');
        $html = '';
        if($page = $tag->page()->children()->find($gallerypage)) {
    
          $html .= '<ul>';
    
          foreach($page->images() as $slide) {
            $html .= '<li>';
            $html .= '<img src="' . $slide->url() . '">';
            $html .= '</li>';
          }
    
          $html .= '</ul>';
        } 
          return $html;
      }
    );
    

    And here the code for your second option:

    <?php
    
    kirbytext::$tags['gallery'] = array(
      'html' => function($tag) {
        // get the page
        $page = $tag->page();
       
        // get the array of images, make sure to remove any whitespace using trim
        $images = array_map('trim', explode(',', $tag->attr('gallery')));
        $html = '';
          // loop through the image array
          foreach ($images as $slide) {
              // get the image
              $image = $page->image($slide);
              $html .= '<li>';
              $html .= '<img src="' . $image->url() . '">';
              $html .= '</li>';
           }
    
          return $html;
    
      }
    );
    

    Please not that you have to declare a variable (in this case $html) first before you can add to it:

    $html = '';
    $html .= 'something';
    
    1 Like

    @texnixe Thank you so very much, both methods are working now! :grinning: Hopefully this can help some others in future, too!

    One strange thing is happening though. I built a galleries.yml blueprint, for the second method, so I can add a subpage with the galleries.yml template. Then I add the images for the gallery to this new subpage. I want them to be able to have captions, so I specified a caption field and an alt text field in the galleries.yml …but those fields won’t show up in the panel. Here’s the relevant galleries.yml code:

    //file settings
      type: 
        - image
      fields:
        caption:
          label: Caption
          type: textarea
        alttext:
          label: Alternate text
          type: text
          placeholder: Brief description of the image
    

    The alt text and caption fields I added for files of the blogarticle page (method 1) are appearing perfectly, and I copied the above text originally from the functioning blogarticle.yml file into the galleries.yml file. So I am not sure what the issue is…

    Thanks for all your help!

    Don’t know if that’s a copy and paste error, but the files setting is missing:

    //file settings
    files:
      type: 
        - image
      fields:
        caption:
          label: Caption
          type: textarea
        alttext:
          label: Alternate text
          type: text
          placeholder: Brief description of the image
    

    Other than that it looks alright.

    BTW: I modified the subpage option above and added an if-statement to make sure the page exists before calling the image() method on it.

    The other tag would also need to check if the array is not empty.

    You’re right, I must have missed that line when I copied and pasted into galleries.yml. Fixed now. Thanks so so much for helping; I am really impressed with the Kirby support!