Tutorial: Object-Oriented Way of Creating a jQuery Image Slider

Table of Contents:

The purpose of this article is to demonstrate object-oriented design in JavaScript, by creating a jQuery powered image gallery script from scratch. Note that we are not creating a jQuery plugin, but simply using jQuery for DOM selection and manipulation. In the near future, this article might be updated to jQuery plugin version.



Demonstration: http://test.thecodecentral.com/demos/simple_gallery/
See it on GitHub: https://github.com/thecodecentral/Simple-Image-Slider

The Theory

The theory behind it is pretty simple. We first align a list of images side by side, this will allow us to create a long horizontal panel. Above the panel, we create a “windowed” area to show only part of the panel. We achieve this by setting style of the container element to overflow:none. Lastly, we implement JavaScript code to move the horizontal panel.

Creating the Object Blueprint

There’s no such thing really is class in JavaScript, so we will call it object blueprint for now. But for convenience, we will loosely refer this as class later on. We are going to create something like this,

  1. var SimpleGallery = function(){
  2.   //constructor
  3. };
  4. SimpleGallery.prototype = {
  5.   //implementation
  6. };

Once we have the blue print, we can create the gallery object like this,

  1. var gallery = new SimpleGallery();

If you are curious about how it works, here is a good read about applying OOP paradigm in JavaScript.

HTML/CSS Prototype

Before implementing the JavaScript further, we are going to create a quick prototype of the gallery. No JavaScript is involved in this step.

  1. <html>
  2.   <head>
  3.     <style type=”text/css”>
  4.       .simple_gallery{
  5.         width: 700px;
  6.         height: 400px;
  7.         position: relative;
  8.         overflow: hidden;
  9.       }
  10.       .simple_gallery .slide_panel{
  11.         position: absolute;
  12.         clear: both;
  13.         height: 400px;
  14.         width: 10000px;
  15.         left: 0;
  16.         top: 0;
  17.       }
  18.     </style>
  19.   </head>
  20.   <body>
  21.     <div id=”gallery” class=”simple_gallery” style=”display: none”>
  22.       <div class=”slide_panel”>
  23.         <img src=”images/1.jpg” alt=”Image 1″/>
  24.         <img src=”images/2.jpg” alt=”Image 2″/>
  25.         <img src=”images/3.jpg” alt=”Image 3″/>
  26.         <img src=”images/4.jpg” alt=”Image 4″/>
  27.         <img src=”images/5.jpg” alt=”Image 5″/>
  28.         <img src=”images/6.jpg” alt=”Image 6″/>
  29.         <img src=”images/7.jpg” alt=”Image 7″/>
  30.       </div>
  31.     </div>
  32.   </body>
  33. </html>

By this little amount of code, we already have a bare-bone version of the gallery we are trying to create. DIV.slide_panel is now scrollable. If you have Firefox browser with Firebug installed, you can scroll it by editing the left position of this DIV element. See a live demonstration here.

We are going to expand our JavaScript code based on this prototype gallery.

Coding the Gallery Script

Firstly, please have a look at the completed script to get an overview of what it looks like. The entire script seems long, but it is divided into many well defined code blocks, which can help you to understand the code better. The constructor now has been updated to initialize many object wide variables. You don’t need to know what these are, but just remember they will be used in some places within the class.

  1. //constrcutor
  2. var SimpleGallery = function(options){
  3.   this.renderToEl = null;
  4.   this.options = $.extend({
  5.     slidePanelClassName: ‘slide_panel’,
  6.     navLeftClassName: ‘nav_left’,
  7.     navRightClassName: ‘nav_right’,
  8.     slideClassName: ‘slide_block’, //class to determine the width of each slide,
  9.     itemRenderer: this.itemRenderer,
  10.     galleryRenderer: this.galleryRenderer
  11.   }, options);
  12.   //so on …
  13.   //see simple.gallery.js
  14. };

One thing may be confusing to new jQuery user is the using of $.extend. Here we use $.extend to merge options passed to the constructor with the default options inside of the constructor. For example, if we do

  1. new SimpleGallery({slideClassName: ‘slide_new’});

this.options.slideClassName will become ‘slide_new’, instead of the old value ‘slide_block’.

The rest is the class body, which are merely functions.

  1. SimpleGallery.prototype = {
  2.  getData:function(){
  3.   },
  4.   getCurrentSlide:function(){
  5.   },
  6.   getNumberSlides:function(){
  7.   },
  8.   getCurrentSlideData:function(){
  9.   },
  10.   render:function(toEl){
  11.   },
  12.   scrollTo: function(index){
  13.   }
  14.   //and so on …
  15. }

The Scroll to Function

I will focus on discussing the “scrollTo” function, which is the most important function in the class. This function is not hard to understand either. You can almost read it as plain English. The function take a parameter “index”, which is the slide number to scroll to. Please read the code comment for more explanations.

  1. /**
  2.  * Scroll to a slide. Index is 0 based.
  3.  */
  4. scrollTo: function(index){
  5.   //if it is scrolling, do nothing
  6.   if(this.isAnimating){
  7.     return;
  8.   }
  9.   //if index number is out of bound, i.e., invalid, do nothing
  10.   if(index < 0 || index >= this.numberSlides){
  11.     return;
  12.   }
  13.   //if index is the current slide, do thing
  14.   if(index == this.currentSlide){
  15.     return;
  16.   }
  17.   //if we can get to here, scroll to the appropriate slide
  18.   this.isAnimating = true;
  19.   this.slidePanel.show();
  20.   //store “this” context, in order to use it in the animation callback
  21.   var self = this;
  22.   //hide navigations first, then show after animation is completed.
  23.   this.navLeft.hide();
  24.   this.navRight.hide();
  25.   //finally, scroll to the image panel
  26.   this.slidePanel.animate({
  27.     left: (-(index * this.slideWidth)) + ‘px’
  28.   }, ‘slow’, function(){
  29.     //I can’t use this.currentSlide to access class variables, because I am inside of a callback function.
  30.     //”this” in this scope refers to this.slidePanel
  31.     //”self” refers to class instance
  32.     //so to access class variable, I use “self”, which is defined a few lines above
  33.     //we have scrolled to the designated slide, update current slide index
  34.     self.currentSlide = index;
  35.     //indicate that animation is done
  36.     self.isAnimating = false;
  37.     //handle how to display backward/forward button.
  38.     //For example, at the first slide, backward button is hidden; at last page, forward button is hidden.
  39.     self.showHideNav();
  40.     //to make this class even more customizable, we trigger a event
  41.     //when the animation is completed. you can fire more interest events.
  42.     //For example, when at first slide, trigger a ‘simple.gallery.at_first_slide’ event.
  43.     self.renderToEl.trigger(‘simple.gallery.animation_completed’);
  44.   });
  45. }

Once the scrollTo function is implemented, we just need to add navigation buttons, then we have an image slider. “setupNav” and “showHideNav” functions will take care adding and displaying the navigation buttons.

The render() Function

The “render()” function is responsible to display the image slider. We are going to go over this function shortly, but now, just have a quick look at the code.

  1. /**
  2.  * render gallery to the targeted jQuery element
  3.  * @param toEl jQuery element
  4.  */
  5. render:function(toEl){
  6.   this.renderToEl = toEl;
  7.   this.renderToEl.append(this.options.galleryRenderer.apply(this, [this]));
  8.   var panel = toEl.find(‘.’ + this.options.slidePanelClassName);
  9.   panel.empty();
  10.   for(var i in this.data){
  11.     var slide = this.options.itemRenderer.apply(this, [this.data[i]]);
  12.     panel.append(slide);
  13.   }
  14.   this.slidePanel = panel;
  15.   this.slideWidth = panel.find(‘.’ + this.options.slideClassName).width();
  16.   panel.width(this.numberSlides *  this.slideWidth);
  17.   panel.show();
  18.   this.setupNav();
  19.   this.scrollTo(0);
  20. }

It take an argument, which is an jQuery element that you want the slider to be appended into. This function should be pretty easy to understand, except two places:

  1. this.options.galleryRenderer.apply(this, [this])
  2. this.options.itemRenderer.apply(this, [this.data[i]])

Above code is roughly the same as below,

  1. this.options.galleryRenderer(this)
  2. this.options.itemRenderer(this.data[i])

Then, you might ask, why would I use “apply” instead of calling “galleryRenderer” and “itemRenderer” directly? To answer this question, we need to understand what “apply” does. If you are not familiar with the scope problem in JavaScript, here is a very good read. So basically “apply” will correct the scope of two renderers functions (see below for explanation of what renderer is). Still remember this.options = $.extend({}, options) in the constructor? After that call, this.options is assigned to an object. So calling this.options.galleryRenderer(this), will be in the scope of “options” object, not the SimpleGallery object; but this is not what we want. We use apply to fix this problem.

Notice that I put two render functions in the this.options variable. This will provide maximum flexibility. This way, either renderer can be overwritten and customized. Please see final demonstration page for how to customize the renderer.

Instantiating the Slider Object (Directly)

Once the slider class is done, we can instantiate it. We can do it programmatically like this,

  1. var galleryData = [
  2. { url=”images/1.jpg”, title=”Image 1″, description=”Description of the image 1″},
  3. { url=”images/2.jpg”, title=”Image 2″, description=”Description of the image 2″},
  4. { url=”images/3.jpg”, title=”Image 3″, description=”Description of the image 3″},
  5. { url=”images/4.jpg”, title=”Image 4″, description=”Description of the image 4″},
  6. { url=”images/5.jpg”, title=”Image 5″, description=”Description of the image 5″},
  7. { url=”images/6.jpg”, title=”Image 6″, description=”Description of the image 6″},
  8. { url=”images/7.jpg”, title=”Image 7″, description=”Description of the image 7″}
  9. ];
  10. var gallery = new SimpleGallery();
  11. gallery.setData(galleryData).render($(‘#gallery’));

Instantiating the Slider Object (With a Crawler)

Better yet, we can create a slider based on existing images in the document. I have created a simple image crawler, which can extract image information and construct data for the slider class.

  1. /**
  2.  * Select all images, turn them into list of
  3.  * @param el jQuery element
  4.  **/
  5. var SimpleGalleryCrawlerGeneric = function(el){
  6.   this.el = el;
  7. };
  8. SimpleGalleryCrawlerGeneric.prototype = {
  9.   /**
  10.    * extract images from the given element
  11.    * @param el jQuery element
  12.    * @return image URLs and other information
  13.    */
  14.   getData:function(){
  15.     var data = [];
  16.     var self = this;
  17.     this.el.find(‘img’).each(function(i){
  18.       var img = $(this);
  19.       var item = {
  20.         ‘url’:img.attr(‘src’),
  21.         ‘title’:img.attr(‘alt’),
  22.         ‘description’: img.attr(‘title’)
  23.       };
  24.       data.push(item);
  25.     });
  26.     return data;
  27.   }
  28. };

Now, let’s say the original page contains the following,

  1.  <ul id=”gallery_data”>
  2.       <li><img src=”images/1.jpg” alt=”Image 1″ title=”Description of the image 1″/></li>
  3.       <li><img src=”images/2.jpg” alt=”Image 2″ title=”Description of the image 2″/></li>
  4.       <li><img src=”images/3.jpg” alt=”Image 3″ title=”Description of the image 3″/></li>
  5.       <li><img src=”images/4.jpg” alt=”Image 4″ title=”Description of the image 4″/></li>
  6.       <li><img src=”images/5.jpg” alt=”Image 5″ title=”Description of the image 5″/></li>
  7.       <li><img src=”images/6.jpg” alt=”Image 6″ title=”Description of the image 6″/></li>
  8.       <li><img src=”images/7.jpg” alt=”Image 7″ title=”Description of the image 7″/></li>
  9. </ul>

The image slider can be created like this,

  1. $(‘#gallery_data’).hide();
  2. var galleryData = new SimpleGalleryCrawlerGeneric($(‘#gallery_data’)).getData();
  3. var gallery = new SimpleGallery();
  4. gallery.setData(galleryData).render($(‘#gallery’));

This will create a good fall back mechanism. That is, when JavaScript is not supported, original images will be displayed. If JavaScript is supported, slider is displayed. Take a look the demo page, and try to disable JavaScript to see how it falls back nicely.

The Completed Code

JavaScript: http://test.thecodecentral.com/demos/simple_gallery/lib/simple.gallery.js
Slider Demo: http://test.thecodecentral.com/demos/simple_gallery/

By Rz Rasel Posted in jQuery

One comment on “Tutorial: Object-Oriented Way of Creating a jQuery Image Slider

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s