Skip to main content
adding navigation icons

Adding next and previous images to either sides of Galleria slideshow & adding responsiveness

JQuery has made our lives easier with it's vast plugin repository (so is Drupal). The popular jQuery plugins makes their way into Drupal with an easy to configure modules. One such is galleria, that integrates well with views to quickly create an image slideshow.

We recently had a requirement to show the next and previous images attached to either sides of the currently visible galleria slideshow image, which isn't supported by galleria out of the box. Understandably, addressing the needs of people all over the globe may not be possible for these open-source projects, but they do catch-up by exposing an API that we could use to tailor the functionality for our application.

We also wanted the galleria slideshow to be responsive (again, which is not supported out the box as of this writing). To be precise: we want the galleria to occupy full width of the screen, if the display port width is below a threshold limit (say 900px) and want it to be back to it's original width if the display port width goes above the threshold. Here is how we achieved both functionality:

/* It is assumed that the threshold width is also the standard width of the Galleria slideshow.. Which means, on a display of width 1024px, the galleria would take the center stage with a width of 900px and previous/next images on either sides. On responsive mode [when browser width reduced below threshold], galleria will take a 100% width, with NO previous or next images visible */

var _window_threshold_width = 900;

jQuery(window).ready(function() {
  /* Tweak to load previous & next images on the left/right of current image */
  Galleria.ready(function() {
    _responsive_galleria_resize(); /* Call this on page-load, so that if width is < threshold on load, galleria adapts */

    /* We will bind to the loadfinish API event, that is triggered just before the active image being shown is going to be replaced with another image with a slide effect. It is called every time the slide transition is about to occur. */

    this.bind('loadfinish', function(e) {
         var _galleria = this;
         setTimeout(function() {
            /* cleanup old tags added by us (if any); we will re-add it */

            jQuery('#gallery-img-pre').remove();
            jQuery('#gallery-img-post').remove();
            jQuery('#gallery-img-pre-overlay').remove(); /* The overlay part is optional -- we added this over the prev/next image for a transculent effect over the images appearing on either sides */
            jQuery('#gallery-img-post-overlay').remove();
            var previous_image = _galleria.getData(_galleria.getPrev());
            var next_image = _galleria.getData(_galleria.getNext());
            if (jQuery(e.imageTarget).position()) { /* e.imageTarget is the <img> tag, that is visible currently on galleria */
               jQuery(e.imageTarget).before('<img id="gallery-img-pre" src="' + previous_image.image + '" />');
               jQuery('#gallery-img-pre').css('margin-left', '-' + (_window_threshold_width - jQuery(e.imageTarget).position().left) + 'px');
               jQuery(e.imageTarget).after('<img id="gallery-img-post" src="' + next_image.image + '" />');
               jQuery('#gallery-img-post').css('margin-left', (jQuery(e.imageTarget).position().left + _window_threshold_width) + 'px');
               

               /* The overlay part is optional -- we added this over the prev/next image for a transculent effect over the images appearing on either sides */    
               jQuery(e.imageTarget).before('<div id="gallery-img-pre-overlay"></div>');
               jQuery('#gallery-img-pre-overlay').css('margin-left', '-' + (_window_threshold_width - jQuery(e.imageTarget).position().left) + 'px');
               jQuery(e.imageTarget).after('<div id="gallery-img-post-overlay"></div>');
               jQuery('#gallery-img-post-overlay').css('margin-left', (jQuery(e.imageTarget).position().left + _window_threshold_width) + 'px');
            }
         }, (jQuery(window).width() - _window_threshold_width)/2); /* This timeout is essential to make a "seamless" transition effect & makes illusion that the images on either sides are actually attached to the left & right of current image */
    } /* ends .bind('loadfinish'); */
  }); /* ends Galleria.ready() */
}); /* ends jQuery(window).ready() */

/* Function to make the Galleria responsive (full width) & to reset it back to normal state */
function _responsive_galleria_resize() {
  var ref_width = 900; /* Feed in your Galleria's width */
  var ref_height = 414; /* Feed in your Galleria's height */
  var ht = ref_height;
  if ((jQuery(window).width() < _window_threshold_width) {
    /* If you have reached here, it means.. current window viewport width is < threshold. So, find the reduced height of the galleria w.r.t current window width, maintaining the aspect ratio */
    ht = jQuery('.galleria-stage').width();
    ht = parseInt(ht * (ref_height / ref_width));
  }
  jQuery('.galleria-images').style('height', ht + 'px', 'important'); /* .style (!important) is not supported out of the box - refer to http://stackoverflow.com/a/8894528 to implement it */
  jQuery('.galleria-images > .galleria-image').style('height', ht + 'px', 'important');
  jQuery('.galleria-container').style('height', ht + 'px', 'important');
  jQuery('.galleria-image img').style('height', ht + 'px', 'important');
  jQuery('.galleria-info').style('height', ht + 'px', 'important');
}

/* Responsiveness: Trick to auto-center & reload galleria on window resize */
var _window_width = jQuery(window).width();
jQuery(window).resize(function() {
  if (jQuery(window).width() != _window_width) {
      _window_width = jQuery(window).width();
      var g = jQuery('#galleria-1').data('galleria'); /* Note: this may not be very reliable, but it works for us */
      /* The trick we'll employ is that: we will alter the styling of galleria, which would be in effect after next slideshow image has loaded.. But, without waiting, we're going to force reload with some timeouts */
      if (g) {
        g.setOptions('transition', 'flash').setOptions('transitionSpeed', '20').resize(); /* Change the transition style temporarily to quickly reload galleria */
        setTimeout(function() {
          g.show(g.getIndex()); /* Actual reload-galleria call */
        }, 100);
        setTimeout(function() {
          g.setOptions('transition', 'slide').setOptions('transitionSpeed', '400');
        }, 600); /* Reset transition after all the reloading/redrawing is done */
        _responsive_galleria_resize(); /* The resize function */
      }
  }
});

As you could notice, most of the functionality is explained with inline comments wherever required. Let us know if this works for you or if you want to suggest a bettter approach to achieve the functionality. See it in action here.

Comments

Chad (not verified)

Sat, 03/16/2013 - 15:17

I recently had to do something similar using Galleria/Drupal. I never thought of a pure 100% JS solution, but nice work.

If curious as to my approach, I took advantage of the "previous" and "next" text links to go from one image to another and used CSS to use images in place of the text.

Add new comment

The content of this field is kept private and will not be shown publicly.

Plain text

  • No HTML tags allowed.
  • Lines and paragraphs break automatically.
  • Web page addresses and email addresses turn into links automatically.