Thursday, April 1, 2010

jQuery Image Gallery Plugin with Slideshow functionality

In my ongoing cavalcade on JavaScript/jQuery Web Image tools I decided to design a very useful and commonly used tool; a very easy to use Image Gallery/Slideshow Plugin. There are a plethora of JavaScript/jQuery Image Gallery tools you can find on internet, but for most of them you will have to pay for the source code. Though my plugin may not be that customizable but hey, it does gets the job done with minimal effort. It also features a Slideshow tool and controls to navigate through all the images in the gallery. You can tweak the CSS file to match the color and styling of your website. If you want to use it in it’s own style, it’s just a plug and play feature to add on your website. It isn’t that bad? Is it, plus FREE!!!

Why should you use this Image Gallery Plugin:

  1. Zero coding required, just plug-n-play.
  2. Works on any screen size.
  3. Works with images of any size, resolution or aspect ratio.
  4. No images used in the layout, hence faster to load.
  5. Compatible with all the modern browsers.
  6. Users can navigate between images using the Image Gallery List or the Navigation buttons.
  7. Users can set the Slideshow speed during plugin initialization.

This is how the tool looks like in action:

jQuery Image Gallery Plugin

To begin with, first you need to add links for script reference to the latest jQuery code, ImageGallery.js file (provided below) and ImageGallery.css stylesheet (provided below) in the head section of your page. To use this plugin you just need to create a div container in your HTML page and put all the images in there. You can apply styling to your container in any way you want to. To assign Image Gallery event to all the images, you just need to use the jQuery plugin on the image container as shown in example below in the page load event.

      Here in this sample HTML code I have used a pic_container class for my image div container (CSS in the head section). Then to assign the Image Gallery plugin in the $(document).ready() function I have used jQuery class selector to assign plugin to my container as $(".pic_container").ImageGallery(3000);, where the values inside ImageGallery() function is the time delay in milliseconds for the Slideshow (1000ms = 1sec).

      Including this plugin on your existing page you’ll only require the 2 links to jQuery (.js) files and the link to Image Gallery stylesheet (ImageGallery.css) file. To assign the plugin to your div tags, you will need to use the page load function ($(document).ready()) as shown below:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<title>jQuery Image Gallery by Abhinay Rathore</title>
<script src="http://code.jquery.com/jquery-latest.js"></script>
<script src="ImageGallery.js"></script>
<link href="ImageGallery.css" rel="stylesheet" type="text/css" />
<script type="text/javascript">
/* Developed by: Abhinay Rathore [web3o.blogspot.com] */
//////////////////[ Page Load Function ]///////////////////////
$(document).ready(function(){
      //Add ImageGallery function to all the 'pic_container' containers
      //SlideShow Time Interval can be passed as function argument (1000 = 1sec)
      $(".pic_container").ImageGallery(3000);
});
/////////////////[ End Page Load Function ]///////////////////
</script>

<style type="text/css">
.pic_container {
      border: 1px solid #9CF;
}
.pic_container img{
      border: 1px solid #9CF;
      width: auto; height: 100px;
      padding: 5px; margin: 5px;
      cursor: pointer;
}
</style>

</head>

<body>
<div class="pic_container">
<img src="BlueHills.jpg" />
<img src="Sunset.jpg" />
<img src="WaterLilies.jpg" />
<img src="Winter.jpg" />
<img src="liberty.jpg" />
<img src="goldengate1.jpg" />
<img src="city1.jpg" />
<img src="scene21.jpg" />
<img src="taj_mahal1.jpg" />
<img src="taj1.jpg" />
</div>
</body>
</html>

To include the Image Gallery plugin code you will need to create a separate ImageGallery.js file and put the following contents in there. The jQuery/JavaScript code in this file is pretty easy to understand and tweak around. The main event starts from the startGallery() function where all the controls and containers are added to the HTML page and Gallery List is populated at the bottom. displayPicture() function is used to display the Main Picture and needs to be called for any subsequent picture display calls. Slideshow is controlled by the three function defined under the Slideshow Functions section. Gallery List scrolling is handled by the separate set of functions defined under Gallery List Scroll Functions section. I have used minimal amount of well commented code to get the functionality working, so if you need extra features, you can always modify the code according to your needs.

Contents of ImageGallery.js file:
////////////////////////////////////////////////////////
// Developed by: Abhinay Rathore [web3o.blogspot.com] //
////////////////////////////////////////////////////////

//////////////////[ jQuery Plugin ]///////////////////////
jQuery.fn.ImageGallery = function(Time_Interval){
      //Assign Click event to all the images in the container...
      this.children("img").click(function(){ startGallery(this); });
      //Set SlideShow Time Interval
      if(!Time_Interval) SlideShow_Time_Interval = 3000;
      else SlideShow_Time_Interval = Time_Interval;
}
//////////////////[ END jQuery Plugin ]///////////////////////

//////////////////[ Global Variables ]///////////////////////
var Gallery = new Array();
var MaxPicWidth, MaxPicHeight, WindowWidth, WindowHeight, CurrentIndex, MaxIndex;
var GalleryListContainerWidth, GalleryListWidth, WidthDiff;
var SlideShow_Time_Interval;
var PageTitle;
/////////////////[ End Global Variables ]////////////////////

//////////////////[ Picture Gallery Functions ]///////////////////////
//This function initiates the Picture Gallery by loading all the containers and controls
function startGallery(id){
      //Scroll Page to top
      $('html,body').animate({scrollTop: 0}, 'fast');
     
      //Declare Global variables...
      WindowWidth = $(window).width();
      WindowHeight = $(window).height();
      MaxPicWidth = WindowWidth - 100;
      MaxPicHeight = WindowHeight - 170;
     
      //Create translucent background...
      var bg = document.createElement('div');
      bg.id = "Gallery_Background";
      document.body.appendChild(bg); //Attach background to the BODY
      $(bg).fadeTo('fast', 0.9);
     
      //Create Gallery Container with dimensions of the window...
      var container = document.createElement('div');
      container.id = "GalleryContainer";
      $(container).css({'width': WindowWidth, 'height': WindowHeight});
     
      //Create and attach the Gallery Close Button to the Container...
      var CloseButton = document.createElement('div');
      CloseButton.id = "GalleryCloseButton";
      CloseButton.innerHTML = "X";
      container.appendChild(CloseButton);
      $(CloseButton).click(function(){ stopGallery() }); //Attach Close event
     
      //Create and attach the container for Gallery Picture List
      var GalleryListContainer = document.createElement('div');
      GalleryListContainer.id = "GalleryListContainer";
      $(GalleryListContainer).css({'top': WindowHeight - 110, 'left': '50px',
                    'width': WindowWidth - 100 - 4, 'height': '100px'});
      container.appendChild(GalleryListContainer);
     
      //Create and attach the Gallery List to the Gallery List Container...
      var GalleryList = document.createElement('div');
      GalleryList.id = "GalleryList";
      GalleryListContainer.appendChild(GalleryList);
     
      //Create and attach the Gallery List Left Scroller to the Container...
      var GalleryListLeft = document.createElement('div');
      GalleryListLeft.id = "GalleryListLeft";
      $(GalleryListLeft).css({'top': WindowHeight - 110, 'left': '0px'});
      GalleryListLeft.appendChild(createSpanNode("&loz;"));
      container.appendChild(GalleryListLeft);
     
      //Create and attach the Gallery List Right Scroller to the Container...
      var GalleryListRight = document.createElement('div');
      GalleryListRight.id = "GalleryListRight";
      $(GalleryListRight).css({'top': WindowHeight - 110, 'right': '0px'});
      GalleryListRight.appendChild(createSpanNode("&loz;"));
      container.appendChild(GalleryListRight);
     
      //Create and attach the Gallery Controls Container to the Container...
      var ControlsContainer = document.createElement('div');
      ControlsContainer.id = "ControlsContainer";
      $(ControlsContainer).css({'top': WindowHeight - 145});
      container.appendChild(ControlsContainer);
     
      //Create and attach the Gallery Controls to the Controls Container...
      //First Image Control
      var First = document.createElement('div');
      First.id = "First";
      First.className = "button";
      First.innerHTML = "First";
      ControlsContainer.appendChild(First);
      //Previous Image Control
      var Prev = document.createElement('div');
      Prev.id = "Prev";
      Prev.className = "button";
      Prev.innerHTML = "&laquo;Prev";
      ControlsContainer.appendChild(Prev);
      //Play Pause Slideshow Control
      var Play = document.createElement('div');
      Play.id = "Play";
      Play.className = "button";
      Play.innerHTML = "Slideshow";
      $(Play).click(function(){ StartSlideShow(); });
      ControlsContainer.appendChild(Play);
      //Next Image Control
      var Next = document.createElement('div');
      Next.id = "Next";
      Next.className = "button";
      Next.innerHTML = "Next&raquo;";
      ControlsContainer.appendChild(Next);
      //Last Image Control
      var Last = document.createElement('div');
      Last.id = "Last";
      Last.className = "button";
      Last.innerHTML = "Last";
      ControlsContainer.appendChild(Last);
     
      //Create and attach the Main Pictire holder to the Container...
      var MainPicture = document.createElement('div');
      MainPicture.id = "GalleryMainPicture";
      container.appendChild(MainPicture);
     
      //Attach the Container to the BODY
      document.body.appendChild(container);
      //Disable Page Scroll
      $('html,body').css({'overflow': 'hidden'});
      //Add the Pictures to the Gallery List
      //This function returns the index of the clicked image
      var index = LoadPictures(id, GalleryList);
     
      //Display the clicked picture in the MainPicture box...
      displayPicture(index, true);
     
      PageTitle = document.title;
      document.title = "Image Gallery by Abhinay Rathore [web3o.blogspot.com]";
}
//Stops the Image Gallery when Close Button is clicked
function stopGallery(){
      Gallery = new Array(); //Clear the Gallery Array
      StopSlideShow(); //Stop Slideshow is it is running
      $("#GalleryContainer").children().remove(); //Remove all child nodes from Container
      $("#GalleryContainer").remove(); //Remove the Container
      $("#Gallery_Background").remove(); //Remove Gallery Background
      $('html,body').css({'overflow': 'auto'}); //Enable Page Scroll
      document.title = PageTitle;
}
//////////////////[ END Picture Gallery Functions ]///////////////////////

/////////////////[ Gallery List Picture collector Function ]///////////////////
//This function adds all the sibling images to the Gallery List and returns the
//index to the clicked image
function LoadPictures(id, GalleryList){
      var pics = $(id).parent().children(); //Get all the siblings of the clicked image
      var index = 0, i;
      for(i=0; i<pics.length; i++) //Iterate through all the siblings and add to the Gallery Array
      {
            var img = document.createElement('img'); //Create new image
            img.src = pics[i].src;
            img.name = i //Store Array index in the 'name' attribute of thumbnails
            Gallery[i] = pics[i].src; //Add image link to the Gallery Array
            if(pics[i] == id){ index = i; }  //Clicked Image index
            //Attach click event to the images...
            $(img).click(function(){ displayPicture(parseInt(this.name), true);});
            GalleryList.appendChild(img); //Add newly created image thumbnail to the Gallery List
      }
      MaxIndex = i - 1; //Max Index in the array
     
      //Assign click events to First and Last image control buttons
      $("#First").click(function(){ displayPicture(0, true); });
      $("#Last").click(function(){ displayPicture(MaxIndex, true); });
     
      //Calculate Gallery List width to compare with the Gallery List Container
      //If Gallery List Width is less then the Container Width then the
      //List Scroll controls are not displayed
      var GalleryListContainer = $("#GalleryListContainer");
      GalleryListContainerWidth = GalleryListContainer.width();
      var GalleryListContainerOffset = GalleryListContainer.offset();
      var lastChild = $("#GalleryList > img:nth-child(" + (i) + ")");
      var lastChildPosition  = lastChild.position();
      var lastChildWidth  = lastChild.width();
      var GalleryList = $("#GalleryList");
      var GalleryListOffset  = GalleryList.offset();
      GalleryListWidth = Math.round(GalleryListOffset.left + lastChildPosition.left + lastChildWidth - GalleryListContainerOffset.left + 5);
     
      if(GalleryListWidth > GalleryListContainerWidth){ //Attach mouse events to List Scroll Controls
            WidthDiff = GalleryListWidth - GalleryListContainerWidth;
            $("#GalleryListLeft").mouseover(function(){scrollGalleryList('L');});
            $("#GalleryListRight").mouseover(function(){scrollGalleryList('R');});
            $("#GalleryListLeft, #GalleryListRight").mouseout(function(){stopScrollGalleryList();});
      } else { //Hide List Scroll Controls
            $("#GalleryListLeft, #GalleryListRight").css({'visibility': 'hidden'});
      }
      return index;
}
/////////////////[ END Gallery List Picture collector Function ]///////////////////

//////////////////[ Display Picture Functions ]///////////////////////
//This function displays the Image at the given index in Gallery Array
function displayPicture(index, enableControls){
      CurrentIndex = index; //Set Current Index for Slideshow
     
      var MainPicture = $("#GalleryMainPicture");
      MainPicture.children().remove(); //Remove previous image
      var img = document.createElement('img'); //Create new image
      img.src = Gallery[index]; //Set new image source
      MainPicture.append(img); //Add newly created image to the MainPicture box
      var imgDim = PicDimensions(img) //Get image dimensions to fit in the MainPicture box
      $(img).css({'height': imgDim.height, 'width': imgDim.width}); //Set new image dimensions
      //Set new size and margins for the MainPicture box
      MainPicture.css({'height': imgDim.height, 'width':imgDim.width,
                              'left': LeftMargin(imgDim.width), 'top': TopMargin(imgDim.height)});
     
      //If not a Slideshow display: enable the Next/Prev image controls
      if(enableControls){ EnablePictureControls(index); }
     
      //Highlight selected picture under the Gallery List images
      highlightSelectedPic(index);
}
//This functions highlights the selected picture under the Gallery List images
function highlightSelectedPic(index){
      $("#GalleryList").children().fadeTo(0, 0.5); //Fade all the images in Gallery List
      var selectedChild = $("#GalleryList > img:nth-child(" + (index + 1) + ")");
      selectedChild.fadeTo(0, 1.0); //Highlight the selected image (at given index)
     
      //Calculate the image thumbnail position inside Gallery List to bring it in focus
      var GalleryList  = $("#GalleryList");
      var GalleryListContainer = $("#GalleryListContainer");
      var GalleryListContainerOffset = GalleryListContainer.offset();
      var GalleryListOffset  = GalleryList.offset();
      var selectedChildPosition  = selectedChild.position();
      var selectedChildWidth  = selectedChild.width();
      var leftEdge = Math.round(GalleryListOffset.left + selectedChildPosition.left);
      var rigthEdge = Math.round(GalleryListOffset.left + selectedChildPosition.left + selectedChildWidth);
     
      //Bring the selected picture into foucs in Gallery List
      if(rigthEdge > GalleryListContainerWidth){ //scroll left
            GalleryList.animate({left: '-=' + (rigthEdge - GalleryListContainerWidth - GalleryListContainerOffset.left + 5)}, 200);
      } else if(leftEdge < GalleryListContainerOffset.left){ //scroll right
            GalleryList.animate({left: '+=' + (GalleryListContainerOffset.left - leftEdge + 5)}, 200);
      }
}
//This function is used to enable the Next/Prev Image Controls
//based upon the index in Gallery Array
function EnablePictureControls(index){
      var Prev = $("#Prev"), Next = $("#Next");
      $("#Prev, #Next").css({'visibility': 'visible'});
      $("#First, #Last").css({'visibility': 'visible'});
      Prev.unbind('click'); //Unbind existing click events
      Next.unbind('click'); //Unbind existing click events
      if(Gallery.length == 1){ //If only one image, hide Next/Prev image controls
            $("#Prev, #Next").css({'visibility': 'hidden'});
            $("#First, #Last").css({'visibility': 'hidden'});
      } else if(index == 0){ //If first image displayed, hide Prev image control
            Prev.css({'visibility': 'hidden'});
            $("#First").css({'visibility': 'hidden'});
            Next.click(function(){displayPicture(index+1, true);});
      } else if(index == Gallery.length - 1){ //If last image displayed, hide Next image control
            Prev.click(function(){displayPicture(index-1, true);});
            Next.css({'visibility': 'hidden'});
            $("#Last").css({'visibility': 'hidden'});
      } else { //Show Next/Prev image controls
            Prev.click(function(){displayPicture(index-1, true);});
            Next.click(function(){displayPicture(index+1, true);});
      }
}
//////////////////[ END Display Picture Functions ]///////////////////////

//////////////////[ SlideShow Functions ]///////////////////////
var SlideShowIndex = 0;
function StartSlideShow(){ //Start SlideShow...
      //Hide Next/Prev and First/Last Image Controls
      $("#Prev, #Next").css({'visibility': 'hidden'});
      $("#First, #Last").css({'visibility': 'hidden'});
      //Change Play Button to Pause
      $("#Play").unbind('click');
      $("#Play").text('Stop Slideshow');
      $("#Play").click(function(){ StopSlideShow(); });
     
      var MainPicture = document.getElementById("GalleryMainPicture");
      //Set SlideShow index
      if(CurrentIndex == MaxIndex){ SlideShowIndex = 0; }
      else { SlideShowIndex = CurrentIndex + 1; }
      //Start SlideShow timer with time_interval specified above
      MainPicture.timer = setInterval(function() { PlaySlideShow(); }, SlideShow_Time_Interval);
}
function PlaySlideShow(){ //Switch SlideShow Image
      displayPicture(SlideShowIndex, false);
      SlideShowIndex += 1; //Step to next image
      if(SlideShowIndex > MaxIndex) SlideShowIndex = 0;
}
function StopSlideShow(){ //Stop SlideShow...
      var MainPicture = document.getElementById("GalleryMainPicture");
      clearTimeout(MainPicture.timer); //Clear SlideShow timer
     
      //Show Next/Prev and First/Last Image Controls
      $("#Prev, #Next").css({'visibility': 'visible'});
      $("#First, #Last").css({'visibility': 'visible'});
      //Enable Next/Prev Controls based upon the Current Index
      EnablePictureControls(CurrentIndex);
     
      //Change Pause Button to Play
      $("#Play").unbind('click');
      $("#Play").text('Slideshow');
      $("#Play").click(function(){ StartSlideShow(); });
}
//////////////////[ END SlideShow Functions ]///////////////////////

//////////////////[ Gallery List Scroll Functions ]///////////////////////
//Gallery List scrolling begins when the user takes the mouse over the
//Gallery List scroll controls and stops when the mouse moves out of the controls
function scrollGalleryList(dir){ //Start Scrolling the Gallery List
      var GalleryList = document.getElementById("GalleryList");
      //Start Gallery List Scroll timer
      GalleryList.timer = setInterval(function() { animateGalleryList(dir); }, 10);
}
function animateGalleryList(dir){
      var GalleryList = document.getElementById("GalleryList");
      var left = $(GalleryList).css("left"); //Get current left position
      if(left == "auto") left = parseInt(0); else left = parseInt(left.replace("px", ""));
      switch(dir) //shift the Gallery List to left/right based upon the direction
    {
            case "R": if(Math.abs(left) < WidthDiff) { $(GalleryList).css({'left': left-10}); }
                              else { stopScrollGalleryList(); }
                              break;
            case "L": if(left < 0) { $(GalleryList).css({'left': left+10}); }
                              else { stopScrollGalleryList(); }
                              break;
      }
}
function stopScrollGalleryList(){ //Stop Scrolling the Gallery List
      var GalleryList = document.getElementById("GalleryList");
      clearTimeout(GalleryList.timer); //Clear Gallery List Scroll timer
}
//////////////////[ END Gallery List Scroll Functions ]///////////////////////

//This function returns the display picture dimensions based upon the
//maximum picture hight and width according to the page size
function PicDimensions(pic){
      var d = new Dimensions();
      d.height = Math.min(MaxPicHeight, $(pic).height());
      d.width = Math.round($(pic).width() * d.height / $(pic).height());
      if(d.width > MaxPicWidth){
            d.width = MaxPicWidth;
            d.height = Math.round($(pic).height() * d.width / $(pic).width());
      }
      return d;
}
function Dimensions(){ //Dimensions class to hold width and height values
      var width; var height;
}

//This funcition creates a 'span' node with the provided text
function createSpanNode(text){
      var span = document.createElement('span');
      span.innerHTML = text;
      return span;
}

//These functions calculate the Left and Top margins for any div tag
//to center align them to the page based upon their width and height
//These functions are mainly used to center align the MainPicture box
function LeftMargin(width){
      return Math.round((WindowWidth - width)/2);
}
function TopMargin(height){
      return Math.round((WindowHeight - 150 - height)/2);
}

The CSS code for the Image Gallery plugin is pretty easy to modify. It does not use any images so it is faster to load as well but you can always add images to make it look prettier. To match the color and styling of your website you can tweak around this code on your own. The ID’s in CSS match with the ID’s in the jQuery code so it will be pretty easy to figure out the layout. Most of the dynamic styling is done in the startGallery() function where you can easily tweak them. Almost all of the elements are absolutely aligned and the positioning is decided by the dynamic jQuery code based upon the window dimensions. Create this ImageGallery.css file and link it in the head section of your page.

Contents of ImageGallery.css file:
#Gallery_Background{
      background-color: #DFDFDF;
      width: 100%; height: 100%;
      position: absolute;
      top: 0px; left: 0px;
}
#GalleryContainer{
      position: absolute;
      top: 0px; left: 0px;
}
#GalleryCloseButton{
      background-color: #fff;
      position: absolute;
      top: 5px; right: 5px;
      border: 2px solid #069; color: #069;
      font-family: "Arial Black", Gadget, sans-serif;
      font-size: large; line-height: 20px;
      width: 20px; height: 20px;
      text-align: center;
      cursor: pointer;
}
#GalleryMainPicture{
      background-color: #FFF;
      position: absolute;
      border: 3px solid #069;
      overflow: hidden;
}
#ControlsContainer{
      position: relative; text-align: center;
      margin: 0 auto;
}
#ControlsContainer .button{
      position: relative; display: inline-block;
      text-align: center; cursor: pointer;
      height: 25px; width: auto;
      background-color: #FFF;
      font-family: Verdana, Geneva, sans-serif;
      font-weight: bold; font-size: medium;
      line-height: 25px; color: #069;
      margin: 0px 5px 0px 5px; padding: 0px 5px 0px 5px;
      border: 2px solid #069;
      overflow: hidden;
}
#GalleryListContainer{
      background-color: #FFF;
      position: absolute; overflow: hidden;
      border: 2px solid #069;
}
#GalleryList{
      position: relative;
      background-color: #FFF;
      text-align: center;
      height: 100px; width: auto;
      white-space: nowrap;
      padding: 5px; margin: 0 auto;
      display: block;
}
#GalleryList img{
      margin: 0px 5px 0px 0px;
      height: 90px; width: auto;
      cursor: pointer;
}
#GalleryListLeft, #GalleryListRight{
      position: absolute;
      height: 104px; width: 50px;
      cursor: pointer; overflow: hidden;
      font-family: Verdana, Geneva, sans-serif;
      font-weight: bold; font-size: 126px;
      line-height: 90px; color: #069;
}
#GalleryListLeft span{
      margin-left: -5px;
}
#GalleryListRight span{
      margin-left: -55px;
}
#GalleryListLeft:hover, #GalleryListRight:hover{
      color: #09C;
}

Feel free to use or modify and play around with this code at your own risk and convenience. If you use this code on your website, please do provide due credits to me in the ImageGallery.js file (I guess that’s not too much to ask for).

No comments:

Post a Comment

Thanks a lot for your valuable comments :)