Home » TUTORIALS

PAGINATE ANYTHING WITH JQUERY!

29 November 2009 No Comment

Paginate Anything with jQuery!

By: Nikola Malich

In this Nettuts+ PLUS tutorial, you’ll learn how to use jQuery to paginate virtually anything, blogs, image galleries, tables and more!
We will review the basic set up, steps and calculations required to paginate content and create dynamic links.
By the end of this tutorial you should feel comfortable incorporating this style of pagination into any of you projects. Enjoy!

Getting Started with jQuery Pagination

Sample

Sample

1. Defining an options argument

Info


Our first step will be to create a new jQuery Plugin which we’ll call ‘paginate’. Our Paginate Plugin will will have one argument, ‘options’, which is an object.
Keep in mind that any option can be overridden when initializing the Plugin.
Here are the two options we’ll use:

  • content: We’ll specify a jQuery selector here to represent the individual ‘items’ we’ll be paginating. Our default selector will be ‘TBODY TR’ which will select all the table rows belonging to a table body.
  • limit: Here we’ll specify how many ‘items’ we’d like to display per page. We’ll set a default limit of 5 items per page.

Here’s what we have so far:

     $.fn.paginate = function(options) {
          var options = jQuery.extend({
               content: 'TBODY TR',
               limit: 5
          },options);
     }
                    

For some more information on developing a jQuery Plugin have a look at these great articles:

2. Iterating through our matched selectors

Now, using jQuery’s each() method, we’ll iterate through all of the matched selectors from our Plugins init.
For example, if we call pagination like this, $(‘TABLE’).paginate(), the each() method will iterate through all the TABLES within the page.
It’s within this iteration that we’ll do all of our work:

     $.fn.paginate = function(options) {
          var options = jQuery.extend({
               content: 'TBODY TR',
               limit: 5
          },options);

          return this.each(function() {

               return this;
          });
     }
                    


Above, you’ll notice that we are returning ‘this’ at the end of our iteration.
It’s very important to return ‘this’ so as not to break the chain.
In other words, you won’t be able to add any more methods after this Plugin is called if you don’t return ‘this’.


Caching Selectors and Settings

Info


Next, let’s create an object to cache the various selectors we’ll be using as well as a few settings.
Please note that you don’t need to use an object here but it can help to keep things a bit tidier.
Let’s name our object page. We’ll give it six properties here:

  • parent: We’ll cache the jQuery ‘this’ object as our parent property. Doing so may help in understanding the logic of our code a little bit later on.
  • content: We’ll cache a jQuery selector for all of the individual the content items we’ll be paginating. We use a ternary operator to determine if we’re working with a TABLE or not as we’ll traverse the DOM a little differently if we are.
  • total: We will use the jQuery size() method to determine how many items are stored in our content property. Then, we’ll divide this total by the limit specified in our options argument and round this figure to the next whole integer using the JavaScriptceil() method. This will give us our true total number of pages.
  • display: Using jQuery’s css() method, we’ll cache the CSS ‘display’ property for our content items. We’ll use this property when displaying ‘pages’ later one.
  • prev: The prev property will be used when clicking the ‘previous’ link. It’s value will be changed dynamically when we navigate through our paginated content. Initially, we’ll be displaying page 1 and as there is no page before this we’ll set prev to 0.
  • next: The next property will be used when clicking the ‘next’ link. This value will also be changed dynamically when we navigate our paginated content. Since we’re be displaying page 1 first, we’ll set this property to reference the second page, 2.


$.fn.paginate = function(options) {
          var options = jQuery.extend({
               content: 'TBODY TR',
               limit: 5
          },options);

          return this.each(function() {

               var page = {};
               page.parent = $(this),
               page.content = (page.parent.is('TABLE')) ? page.parent.find(options.content) : page.parent.children(options.content),
               page.total = Math.ceil(page.content.size() / options.limit),
               page.display = page.content.css('display'),
               page.prev = 0,
               page.next = 2;

               return this;
          });
}
               

Displaying the First Page

Info


Now that we’ve defined our object, our next step will be to hide all of the content items which aren’t a part of the ‘first page’.
We’ll use the limit property from our options argument in combination with jQuery’s slice() method to select all of the page.content with an index greater than our limit.
Then, we’ll use jQuery’s css() method to access the display property of these matched elements and set it to ‘none’.


The slice() method takes to arguments, the second is optional:

  • start: The index of the first element to select. This element is included.
  • end: The index of the element where we conclude our slice. This element is not included.


So, if our options.limit is 5, and we specify this as the start parameter in our slice, we’ll be selecting everything with an index of 5 and higher.
Thus, all the content items with an index less than 5, 0-4, will be excluded form our selection.


To hide this slice, we will simply access it’s CSS display property and set it to none.
We could use any number of jQuery animations to hide / show our content but for simplicities sake we’ll just change the display property.


Lastly, we will add a class which denotes that this content is ‘hidden’.
This isn’t absolutely necessary but situations may arise where you need to exclude hidden content form certain methods or functions.
Adding this class makes that a bit easier.

$.fn.paginate = function(options) {
          var options = jQuery.extend({
               content: 'TBODY TR',
               limit: 5
          },options);

          return this.each(function() {

               var page = {};
               page.parent = $(this),
               page.content = (page.parent.is('TABLE')) ? page.parent.find(options.content) : page.parent.children(options.content),
               page.total = Math.ceil(page.content.size() / options.limit),
               page.display = page.content.css('display'),
               page.prev = 0,
               page.next = 2;

               page.content.slice(options.limit).css('display', 'none').addClass('ui-helper-hidden');

               return this;
          });
}
               

Creating the Pagination Link Container and Previous Button

Info


Our next step will be to create a Container for all of our Pagination links.
Here is an overview of what we’ll do:

  • Using the createElement() method, we’ll create a new DIV within our document as a jQuery object.
  • We’ll add an appropriate class to this DIV using jQuery’s addClass() method.
  • Then, using a ternary operator, we’re going to append or insert this new ELEMENT to the appropriate location within the document.

$.fn.paginate = function(options) {
          var options = jQuery.extend({
               content: 'TBODY TR',
               limit: 5
          },options);

          return this.each(function() {

               var page = {};
               page.parent = $(this),
               page.content = (page.parent.is('TABLE')) ? page.parent.find(options.content) : page.parent.children(options.content),
               page.total = Math.ceil(page.content.size() / options.limit),
               page.display = page.content.css('display'),
               page.prev = 0,
               page.next = 2;

               page.content.slice(options.limit).css('display', 'none').addClass('ui-helper-hidden');

               $(document.createElement("DIV")).addClass("link-container")[(page.parent.is('TABLE')) ? 'insertAfter' : 'appendTo'](this);

               return this;
          });
}
               


Above, you may notice an interesting expression after the addClass() method.
We’re using a conditional / ternary operator, within square brackets, which will return a string representing the method name we need to use.
This type of shortcut is only valid if it returns a string.
So, we’ll return the string which represents the appropriate jQuery method for ‘inserting’ our content.


Now, let’s cache a selector for our new DIV.link-container.
Again, we’ll need to determine if we’re working with a TABLE here as our method of DOM traversal will vary slightly if we are.


$.fn.paginate = function(options) {
          var options = jQuery.extend({
               content: 'TBODY TR',
               limit: 5
          },options);

          return this.each(function() {

               var page = {};
               page.parent = $(this),
               page.content = (page.parent.is('TABLE')) ? page.parent.find(options.content) : page.parent.children(options.content),
               page.total = Math.ceil(page.content.size() / options.limit),
               page.display = page.content.css('display'),
               page.prev = 0,
               page.next = 2;

               page.content.slice(options.limit).css('display', 'none').addClass('ui-helper-hidden');

               $(document.createElement("DIV")).addClass("link-container")[(page.parent.is('TABLE')) ? 'insertAfter' : 'appendTo'](this);

               page.linkContainer = (page.parent.is('TABLE')) ? page.parent.next('.link-container:first') : page.parent.find('.link-container:first');

               return this;
          });
}
               


With our link container in place, we’ll now create our ‘Previous’ link.
Essentially, we’ll use the same technique as above but without the ternary operator to determine our ‘insertion’ type as we’ll always be appending it to the link container.
Here’s a breakdown of what we’ll be doing in our next step:

  • Using the createElement() method, we’ll create a new ANCHOR as a jQuery object
  • We’ll then add the appropriate classes to this ANCHOR: “pagination-link previous ui-state-default”
    • Please note that the ‘ui-state-default’ class is used as an ‘Interaction State’ within the jQuery UI CSS Framework. It’s primarily used for clickable button-like elements.
  • Next, we’ll define this ANCHOR’S HREF, TITLE and REL attributes using the attr() method
    • The REL attribute will be set as ‘nofollow’ to prevent search engines from following this link.
  • Using the text() method, we’ll set the text for this link as the ‘<' symbol for 'previous'.
  • Lastly, we’ll use jQuery’s appendTo() method to attach this ANCHOR to the DIV.link-container we created and cached as our page.linkContainer property.

Here’s how it all looks thus far:

$.fn.paginate = function(options) {
          var options = jQuery.extend({
               content: 'TBODY TR',
               limit: 5
          },options);

          return this.each(function() {

               var page = {};
               page.parent = $(this),
               page.content = (page.parent.is('TABLE')) ? page.parent.find(options.content) : page.parent.children(options.content),
               page.total = Math.ceil(page.content.size() / options.limit),
               page.display = page.content.css('display'),
               page.prev = 0,
               page.next = 2;

               page.content.slice(options.limit).css('display', 'none').addClass('ui-helper-hidden');

               $(document.createElement("DIV")).addClass("link-container")[(page.parent.is('TABLE')) ? 'insertAfter' : 'appendTo'](this);

               page.linkContainer = (page.parent.is('TABLE')) ? page.parent.next('.link-container:first') : page.parent.find('.link-container:first');

               $(document.createElement("A")).addClass("pagination-link previous ui-state-default").attr('href', 'previous').attr('title', 'Previous page').attr('rel', 'nofollow').text('<').appendTo(page.linkContainer);

               return this;
          });
}
               

In the Loop - Creating Anchors and Selectors

Info


This step is, perhaps, one of the most important steps we're going to take.
Using a for loop, we are going iterate through our total number of pages, page.total.
We'll create numeric links within this loop as well as cache selectors for our content pages.
Here's an overview of what we'll be doing:

  • First, we are going to define a few vars:

    • offset: The offset var will be the loop counter var from our for statement + 1. We'll use offset as a page number / counter of sorts.
    • min: The min var will be the used to define the 'starting' point of our page slice() a little later on.
      We'll multiply our offset property by the options.limit argument specified earlier and then subtract the options.limit from this total.
      So, if our offset is 1 and our options.limit is 5, the min var will be ((1 * 5) - 5), or 0.
      As were using a zero based index this will represent our first page.
    • max: The max var will be used as the end point in our slice().
      We will simply take our offset and multiply it by the limit specified in our options argument.
      So, if our offset is 1 and our limit is 5, the max var will equal (1 * 5), or 5.
    • NOTE: As we are using a zero based index and jQuery's slice() method, the min var will server as our 'start' argument and the max var will serve as our 'end' argument.
      As such, the slice() method will select everything with an index including and above the min value and up to but not including the max value.
  • Now, using the same technique as we used to create our link container and previous link, we are going to create a numeric link for each page / slice of our content. We'll append these ANCHOR'S to our page.linkContainer. Here's a look at what we'll do:

    • Using the createElement() method, we'll create a new ANCHOR as a jQuery object
    • We'll then add the appropriate classes to this ANCHOR: "pagination-link previous ui-state-default"
      • Please note that the 'ui-state-default' class is used as an 'Interaction State' within the jQuery UI CSS Framework. It's primarily used for clickable button-like elements.
    • Next, we'll define this ANCHOR'S HREF, TITLE and REL attributes using the attr() method
      • We'll define this ANCHOR'S REL attribute as 'nofollow' to prevent search engines form following this link.
    • Using the text() method, we'll set the text for this link using our offset var.
    • Lastly, we'll use jQuery's appendTo() method to attach this ANCHOR to the DIV.link-container we created and cached as our page.linkContainer property.

  • With our calculations complete, and this link created, we'll now cache a selector for this 'particular' page slice.
    We'll store each of these selectors in our page object using the offset var as the property name.
    Remember, the offset var will equal the num var + 1. So, as we iterate, the offset will increment accordingly.
    Thus, our first offset will be 1 and will represent page one of our content.
    In simpler terms, page[1] will contain the selector for the first five content items, page[2] for the next five and so on...


Here's how our for loop looks:

          $(document.createElement("A")).addClass("pagination-link previous ui-state-default").attr('href', 'previous').attr('title', 'Previous page').attr('rel', 'nofollow').text('<').appendTo(page.linkContainer);

          for(var num=0;  num < page.total;   num++){

               var offset = num + 1,
                     min = (offset * options.limit) - (options.limit),
                     max = (offset * options.limit);

               $(document.createElement("A")).addClass("pagination-link numeric ui-state-default").attr('href', offset).attr('title', 'Page '+offset+'').attr('rel', 'nofollow').text(offset).appendTo(page.linkContainer);

               page[offset] = page.content.slice(min, [max]);
          };
               

Creating the Forward Button

Info


With our numeric links created and our page slices cached, we can now create our 'Next' link.
Again, we'll do this in the same manner as we did for our previous links.
Here are the steps we'll be taking:

  • Using the createElement() method, we'll create a new ANCHOR as a jQuery object
  • We'll then add the appropriate classes to this ANCHOR: "pagination-link previous ui-state-default"
  • Next, we'll define this ANCHOR'S HREF, TITLE and REL attributes using the attr() method
    • We'll define this ANCHOR'S REL attribute as 'nofollow' to prevent search engines form following this link.
  • Using the text() method, we'll set the text for this link as the '>' symbol for 'next'.
  • Lastly, we'll use jQuery's appendTo() method to attach this ANCHOR to the DIV.link-container we created and cached as our page.linkContainer property.

          $(document.createElement("A")).addClass("pagination-link previous ui-state-default").attr('href', 'previous').attr('title', 'Previous page').attr('rel', 'nofollow').text('<').appendTo(page.linkContainer);

          for(var num=0;  num < page.total;   num++){

               var offset = num + 1,
                     min = (offset * options.limit) - (options.limit),
                     max = (offset * options.limit);

               $(document.createElement("A")).addClass("pagination-link numeric ui-state-default").attr('href', offset).attr('title', 'Page '+offset+'').attr('rel', 'nofollow').text(offset).appendTo(page.linkContainer);

               page[offset] = page.content.slice(min, [max]);
          };

          $(document.createElement("A")).addClass("pagination-link next ui-state-default").attr('href', 'next').attr('title', 'Next page').attr('rel', 'nofollow').text('>').appendTo(page.linkContainer);
               


With all of our ANCHORS created and all of our page selectors cached we'll now cache a selector for our links.

               $(document.createElement("A")).addClass("pagination-link previous ui-state-default").attr('href', 'previous').attr('title', 'Previous page').attr('rel', 'nofollow').text('<').appendTo(page.linkContainer);

               for(var num=0;  num < page.total;   num++){

                    var offset = num + 1,
                          min = (offset * options.limit) - (options.limit),
                          max = (offset * options.limit);

                    $(document.createElement("A")).addClass("pagination-link numeric ui-state-default").attr('href', offset).attr('title', 'Page '+offset+'').attr('rel', 'nofollow').text(offset).appendTo(page.linkContainer);

                    page[offset] = page.content.slice(min, [max]);
               };

               $(document.createElement("A")).addClass("pagination-link next ui-state-default").attr('href', 'next').attr('title', 'Next page').attr('rel', 'nofollow').text('>').appendTo(page.linkContainer);

               page.anchors = page.linkContainer.find('A');
               


Events - mouseenter, mouseleave and click

Info

1. General Overview


So far, we've created our pagination links and cached selectors for all of the elements and page slices we'll be using.
We'll now add some behavior to the mouseenter, mouseleave and click events for our links.

A. Mouseenter and Mouseleave

Here's an overview of what we'll do on mouseenter and mouseleave:


NOTE:
All of the ANCHORS will have the 'ui-state-default' class. This is our base interaction class.
On mouseenter and mouseleave we'll add or remove the 'ui-state-hover' interaction class accordingly.
Additionally, when an ANCHOR is clicked, if it's not already active, we'll add the 'ui-state-active' class as an indication of the current active page.

  • First, we'll cache a selector for this element which does not have the 'ui-state-active' class
  • Then, using jQuery's event object, we'll determine if the event is mouseenter. If it is, we'll add the 'ui-state-hover' class.
  • If the event is mouseleave, we'll remove the 'ui-state-hover' class.

B. Click

Here's an overview of what we'll do for the click event:



Please note that much of what we'll be doing here is the same for the previous, next and numeric links.
I think it's also important to point out that this code could be made substantially shorter for production.
However, I think it's a good idea to maintain separation and readability for the sake of this tutorial ...


  • Using jQuery's event object, we'll use the preventDefault() method to prevent navigation when clicking our links.
  • Next, we'll determine if the link which was clicked already has the active class. If it does, we'll return false which to prevent any further action.
  • If the link isn't active, we'll check to see if the values for our previous and back buttons are undefined.
    These values will only be undefined if none of the links have been clicked yet.
    Later on, you'll see how we define these properties relative to the active link.
    Since they are undefined at this time, we'll define their values here.
    We'll set the value for our 'prev' link as 0 and the value of 'next' link as 2.
    In simpler terms, since our paginated content will always start on 'page 1' we set the previous page to 0 and the next page to 2.
  • Next, we'll cache a selector for this ANCHOR'S active sibling. We'll use this a bit later to toggle the active classes accordingly.
  • Now, we'll need to determine if the ANCHOR which was clicked is the 'previous' link. If it is, we'll do the following:

    • Determine if we're already on the first page. If we are, since there is no previous page, we'll return false in order to prevent any further action.
    • Next, we'll find the sibling ANCHOR whose HREF attribute corresponds to the value of our page.prev property. We'll cache a selector for this ANCHOR as this.link.
    • Using jQuery's add() method we'll combine this.link with this.siblings and then toggle the active class for all of these matched elements using jQuery's toggleClass() method.
    • Now, using the content selector we cached earlier, page.content, we'll hide all of our content by setting it's CSS display property to none.
      Additionally, we'll add a special class to it, ui-helper-hidden. This is a jQuery UI Framework helper class.
      By default, it sets display to none and as such we could just add or remove this class in order to toggle this elements display property.
      For the sake of this tutorial, however, I'd like to use jQuery's css() method.
      Also, please keep in mind that adding this helper class isn't necessary but situations may arise where you need to exclude hidden content form certain methods or functions.
      Having a helper class for 'hidden' items can make this a bit simpler.

    • Now, using the value stored in our page.prev property, we'll show the appropriate page by setting it's display property back to its original value which was stored in our page.display property.
      Remember, in our for loop, we stored selectors which referenced 'slices' of our content.
      We will also remove the 'ui-helper-hidden' class from this content items as it is now visible.

    • Next, we'll decrement our page.prev property by 1 to reference the 'new' previous page.
    • Lastly, we'll increment our page.next property by 2 so that it references the new 'next' page and not the current one.

  • If the ANCHOR which was clicked is the next link, we'll follow the same steps as above but with a few minor changes. Here's what we'll do:

    • Determine if we're already on the last page of our content. If we are, we'll return false in order to prevent any further action.
    • Next, we'll find the ANCHOR whose HREF attribute corresponds to the value of our page.next property. We'll cache this ANCHOR as this.link.
    • Using jQuery's add() method we'll combine this.link with this.siblings and then toggle the active class for all of these matched elements using jQuery's toggleClass() method.
    • Now, using the content selector we cached earlier, page.content, we'll hide all of our content by setting it's CSS display property to none.
      We'll then add the ui-helper-hidden class to it.

    • Now, using the value stored in our page.next property, we'll show the appropriate page by setting it's display property back to its original value which was stored in our page.display property.
      Remember, in our for loop, we stored selectors which referenced 'slices' of our content.
      We will also remove the 'ui-helper-hidden' class from these content items as well.

    • Next, we'll decrement our page.prev property by 2 so that it references the new 'prev' page and not the current one.
    • Lastly, we'll increment our page.next property by 1 so that it references the new 'next' page.

  • If the ANCHOR which was clicked is a numeric page link we will, again, follow the above steps with a few minor changes. Here's what we'll do:

    • First, we'll cache the selector for this ANCHOR as this.link.
    • Using jQuery's add() method we'll combine this.link with this.siblings and toggle the active class for all of these matched elements using jQuery's toggleClass() method.
    • Now, using the content selector we cached earlier, page.content, we'll hide all of our content by setting it's CSS display property to none.
      We'll then add the ui-helper-hidden class to this content. Again, this is a jQuery UI Framework helper class.
    • Now, we'll get the HREF attribute for this.link and store it as this.offset. This HREF attribute corresponds directly to one of the page slices we cached earlier.

    • Using this.offset as a property name or 'key' within our page object, we'll show the appropriate page by setting it's display property back to its original value which was stored in our page.display property.
      Remember, in our for loop, we stored selectors representing 'slices' of content and set each of these property names to a numeric value symbolic of page number.
      So, assuming the options.limit is 5, page[1] will display the first five items, page[2] will display the next five and so on...

    • Next, we'll decrement our page.prev property by taking this.offset and subtracting 1 from it. Remember, this.offset, which is the ANCHOR'S HREF attribute, corresponds directly to a 'page' number. So, by subtracting 1 from the offset we are selecting the previous page.
    • Lastly, we'll increment our page.next property by taking this.offset and adding 1 to it so that it now references the new 'next' page.

2. The Mouseenter and Mouseleave Events


We'll now bind handlers to the mouseenter and mouseleave events of pagination links.
We'll first cache a selector that excludes all links which have the active class by using jQuery's not() method to exclude them.


               page.anchors.bind('mouseenter mouseleave', function(e){
                    this.self = $(this).not('.ui-state-active');
                });
                    


Next, using the type() property of jQuery's event object, we'll determine what type of event was triggered.
We'll do this within a conditional / ternary operator and we'll add or remove the hover class accordingly.
jQuery's event object will be passed to the argument, e, we specify in our anonymous function here.

               page.anchors.bind('mouseenter mouseleave', function(e){
                    this.self = $(this).not('.ui-state-active');
                    (e.type === 'mouseenter') ? this.self.addClass('ui-state-hover') : this.self.removeClass('ui-state-hover');
                });
                    


Next, as part of a jQuery chain and using jQuery's eq() method, we'll get the select pagination link and add the active class to it.
The second link which will have an index of 1 since we are working with a zero based index and will always be the numeric link for page one.
Since page one is displayed by default we'll make this the active link.
Here's how our code will look:

               page.anchors.bind('mouseenter mouseleave', function(e){
                    this.self = $(this).not('.ui-state-active');
                    (e.type === 'mouseenter') ? this.self.addClass('ui-state-hover') : this.self.removeClass('ui-state-hover');
                }).eq(1).addClass('ui-state-active');
                    

3. The Click Event

A. Default Steps


Let's take a closer look at the click event now.
First of all, using the preventDefault(), method which is part of jQuery's event object, we'll prevent navigation when clicking on our links.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();
                    });
                         


Next, we'll check to see if this link has the active class, ui-state-active.
If it does, then the page slice corresponding to this link is already displayed and we'll return false.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                    });
                         


Now, we'll cache a selector for this links active sibling.
In a moment, we'll using using this selector to toggle active classes.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                    });
                         

B. The Previous Button


We'll be checking if the link which was clicked is our previous or next link.
If it's neither of these, then, by default, it's a numeric link.
The code for each of these conditions is identical except for a few minor but important changes.


Let's start with the previous link.
The first thing we'll do is check to see if our page.prev property is 0.
If it is, this means that the first page is already displayed and we'll return false to stop any further action from occurring.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')){

                              if(page.prev === 0){
                                   return false;
                              };
                         };

                    });
                         


If the first page isn't displayed, we'll cache a selector for the sibling link whose HREF attribute matches our page.prev property.
We'll use jQuery's attribute selector to check our sibling link's HREFs.
We'll concatenate our page.prev property as the value:

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')){

                              if(page.prev === 0){
                                   return false;
                              };

                              this.link = $(this).siblings('A[href= ' + page.prev + ']');
                         };

                    });
                         


Now, using the selector we cached as this.link and the sibling selector we cached earlier, this.siblings, we'll toggle the active class for these matched elements. We'll use jQuery's add() method to combine the two selectors and jQuery's toggleClass() method to toggle the 'ui-state-active' class.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')){

                              if(page.prev === 0){
                                   return false;
                              };

                              this.link = $(this).siblings('A[href= ' + page.prev + ']');
                              this.link.add(this.siblings).toggleClass('ui-state-active');
                         };

                    });
                         


Next, we'll hide our content items by setting their display to none. We'll use the page.content selector we cached earlier to select our content.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')){

                              if(page.prev === 0){
                                   return false;
                              };

                              this.link = $(this).siblings('A[href= ' + page.prev + ']');
                              this.link.add(this.siblings).toggleClass('ui-state-active');

                              page.content.css('display', 'none').addClass('ui-helper-hidden');
                         };

                    });
                         


With our content items hidden, we'll show the appropriate page using one of the slices we cached earlier.
Keep in mind that our page.prev property corresponds directly to the previous page's slice.
So, all we need to do here is specify page.prev as our value.
Additionally, we'll use the display property we cached earlier, page.display, to restore our contents display property back to its default.
Lastly, we'll remove the 'ui-helper-hidden' class as this content is now visible.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')){

                              if(page.prev === 0){
                                   return false;
                              };

                              this.link = $(this).siblings('A[href= ' + page.prev + ']');
                              this.link.add(this.siblings).toggleClass('ui-state-active');

                              page.content.css('display', 'none').addClass('ui-helper-hidden');
                              page[page.prev].css('display', page.display).removeClass('ui-helper-hidden');
                         };

                    });
                         


With the previous page displayed, we'll need to adjust our page.prev and page.next properties accordingly.
Since we've 'moved back' a page we'll decrement our page.prev and page.next properties by 1 so that they reference the new previous page.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')){

                              if(page.prev === 0){
                                   return false;
                              };

                              this.link = $(this).siblings('A[href= ' + page.prev + ']');
                              this.link.add(this.siblings).toggleClass('ui-state-active');

                              page.content.css('display', 'none').addClass('ui-helper-hidden');
                              page[page.prev].css('display', page.display).removeClass('ui-helper-hidden');

                              page.prev--,
                              page.next--;
                         };

                    });
                         

C. The Next Button


If our link is the 'next' button, we'll start by checking to see if the last page of content is already displayed.
We do this by comparing our page.next property to our page.total property + 1.
If the two values match, we'll return false as there is no 'next' page.

NOTE: We add 1 to our page.total property as it uses a zero based index where as our page slices start with the number one.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')) {
                              ....
                         } else if($(this).is('.next')) {

                              if(page.next === (page.total + 1)){
                                   return false;
                              };
                         }

                    });
           


We'll now cache a selector for the sibling link whose HREF attribute matches our page.next property using jQuery's attribute selector to check our sibling link's HREFs.
We'll concatenate our page.next property as the attribute's value:

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')) {
                              ....
                         } else if($(this).is('.next')) {

                              if(page.next === (page.total + 1)){
                                   return false;
                              };

                              this.link = $(this).siblings('A[href= ' + page.next + ']');
                         };
                    });
                         


Now, using the selector we just cached, this.link and the sibling selector we cached earlier, this.siblings, we'll toggle the active class for these matched ELEMENTS. We'll use jQuery's add() method to combine the two selectors and jQuery's toggleClass() method to toggle the 'ui-state-active' class.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')) {
                              ....
                         } else if($(this).is('.next')) {

                              if(page.next === (page.total + 1)){
                                   return false;
                              };

                              this.link = $(this).siblings('A[href= ' + page.next + ']');
                              this.link.add(this.siblings).toggleClass('ui-state-active');

                         };

                    });
                         


Next, using the page.content selector, we'll hide our content items by setting their display to none.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')) {
                              ....
                         } else if($(this).is('.next')) {

                              if(page.next === (page.total + 1)){
                                   return false;
                              };

                              this.link = $(this).siblings('A[href= ' + page.next + ']');
                              this.link.add(this.siblings).toggleClass('ui-state-active');

                              page.content.css('display', 'none').addClass('ui-helper-hidden');
                         };

                    });
                         


With our content hidden, we'll show the page which corresponds to our page.next property.
As the page.next property corresponds directly to one of the page slices we cached earlier, we'll specify it as the property name in our page object.
Additionally, we'll use the display property we cached earlier, page.display, to restore our contents display back to its default value.
Lastly, we'll remove our helper class, 'ui-helper-hidden', as this content is now visible.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')) {
                              ....
                         } else if($(this).is('.next')) {

                              if(page.next === (page.total + 1)){
                                   return false;
                              };

                              this.link = $(this).siblings('A[href= ' + page.next + ']');
                              this.link.add(this.siblings).toggleClass('ui-state-active');

                              page.content.css('display', 'none').addClass('ui-helper-hidden');
                              page[page.next].css('display', page.display).removeClass('ui-helper-hidden');

                         };

                    });
                         


With the 'next page' visible, we'll need to adjust our page.prev and page.next properties accordingly.
Since we've moved forward a page, we'll increment our page.prev and page.next properties by 1 so that they reference the new 'next' page.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')) {
                              ....
                         } else if($(this).is('.next')) {

                              if(page.next === (page.total + 1)){
                                   return false;
                              };

                              this.link = $(this).siblings('A[href= ' + page.next + ']');
                              this.link.add(this.siblings).toggleClass('ui-state-active');

                              page.content.css('display', 'none').addClass('ui-helper-hidden');
                              page[page.next].css('display', page.display).removeClass('ui-helper-hidden');

                              page.prev++,
                              page.next++;

                         };

                    });
                         

D. Numeric Links


If you recall, earlier on, we checked to see if the link which was clicked is already active and we returned false if it was.
With this check in place, there's no further need to determine if we're already on the active page.
So, we'll go ahead and cache a selector for this link:

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')) {
                              ....
                         } else if($(this).is('.next')) {
                              ....
                         } else {
                              this.link = $(this).not('.ui-state-active');
                         }

                    });
                         


Now, using the selector we just cached, this.link and the sibling selector we earlier, this.siblings, we'll toggle the active class for all of these matched selectors. We'll use jQuery's add() method to combine the two selectors and jQuery's toggleClass() method to toggle the 'ui-state-active' class.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')) {
                              ....
                         } else if($(this).is('.next')) {
                              ....
                         } else {

                              this.link = $(this).not('.ui-state-active');
                              this.link.add(this.siblings).toggleClass('ui-state-active');
                         }

                    });
                         


Next, we'll get the HREF attribute of the link which was clicked and store it as this.offset.
This attribute, as you may recall from our loop, will correspond directly to one of the page slices stored in our page object.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')) {
                              ....
                         } else if($(this).is('.next')) {
                              ....
                         } else {

                              this.link = $(this).not('.ui-state-active');
                              this.link.add(this.siblings).toggleClass('ui-state-active');
                         }

                         this.offset = parseInt($(this).attr('href'))

                    });
                         


Now, we'll hide our content by setting it's display to none. We'll use the page.content selector we cached earlier:

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')) {
                              ....
                         } else if($(this).is('.next')) {
                              ....
                         } else {

                              this.link = $(this).not('.ui-state-active');
                              this.link.add(this.siblings).toggleClass('ui-state-active');

                              this.offset = parseInt($(this).attr('href'))

                              page.content.css('display', 'none').addClass('ui-helper-hidden');
                         }

                    });
                         


With our content hidden, we'll show the appropriate page by matching this.offset to the corresponding page slice by specifying this.offset as the property name in our page object.
Additionally, we'll use the display property we cached earlier, page.display, to restore our contents display back to its default.
Lastly, we'll remove the 'ui-helper-hidden' class as this 'page' is now visible.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')) {
                              ....
                         } else if($(this).is('.next')) {
                              ....
                         } else {

                              this.link = $(this).not('.ui-state-active');
                              this.link.add(this.siblings).toggleClass('ui-state-active');

                              this.offset = parseInt($(this).attr('href'))

                              page.content.css('display', 'none').addClass('ui-helper-hidden');
                              page[this.offset].css('display', page.display).removeClass('ui-helper-hidden');
                         }

                    });
                         


With the appropriate page visible, we'll adjust our page.prev and page.next properties accordingly.
Since this.offset is equal to the property name of our current page, we'll subtract 1 from it to get our page.prev value.
Conversely, we'll add 1 to this.offset to get our page.next property.

                    page.anchors.bind('click', function(e){
                         e.preventDefault();

                         if($(this).is('.ui-state-active')){
                              return false;
                         }

                         this.siblings = $(this).siblings('.ui-state-active:first');

                         if($(this).is('.prev')) {
                              ....
                         } else if($(this).is('.next')) {
                              ....
                         } else {

                              this.link = $(this).not('.ui-state-active');
                              this.link.add(this.siblings).toggleClass('ui-state-active');

                              this.offset = parseInt($(this).attr('href'))

                              page.content.css('display', 'none').addClass('ui-helper-hidden');
                              page[this.offset].css('display', page.display).removeClass('ui-helper-hidden');

                              page.prev = this.offset - 1,
                              page.next = this.offset + 1;
                         }

                    });
                         


The End!

Info

That's it!
I hope you now have a strong understanding of how to implement this style of jQuery pagination into your own work.
Remember, you can paginate just about anything with this technique, image galleries, blog rolls, links, tables or even long paragraphs...

Please try out the examples included with this tutorial or create your own!

Good luck and enjoy!

Leave your response!

Add your comment below, or trackback from your own site. You can also subscribe to these comments via RSS.

Be nice. Keep it clean. Stay on topic. No spam.

You can use these tags:
<a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>

This is a Gravatar-enabled weblog. To get your own globally-recognized-avatar, please register at Gravatar.