DataTables logo DataTables

via Ad Packs

Custom pagination types

The style of the pagination options that Datatables presents to the end-user can greatly effect the look and feel of your table, as well as, of course, the interaction behaviour. Through the plug-in options you can define your own paging function to create the interaction that you are looking for.

How to use DataTables plug-in pagination functions

To use a pagination plug-in, you must include the pagination plug-in code from the plug-ins available below, after you load the DataTables library, but before you initialise the DataTable. When initialising the DataTable, you must also tell it to make use of this plug-in, rather than using the default built-in types, by setting the 'sPaginationType' to the value required by the plug-in. As an example the code below makes use of the scrolling pagination plug-in saved into a file (live example):

<script type="text/javascript" src="jquery.dataTables.js"></script>
<script type="text/javascript" src="dataTables.scrollingPagination.js"></script>
<script type="text/javascript">
	$(document).ready(function() {
		$('#example').dataTable( {
			"sPaginationType": "scrolling"
		} );
	} );
</script>

Plug-in pagination functions

Twitter Bootstrap
Show details
This plug-in provides the mark-up needed for using Twitter Bootstrap's pagination styling with DataTables. Note that this plug-in uses the fnPagingInfo API plug-in method to obtain paging information.
Author: Allan Jardine
Code:
$.extend( $.fn.dataTableExt.oPagination, {
	"bootstrap": {
		"fnInit": function( oSettings, nPaging, fnDraw ) {
			var oLang = oSettings.oLanguage.oPaginate;
			var fnClickHandler = function ( e ) {
				e.preventDefault();
				if ( oSettings.oApi._fnPageChange(oSettings, e.data.action) ) {
					fnDraw( oSettings );
				}
			};

			$(nPaging).addClass('pagination').append(
				'<ul>'+
					'<li class="prev disabled"><a href="#">&larr; '+oLang.sPrevious+'</a></li>'+
					'<li class="next disabled"><a href="#">'+oLang.sNext+' &rarr; </a></li>'+
				'</ul>'
			);
			var els = $('a', nPaging);
			$(els[0]).bind( 'click.DT', { action: "previous" }, fnClickHandler );
			$(els[1]).bind( 'click.DT', { action: "next" }, fnClickHandler );
		},

		"fnUpdate": function ( oSettings, fnDraw ) {
			var iListLength = 5;
			var oPaging = oSettings.oInstance.fnPagingInfo();
			var an = oSettings.aanFeatures.p;
			var i, j, sClass, iStart, iEnd, iHalf=Math.floor(iListLength/2);

			if ( oPaging.iTotalPages < iListLength) {
				iStart = 1;
				iEnd = oPaging.iTotalPages;
			}
			else if ( oPaging.iPage <= iHalf ) {
				iStart = 1;
				iEnd = iListLength;
			} else if ( oPaging.iPage >= (oPaging.iTotalPages-iHalf) ) {
				iStart = oPaging.iTotalPages - iListLength + 1;
				iEnd = oPaging.iTotalPages;
			} else {
				iStart = oPaging.iPage - iHalf + 1;
				iEnd = iStart + iListLength - 1;
			}

			for ( i=0, iLen=an.length ; i<iLen ; i++ ) {
				// Remove the middle elements
				$('li:gt(0)', an[i]).filter(':not(:last)').remove();

				// Add the new list items and their event handlers
				for ( j=iStart ; j<=iEnd ; j++ ) {
					sClass = (j==oPaging.iPage+1) ? 'class="active"' : '';
					$('<li '+sClass+'><a href="#">'+j+'</a></li>')
						.insertBefore( $('li:last', an[i])[0] )
						.bind('click', function (e) {
							e.preventDefault();
							oSettings._iDisplayStart = (parseInt($('a', this).text(),10)-1) * oPaging.iLength;
							fnDraw( oSettings );
						} );
				}

				// Add / remove disabled classes from the static elements
				if ( oPaging.iPage === 0 ) {
					$('li:first', an[i]).addClass('disabled');
				} else {
					$('li:first', an[i]).removeClass('disabled');
				}

				if ( oPaging.iPage === oPaging.iTotalPages-1 ) {
					$('li:last', an[i]).addClass('disabled');
				} else {
					$('li:last', an[i]).removeClass('disabled');
				}
			}
		}
	}
} );


/* Example initialisation */
$(document).ready(function() {
	$('#example').dataTable( {
		"sPaginationType": "bootstrap"
	} );
} );
ExtJS style
Show details
This pagination plug-in provides pagination controls for DataTables which match the style and interaction of the ExtJS library's grid component.
Author: Zach Curtis
Code:
$.fn.dataTableExt.oPagination.extStyle = {
    /*
    * Function: oPagination.extStyle.fnInit
    * Purpose:  Initalise dom elements required for pagination with a list of the pages
    * Returns:  -
    * Inputs:   object:oSettings - dataTables settings object
    *           node:nPaging - the DIV which contains this pagination control
    *           function:fnCallbackDraw - draw function which must be called on update
    */
    "fnInit": function (oSettings, nPaging, fnCallbackDraw) {
        nFirst = $('<span />', { 'class': 'paginate_button first' });
        nPrevious = $('<span />', { 'class': 'paginate_button previous' });
        nNext = $('<span />', { 'class': 'paginate_button next' });
        nLast = $('<span />', { 'class': 'paginate_button last' });
        nPageTxt = $("<span />", { text: 'Page' });
        nPageNumBox = $('<input />', { type: 'text', val: 1, 'class': 'pageinate_input_box' });
        nPageOf = $('<span />', { text: 'of' });
        nTotalPages = $('<span />', { text: parseInt(oSettings.aoData.length / oSettings._iDisplayLength, 10) });

        /*   nFirst.appendChild(document.createTextNode(oSettings.oLanguage.oPaginate.sFirst));
        nPrevious.appendChild(document.createTextNode(oSettings.oLanguage.oPaginate.sPrevious));
        nNext.appendChild(document.createTextNode(oSettings.oLanguage.oPaginate.sNext));
        nLast.appendChild(document.createTextNode(oSettings.oLanguage.oPaginate.sLast));
        */
        $(nPaging)
            .append(nFirst)
            .append(nPrevious)
            .append(nPageTxt)
            .append(nPageNumBox)
            .append(nPageOf)
            .append(nTotalPages)
            .append(nNext)
            .append(nLast);

        nFirst.click(function () {
            oSettings.oApi._fnPageChange(oSettings, "first");
            fnCallbackDraw(oSettings);
            nPageNumBox.val(parseInt(oSettings._iDisplayEnd / oSettings._iDisplayLength, 10));
        }).bind('selectstart', function () { return false; });

        nPrevious.click(function () {
            oSettings.oApi._fnPageChange(oSettings, "previous");
            fnCallbackDraw(oSettings);
            nPageNumBox.val(parseInt(oSettings._iDisplayEnd / oSettings._iDisplayLength, 10));
        }).bind('selectstart', function () { return false; });

        nNext.click(function () {
            oSettings.oApi._fnPageChange(oSettings, "next");
            fnCallbackDraw(oSettings);
           nPageNumBox.val(parseInt(oSettings._iDisplayEnd / oSettings._iDisplayLength, 10));
        }).bind('selectstart', function () { return false; });

        nLast.click(function () {
            oSettings.oApi._fnPageChange(oSettings, "last");
            fnCallbackDraw(oSettings);
            nPageNumBox.val(parseInt(oSettings._iDisplayEnd / oSettings._iDisplayLength,10 ));
        }).bind('selectstart', function () { return false; });

        nPageNumBox.focus(function () {
            $(this).attr("style", "border-color: #D0B39A");
        }).blur(function () {
            $(this).attr("style", "border-color: #C9C9C9");
        }).change(function () {
            var pageValue = parseInt($(this).val(), 10);
            if ((pageValue !== NaN) && pageValue > 0 && pageValue < oSettings.aoData.length) {
                oSettings._iDisplayStart = $(this).val();
                fnCallbackDraw(oSettings);
            }
        });

    },

    /*
    * Function: oPagination.extStyle.fnUpdate
    * Purpose:  Update the list of page buttons shows
    * Returns:  -
    * Inputs:   object:oSettings - dataTables settings object
    *           function:fnCallbackDraw - draw function which must be called on update
    */
    "fnUpdate": function (oSettings, fnCallbackDraw) {
        if (!oSettings.aanFeatures.p) {
            return;
        }

        /* Loop over each instance of the pager */
        var an = oSettings.aanFeatures.p;
        for (var i = 0, iLen = an.length; i < iLen; i++) {
            //var buttons = an[i].getElementsByTagName('span');
            var buttons = $(an[i]).find('span.paginate_button');
            if (oSettings._iDisplayStart === 0) {
                buttons.eq(0).attr("class", "paginate_disabled_first paginate_button");
                buttons.eq(1).attr("class", "paginate_disabled_previous paginate_button");
            }
            else {
                buttons.eq(0).attr("class", "paginate_enabled_first paginate_button");
                buttons.eq(1).attr("class", "paginate_enabled_previous paginate_button");
            }

            if (oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay()) {
                buttons.eq(2).attr("class", "paginate_disabled_next paginate_button");
                buttons.eq(3).attr("class", "paginate_disabled_last paginate_button");
            }
            else {
                buttons.eq(2).attr("class", "paginate_enabled_next paginate_button");
                buttons.eq(3).attr("class", "paginate_enabled_last paginate_button");
            }
        }
    }
};

/* Example initialisation */
$(document).ready(function() {
	$('#example').dataTable( {
		"sPaginationType": "extStyle"
	} );
} );
Four button navigation
Show details
The built-in pagination functions provide either two buttons (forward / back) or lots of buttons (forward, back, first, last and individual pages). This plug-in meets the two in the middle providing navigation controls for forward, back, first and last.
Author: Allan Jardine
Code:
$.fn.dataTableExt.oPagination.four_button = {
	/*
	 * Function: oPagination.four_button.fnInit
	 * Purpose:  Initalise dom elements required for pagination with a list of the pages
	 * Returns:  -
	 * Inputs:   object:oSettings - dataTables settings object
	 *           node:nPaging - the DIV which contains this pagination control
	 *           function:fnCallbackDraw - draw function which must be called on update
	 */
	"fnInit": function ( oSettings, nPaging, fnCallbackDraw )
	{
		nFirst = document.createElement( 'span' );
		nPrevious = document.createElement( 'span' );
		nNext = document.createElement( 'span' );
		nLast = document.createElement( 'span' );
		
		nFirst.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sFirst ) );
		nPrevious.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sPrevious ) );
		nNext.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sNext ) );
		nLast.appendChild( document.createTextNode( oSettings.oLanguage.oPaginate.sLast ) );
		
		nFirst.className = "paginate_button first";
		nPrevious.className = "paginate_button previous";
		nNext.className="paginate_button next";
		nLast.className = "paginate_button last";
		
		nPaging.appendChild( nFirst );
		nPaging.appendChild( nPrevious );
		nPaging.appendChild( nNext );
		nPaging.appendChild( nLast );
		
		$(nFirst).click( function () {
			oSettings.oApi._fnPageChange( oSettings, "first" );
			fnCallbackDraw( oSettings );
		} );
		
		$(nPrevious).click( function() {
			oSettings.oApi._fnPageChange( oSettings, "previous" );
			fnCallbackDraw( oSettings );
		} );
		
		$(nNext).click( function() {
			oSettings.oApi._fnPageChange( oSettings, "next" );
			fnCallbackDraw( oSettings );
		} );
		
		$(nLast).click( function() {
			oSettings.oApi._fnPageChange( oSettings, "last" );
			fnCallbackDraw( oSettings );
		} );
		
		/* Disallow text selection */
		$(nFirst).bind( 'selectstart', function () { return false; } );
		$(nPrevious).bind( 'selectstart', function () { return false; } );
		$(nNext).bind( 'selectstart', function () { return false; } );
		$(nLast).bind( 'selectstart', function () { return false; } );
	},
	
	/*
	 * Function: oPagination.four_button.fnUpdate
	 * Purpose:  Update the list of page buttons shows
	 * Returns:  -
	 * Inputs:   object:oSettings - dataTables settings object
	 *           function:fnCallbackDraw - draw function which must be called on update
	 */
	"fnUpdate": function ( oSettings, fnCallbackDraw )
	{
		if ( !oSettings.aanFeatures.p )
		{
			return;
		}
		
		/* Loop over each instance of the pager */
		var an = oSettings.aanFeatures.p;
		for ( var i=0, iLen=an.length ; i<iLen ; i++ )
		{
			var buttons = an[i].getElementsByTagName('span');
			if ( oSettings._iDisplayStart === 0 )
			{
				buttons[0].className = "paginate_disabled_previous";
				buttons[1].className = "paginate_disabled_previous";
			}
			else
			{
				buttons[0].className = "paginate_enabled_previous";
				buttons[1].className = "paginate_enabled_previous";
			}
			
			if ( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() )
			{
				buttons[2].className = "paginate_disabled_next";
				buttons[3].className = "paginate_disabled_next";
			}
			else
			{
				buttons[2].className = "paginate_enabled_next";
				buttons[3].className = "paginate_enabled_next";
			}
		}
	}
};

/* Example initialisation */
$(document).ready(function() {
	$('#example').dataTable( {
		"sPaginationType": "four_button"
	} );
} );
Links pagination
Show details
This pagination plug-in provides exactly the same controls as the built in "full_numbers" control, but uses <A> tags rather than <SPAN> for the navigation elements. This can improve accessibility by being able to tab through available links.
Author: Allan Jardine
Code:
$.fn.dataTableExt.oPagination.links = {
	"fnInit": function ( oSettings, nPaging, fnCallbackDraw )
	{
		var nFirst = document.createElement( 'a' );
		var nPrevious = document.createElement( 'a' );
		var nList = document.createElement( 'span' );
		var nNext = document.createElement( 'a' );
		var nLast = document.createElement( 'a' );
		
		nFirst.innerHTML = oSettings.oLanguage.oPaginate.sFirst;
		nPrevious.innerHTML = oSettings.oLanguage.oPaginate.sPrevious;
		nNext.innerHTML = oSettings.oLanguage.oPaginate.sNext;
		nLast.innerHTML = oSettings.oLanguage.oPaginate.sLast;
		
		var oClasses = oSettings.oClasses;
		nFirst.className = oClasses.sPageButton+" "+oClasses.sPageFirst;
		nPrevious.className = oClasses.sPageButton+" "+oClasses.sPagePrevious;
		nNext.className= oClasses.sPageButton+" "+oClasses.sPageNext;
		nLast.className = oClasses.sPageButton+" "+oClasses.sPageLast;
		
		nPaging.appendChild( nFirst );
		nPaging.appendChild( nPrevious );
		nPaging.appendChild( nList );
		nPaging.appendChild( nNext );
		nPaging.appendChild( nLast );
		
		$(nFirst).bind( 'click.DT', function () {
			if ( oSettings.oApi._fnPageChange( oSettings, "first" ) )
			{
				fnCallbackDraw( oSettings );
			}
		} );
		
		$(nPrevious).bind( 'click.DT', function() {
			if ( oSettings.oApi._fnPageChange( oSettings, "previous" ) )
			{
				fnCallbackDraw( oSettings );
			}
		} );
		
		$(nNext).bind( 'click.DT', function() {
			if ( oSettings.oApi._fnPageChange( oSettings, "next" ) )
			{
				fnCallbackDraw( oSettings );
			}
		} );
		
		$(nLast).bind( 'click.DT', function() {
			if ( oSettings.oApi._fnPageChange( oSettings, "last" ) )
			{
				fnCallbackDraw( oSettings );
			}
		} );
		
		/* Take the brutal approach to cancelling text selection */
		$('a', nPaging)
			.bind( 'mousedown.DT', function () { return false; } )
			.bind( 'selectstart.DT', function () { return false; } );
		
		/* ID the first elements only */
		if ( oSettings.sTableId !== '' && typeof oSettings.aanFeatures.p == "undefined" )
		{
			nPaging.setAttribute( 'id', oSettings.sTableId+'_paginate' );
			nFirst.setAttribute( 'id', oSettings.sTableId+'_first' );
			nPrevious.setAttribute( 'id', oSettings.sTableId+'_previous' );
			nNext.setAttribute( 'id', oSettings.sTableId+'_next' );
			nLast.setAttribute( 'id', oSettings.sTableId+'_last' );
		}
	},
	
	"fnUpdate": function ( oSettings, fnCallbackDraw )
	{
		if ( !oSettings.aanFeatures.p )
		{
			return;
		}
		
		var iPageCount = $.fn.dataTableExt.oPagination.iFullNumbersShowPages;
		var iPageCountHalf = Math.floor(iPageCount / 2);
		var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength);
		var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
		var sList = "";
		var iStartButton, iEndButton, i, iLen;
		var oClasses = oSettings.oClasses;
		
		/* Pages calculation */
		if (iPages < iPageCount)
		{
			iStartButton = 1;
			iEndButton = iPages;
		}
		else
		{
			if (iCurrentPage <= iPageCountHalf)
			{
				iStartButton = 1;
				iEndButton = iPageCount;
			}
			else
			{
				if (iCurrentPage >= (iPages - iPageCountHalf))
				{
					iStartButton = iPages - iPageCount + 1;
					iEndButton = iPages;
				}
				else
				{
					iStartButton = iCurrentPage - Math.ceil(iPageCount / 2) + 1;
					iEndButton = iStartButton + iPageCount - 1;
				}
			}
		}
		
		/* Build the dynamic list */
		for ( i=iStartButton ; i<=iEndButton ; i++ )
		{
			if ( iCurrentPage != i )
			{
				sList += '<a class="'+oClasses.sPageButton+'">'+i+'</a>';
			}
			else
			{
				sList += '<a class="'+oClasses.sPageButtonActive+'">'+i+'</a>';
			}
		}
		
		/* Loop over each instance of the pager */
		var an = oSettings.aanFeatures.p;
		var anButtons, anStatic, nPaginateList;
		var fnClick = function(e) {
			/* Use the information in the element to jump to the required page */
			var iTarget = (this.innerHTML * 1) - 1;
			oSettings._iDisplayStart = iTarget * oSettings._iDisplayLength;
			fnCallbackDraw( oSettings );
			e.preventDefault();
		};
		var fnFalse = function () { return false; };
		
		for ( i=0, iLen=an.length ; i<iLen ; i++ )
		{
			if ( an[i].childNodes.length === 0 )
			{
				continue;
			}
			
			/* Build up the dynamic list forst - html and listeners */
			var qjPaginateList = $('span:eq(0)', an[i]);
			qjPaginateList.html( sList );
			$('a', qjPaginateList).bind( 'click.DT', fnClick ).bind( 'mousedown.DT', fnFalse )
				.bind( 'selectstart.DT', fnFalse );
			
			/* Update the 'premanent botton's classes */
			anButtons = an[i].getElementsByTagName('a');
			anStatic = [
				anButtons[0], anButtons[1], 
				anButtons[anButtons.length-2], anButtons[anButtons.length-1]
			];
			$(anStatic).removeClass( oClasses.sPageButton+" "+oClasses.sPageButtonActive+" "+oClasses.sPageButtonStaticDisabled );
			if ( iCurrentPage == 1 )
			{
				anStatic[0].className += " "+oClasses.sPageButtonStaticDisabled;
				anStatic[1].className += " "+oClasses.sPageButtonStaticDisabled;
			}
			else
			{
				anStatic[0].className += " "+oClasses.sPageButton;
				anStatic[1].className += " "+oClasses.sPageButton;
			}
			
			if ( iPages === 0 || iCurrentPage == iPages || oSettings._iDisplayLength == -1 )
			{
				anStatic[2].className += " "+oClasses.sPageButtonStaticDisabled;
				anStatic[3].className += " "+oClasses.sPageButtonStaticDisabled;
			}
			else
			{
				anStatic[2].className += " "+oClasses.sPageButton;
				anStatic[3].className += " "+oClasses.sPageButton;
			}
		}
	}
};

/* Example initialisation */
$(document).ready(function() {
	$('#example').dataTable( {
		"sPaginationType": "links"
	} );
} );
Select list
Show details
This pagination plug-in provides a select menu with the list of the page numbers that are available for viewing.
Author: jneilliii
Code:
$.fn.dataTableExt.oPagination.listbox = {
	/*
	 * Function: oPagination.listbox.fnInit
	 * Purpose:  Initalise dom elements required for pagination with listbox input
	 * Returns:  -
	 * Inputs:   object:oSettings - dataTables settings object
	 *		       node:nPaging - the DIV which contains this pagination control
	 *		       function:fnCallbackDraw - draw function which must be called on update
	 */
	"fnInit": function (oSettings, nPaging, fnCallbackDraw) {
		var nInput = document.createElement('select');
		var nPage = document.createElement('span');
		var nOf = document.createElement('span');
		nOf.className = "paginate_of";
		nPage.className = "paginate_page";
		if (oSettings.sTableId !== '') {
			nPaging.setAttribute('id', oSettings.sTableId + '_paginate');
		}
		nInput.style.display = "inline";
		nPage.innerHTML = "Page ";
		nPaging.appendChild(nPage);
		nPaging.appendChild(nInput);
		nPaging.appendChild(nOf);
		$(nInput).change(function (e) { // Set DataTables page property and redraw the grid on listbox change event.
			window.scroll(0,0); //scroll to top of page
			if (this.value === "" || this.value.match(/[^0-9]/)) { /* Nothing entered or non-numeric character */
				return;
			}
			var iNewStart = oSettings._iDisplayLength * (this.value - 1);
			if (iNewStart > oSettings.fnRecordsDisplay()) { /* Display overrun */
				oSettings._iDisplayStart = (Math.ceil((oSettings.fnRecordsDisplay() - 1) / oSettings._iDisplayLength) - 1) * oSettings._iDisplayLength;
				fnCallbackDraw(oSettings);
				return;
			}
			oSettings._iDisplayStart = iNewStart;
			fnCallbackDraw(oSettings);
		}); /* Take the brutal approach to cancelling text selection */
		$('span', nPaging).bind('mousedown', function () {
			return false;
		});
		$('span', nPaging).bind('selectstart', function () {
			return false;
		});
	},
	
	/*
	 * Function: oPagination.listbox.fnUpdate
	 * Purpose:  Update the listbox element
	 * Returns:  -
	 * Inputs:   object:oSettings - dataTables settings object
	 *		       function:fnCallbackDraw - draw function which must be called on update
	 */
	"fnUpdate": function (oSettings, fnCallbackDraw) {
		if (!oSettings.aanFeatures.p) {
			return;
		}
		var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength);
		var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1; /* Loop over each instance of the pager */
		var an = oSettings.aanFeatures.p;
		for (var i = 0, iLen = an.length; i < iLen; i++) {
			var spans = an[i].getElementsByTagName('span');
			var inputs = an[i].getElementsByTagName('select');
			var elSel = inputs[0];
			if(elSel.options.length != iPages) {
				elSel.options.length = 0; //clear the listbox contents
				for (var j = 0; j < iPages; j++) { //add the pages
					var oOption = document.createElement('option');
					oOption.text = j + 1;
					oOption.value = j + 1;
					try {
						elSel.add(oOption, null); // standards compliant; doesn't work in IE
					} catch (ex) {
						elSel.add(oOption); // IE only
					}
				}
				spans[1].innerHTML = " nbsp;of nbsp;" + iPages;
			}
		  elSel.value = iCurrentPage;
		}
	}
};

/* Example initialisation */
$(document).ready(function() {
	$('#example').dataTable( {
		"sPaginationType": "listbox"
	} );
} );
Navigation with text input
Show details
Sometimes for quick navigation, it can be useful to allow an end user to enter which page they wish to jump to manually. This paging control uses a text input box to accept new paging numbers (arrow keys are also allowed for), and four standard navigation buttons are also presented to the end user.
Author: Allan Jardine
Code:
$.fn.dataTableExt.oPagination.input = {
	/*
	 * Function: oPagination.input.fnInit
	 * Purpose:  Initalise dom elements required for pagination with input textbox
	 * Returns:  -
	 * Inputs:   object:oSettings - dataTables settings object
	 *           node:nPaging - the DIV which contains this pagination control
	 *           function:fnCallbackDraw - draw function which must be called on update
	 */
	"fnInit": function ( oSettings, nPaging, fnCallbackDraw )
	{
		var nFirst = document.createElement( 'span' );
		var nPrevious = document.createElement( 'span' );
		var nNext = document.createElement( 'span' );
		var nLast = document.createElement( 'span' );
		var nInput = document.createElement( 'input' );
		var nPage = document.createElement( 'span' );
		var nOf = document.createElement( 'span' );
		
		nFirst.innerHTML = oSettings.oLanguage.oPaginate.sFirst;
		nPrevious.innerHTML = oSettings.oLanguage.oPaginate.sPrevious;
		nNext.innerHTML = oSettings.oLanguage.oPaginate.sNext;
		nLast.innerHTML = oSettings.oLanguage.oPaginate.sLast;
		
		nFirst.className = "paginate_button first";
		nPrevious.className = "paginate_button previous";
		nNext.className="paginate_button next";
		nLast.className = "paginate_button last";
		nOf.className = "paginate_of";
		nPage.className = "paginate_page";
		
		if ( oSettings.sTableId !== '' )
		{
			nPaging.setAttribute( 'id', oSettings.sTableId+'_paginate' );
			nPrevious.setAttribute( 'id', oSettings.sTableId+'_previous' );
			nPrevious.setAttribute( 'id', oSettings.sTableId+'_previous' );
			nNext.setAttribute( 'id', oSettings.sTableId+'_next' );
			nLast.setAttribute( 'id', oSettings.sTableId+'_last' );
		}
		
		nInput.type = "text";
		nInput.style.width = "15px";
		nInput.style.display = "inline";
		nPage.innerHTML = "Page ";
		
		nPaging.appendChild( nFirst );
		nPaging.appendChild( nPrevious );
		nPaging.appendChild( nPage );
		nPaging.appendChild( nInput );
		nPaging.appendChild( nOf );
		nPaging.appendChild( nNext );
		nPaging.appendChild( nLast );
		
		$(nFirst).click( function () {
			oSettings.oApi._fnPageChange( oSettings, "first" );
			fnCallbackDraw( oSettings );
		} );
		
		$(nPrevious).click( function() {
			oSettings.oApi._fnPageChange( oSettings, "previous" );
			fnCallbackDraw( oSettings );
		} );
		
		$(nNext).click( function() {
			oSettings.oApi._fnPageChange( oSettings, "next" );
			fnCallbackDraw( oSettings );
		} );
		
		$(nLast).click( function() {
			oSettings.oApi._fnPageChange( oSettings, "last" );
			fnCallbackDraw( oSettings );
		} );
		
		$(nInput).keyup( function (e) {
			
			if ( e.which == 38 || e.which == 39 )
			{
				this.value++;
			}
			else if ( (e.which == 37 || e.which == 40) && this.value > 1 )
			{
				this.value--;
			}
			
			if ( this.value == "" || this.value.match(/[^0-9]/) )
			{
				/* Nothing entered or non-numeric character */
				return;
			}
			
			var iNewStart = oSettings._iDisplayLength * (this.value - 1);
			if ( iNewStart > oSettings.fnRecordsDisplay() )
			{
				/* Display overrun */
				oSettings._iDisplayStart = (Math.ceil((oSettings.fnRecordsDisplay()-1) / 
					oSettings._iDisplayLength)-1) * oSettings._iDisplayLength;
				fnCallbackDraw( oSettings );
				return;
			}
			
			oSettings._iDisplayStart = iNewStart;
			fnCallbackDraw( oSettings );
		} );
		
		/* Take the brutal approach to cancelling text selection */
		$('span', nPaging).bind( 'mousedown', function () { return false; } );
		$('span', nPaging).bind( 'selectstart', function () { return false; } );
	},
	
	/*
	 * Function: oPagination.input.fnUpdate
	 * Purpose:  Update the input element
	 * Returns:  -
	 * Inputs:   object:oSettings - dataTables settings object
	 *           function:fnCallbackDraw - draw function which must be called on update
	 */
	"fnUpdate": function ( oSettings, fnCallbackDraw )
	{
		if ( !oSettings.aanFeatures.p )
		{
			return;
		}
		var iPages = Math.ceil((oSettings.fnRecordsDisplay()) / oSettings._iDisplayLength);
		var iCurrentPage = Math.ceil(oSettings._iDisplayStart / oSettings._iDisplayLength) + 1;
		
		/* Loop over each instance of the pager */
		var an = oSettings.aanFeatures.p;
		for ( var i=0, iLen=an.length ; i<iLen ; i++ )
		{
			var spans = an[i].getElementsByTagName('span');
			var inputs = an[i].getElementsByTagName('input');
			spans[3].innerHTML = " of "+iPages
			inputs[0].value = iCurrentPage;
		}
	}
}


/* Example initialisation */
$(document).ready(function() {
	$('#example').dataTable( {
		"sPaginationType": "input"
	} );
} );
Scrolling navigation
Show details
This modification of DataTables' standard two button pagination controls adds a little animation effect to the paging action by redrawing the table multiple times for each event, each draw progressing by one row until the required point in the table is reached.
Author: Allan Jardine
Code:
/* Time between each scrolling frame */
$.fn.dataTableExt.oPagination.iTweenTime = 100;

$.fn.dataTableExt.oPagination.scrolling = {
	"fnInit": function ( oSettings, nPaging, fnCallbackDraw )
	{
		var oLang = oSettings.oLanguage.oPaginate;
		var oClasses = oSettings.oClasses;
		var fnClickHandler = function ( e ) {
			if ( oSettings.oApi._fnPageChange( oSettings, e.data.action ) )
			{
				fnCallbackDraw( oSettings );
			}
		};

		var sAppend = (!oSettings.bJUI) ?
			'<a class="'+oSettings.oClasses.sPagePrevDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button">'+oLang.sPrevious+'</a>'+
			'<a class="'+oSettings.oClasses.sPageNextDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button">'+oLang.sNext+'</a>'
			:
			'<a class="'+oSettings.oClasses.sPagePrevDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button"><span class="'+oSettings.oClasses.sPageJUIPrev+'"></span></a>'+
			'<a class="'+oSettings.oClasses.sPageNextDisabled+'" tabindex="'+oSettings.iTabIndex+'" role="button"><span class="'+oSettings.oClasses.sPageJUINext+'"></span></a>';
		$(nPaging).append( sAppend );
		
		var els = $('a', nPaging);
		var nPrevious = els[0],
			nNext = els[1];
		
		oSettings.oApi._fnBindAction( nPrevious, {action: "previous"}, function() {
			/* Disallow paging event during a current paging event */
			if ( typeof oSettings.iPagingLoopStart != 'undefined' && oSettings.iPagingLoopStart != -1 )
			{
				return;
			}
			
			oSettings.iPagingLoopStart = oSettings._iDisplayStart;
			oSettings.iPagingEnd = oSettings._iDisplayStart - oSettings._iDisplayLength;
			
			/* Correct for underrun */
			if ( oSettings.iPagingEnd < 0 )
			{
			  oSettings.iPagingEnd = 0;
			}
			
			var iTween = $.fn.dataTableExt.oPagination.iTweenTime;
			var innerLoop = function () {
				if ( oSettings.iPagingLoopStart > oSettings.iPagingEnd ) {
					oSettings.iPagingLoopStart--;
					oSettings._iDisplayStart = oSettings.iPagingLoopStart;
					fnCallbackDraw( oSettings );
					setTimeout( function() { innerLoop(); }, iTween );
				} else {
					oSettings.iPagingLoopStart = -1;
				}
			};
			innerLoop();
		} );

		oSettings.oApi._fnBindAction( nNext, {action: "next"}, function() {
			/* Disallow paging event during a current paging event */
			if ( typeof oSettings.iPagingLoopStart != 'undefined' && oSettings.iPagingLoopStart != -1 )
			{
				return;
			}
			
			oSettings.iPagingLoopStart = oSettings._iDisplayStart;
			
			/* Make sure we are not over running the display array */
			if ( oSettings._iDisplayStart + oSettings._iDisplayLength < oSettings.fnRecordsDisplay() )
			{
				oSettings.iPagingEnd = oSettings._iDisplayStart + oSettings._iDisplayLength;
			}
			
			var iTween = $.fn.dataTableExt.oPagination.iTweenTime;
			var innerLoop = function () {
				if ( oSettings.iPagingLoopStart < oSettings.iPagingEnd ) {
					oSettings.iPagingLoopStart++;
					oSettings._iDisplayStart = oSettings.iPagingLoopStart;
					fnCallbackDraw( oSettings );
					setTimeout( function() { innerLoop(); }, iTween );
				} else {
					oSettings.iPagingLoopStart = -1;
				}
			};
			innerLoop();
		} );
	},
	
	"fnUpdate": function ( oSettings, fnCallbackDraw )
	{
		if ( !oSettings.aanFeatures.p )
		{
			return;
		}
		
		/* Loop over each instance of the pager */
		var an = oSettings.aanFeatures.p;
		for ( var i=0, iLen=an.length ; i<iLen ; i++ )
		{
			if ( an[i].childNodes.length !== 0 )
			{
				an[i].childNodes[0].className = 
					( oSettings._iDisplayStart === 0 ) ? 
					oSettings.oClasses.sPagePrevDisabled : oSettings.oClasses.sPagePrevEnabled;
				
				an[i].childNodes[1].className = 
					( oSettings.fnDisplayEnd() == oSettings.fnRecordsDisplay() ) ? 
					oSettings.oClasses.sPageNextDisabled : oSettings.oClasses.sPageNextEnabled;
			}
		}
	}
}

/* Example initialisation */
$(document).ready(function() {
	$('#example').dataTable( {
		"sPaginationType": "scrolling"
	} );
} );

Note that all contributed code is copyright to the original author, unless otherwise stated.