Prettier JQuery tables
[contractdashboard.git] / media / js / jquery.dataTables.js
blob:a/media/js/jquery.dataTables.js -> blob:b/media/js/jquery.dataTables.js
--- a/media/js/jquery.dataTables.js
+++ b/media/js/jquery.dataTables.js
@@ -1,1 +1,6816 @@
+/*
+ * File:        jquery.dataTables.js
+ * Version:     1.7.4
+ * Description: Paginate, search and sort HTML tables
+ * Author:      Allan Jardine (www.sprymedia.co.uk)
+ * Created:     28/3/2008
+ * Language:    Javascript
+ * License:     GPL v2 or BSD 3 point style
+ * Project:     Mtaala
+ * Contact:     allan.jardine@sprymedia.co.uk
+ * 
+ * Copyright 2008-2010 Allan Jardine, all rights reserved.
+ *
+ * This source file is free software, under either the GPL v2 license or a
+ * BSD style license, as supplied with this software.
+ * 
+ * This source file is distributed in the hope that it will be useful, but 
+ * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 
+ * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
+ * 
+ * For details please refer to: http://www.datatables.net
+ */
 
+/*
+ * When considering jsLint, we need to allow eval() as it it is used for reading cookies and 
+ * building the dynamic multi-column sort functions.
+ */
+/*jslint evil: true, undef: true, browser: true */
+/*globals $, jQuery,_fnExternApiFunc,_fnInitalise,_fnLanguageProcess,_fnAddColumn,_fnColumnOptions,_fnAddData,_fnGatherData,_fnDrawHead,_fnDraw,_fnReDraw,_fnAjaxUpdate,_fnAjaxUpdateDraw,_fnAddOptionsHtml,_fnFeatureHtmlTable,_fnScrollDraw,_fnAjustColumnSizing,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnBuildSearchArray,_fnBuildSearchRow,_fnFilterCreateSearch,_fnDataToSearch,_fnSort,_fnSortAttachListener,_fnSortingClasses,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnFeatureHtmlLength,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnNodeToDataIndex,_fnVisbleColumns,_fnCalculateEnd,_fnConvertToWidth,_fnCalculateColumnWidths,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnArrayCmp,_fnDetectType,_fnSettingsFromNode,_fnGetDataMaster,_fnGetTrNodes,_fnGetTdNodes,_fnEscapeRegex,_fnDeleteIndex,_fnReOrderIndex,_fnColumnOrdering,_fnLog,_fnClearTable,_fnSaveState,_fnLoadState,_fnCreateCookie,_fnReadCookie,_fnGetUniqueThs,_fnScrollBarWidth,_fnApplyToChildren,_fnMap*/
+
+(function($, window, document) {
+	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 * Section - DataTables variables
+	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+	
+	/*
+	 * Variable: dataTableSettings
+	 * Purpose:  Store the settings for each dataTables instance
+	 * Scope:    jQuery.fn
+	 */
+	$.fn.dataTableSettings = [];
+	var _aoSettings = $.fn.dataTableSettings; /* Short reference for fast internal lookup */
+	
+	/*
+	 * Variable: dataTableExt
+	 * Purpose:  Container for customisable parts of DataTables
+	 * Scope:    jQuery.fn
+	 */
+	$.fn.dataTableExt = {};
+	var _oExt = $.fn.dataTableExt;
+	
+	
+	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 * Section - DataTables extensible objects
+	 * 
+	 * The _oExt object is used to provide an area where user dfined plugins can be 
+	 * added to DataTables. The following properties of the object are used:
+	 *   oApi - Plug-in API functions
+	 *   aTypes - Auto-detection of types
+	 *   oSort - Sorting functions used by DataTables (based on the type)
+	 *   oPagination - Pagination functions for different input styles
+	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+	
+	/*
+	 * Variable: sVersion
+	 * Purpose:  Version string for plug-ins to check compatibility
+	 * Scope:    jQuery.fn.dataTableExt
+	 * Notes:    Allowed format is a.b.c.d.e where:
+	 *   a:int, b:int, c:int, d:string(dev|beta), e:int. d and e are optional
+	 */
+	_oExt.sVersion = "1.7.4";
+	
+	/*
+	 * Variable: sErrMode
+	 * Purpose:  How should DataTables report an error. Can take the value 'alert' or 'throw'
+	 * Scope:    jQuery.fn.dataTableExt
+	 */
+	_oExt.sErrMode = "alert";
+	
+	/*
+	 * Variable: iApiIndex
+	 * Purpose:  Index for what 'this' index API functions should use
+	 * Scope:    jQuery.fn.dataTableExt
+	 */
+	_oExt.iApiIndex = 0;
+	
+	/*
+	 * Variable: oApi
+	 * Purpose:  Container for plugin API functions
+	 * Scope:    jQuery.fn.dataTableExt
+	 */
+	_oExt.oApi = { };
+	
+	/*
+	 * Variable: aFiltering
+	 * Purpose:  Container for plugin filtering functions
+	 * Scope:    jQuery.fn.dataTableExt
+	 */
+	_oExt.afnFiltering = [ ];
+	
+	/*
+	 * Variable: aoFeatures
+	 * Purpose:  Container for plugin function functions
+	 * Scope:    jQuery.fn.dataTableExt
+	 * Notes:    Array of objects with the following parameters:
+	 *   fnInit: Function for initialisation of Feature. Takes oSettings and returns node
+	 *   cFeature: Character that will be matched in sDom - case sensitive
+	 *   sFeature: Feature name - just for completeness :-)
+	 */
+	_oExt.aoFeatures = [ ];
+	
+	/*
+	 * Variable: ofnSearch
+	 * Purpose:  Container for custom filtering functions
+	 * Scope:    jQuery.fn.dataTableExt
+	 * Notes:    This is an object (the name should match the type) for custom filtering function,
+	 *   which can be used for live DOM checking or formatted text filtering
+	 */
+	_oExt.ofnSearch = { };
+	
+	/*
+	 * Variable: afnSortData
+	 * Purpose:  Container for custom sorting data source functions
+	 * Scope:    jQuery.fn.dataTableExt
+	 * Notes:    Array (associative) of functions which is run prior to a column of this 
+	 *   'SortDataType' being sorted upon.
+	 *   Function input parameters:
+	 *     object:oSettings-  DataTables settings object
+	 *     int:iColumn - Target column number
+	 *   Return value: Array of data which exactly matched the full data set size for the column to
+	 *     be sorted upon
+	 */
+	_oExt.afnSortData = [ ];
+	
+	/*
+	 * Variable: oStdClasses
+	 * Purpose:  Storage for the various classes that DataTables uses
+	 * Scope:    jQuery.fn.dataTableExt
+	 */
+	_oExt.oStdClasses = {
+		/* Two buttons buttons */
+		"sPagePrevEnabled": "paginate_enabled_previous",
+		"sPagePrevDisabled": "paginate_disabled_previous",
+		"sPageNextEnabled": "paginate_enabled_next",
+		"sPageNextDisabled": "paginate_disabled_next",
+		"sPageJUINext": "",
+		"sPageJUIPrev": "",
+		
+		/* Full numbers paging buttons */
+		"sPageButton": "paginate_button",
+		"sPageButtonActive": "paginate_active",
+		"sPageButtonStaticDisabled": "paginate_button",
+		"sPageFirst": "first",
+		"sPagePrevious": "previous",
+		"sPageNext": "next",
+		"sPageLast": "last",
+		
+		/* Stripping classes */
+		"sStripOdd": "odd",
+		"sStripEven": "even",
+		
+		/* Empty row */
+		"sRowEmpty": "dataTables_empty",
+		
+		/* Features */
+		"sWrapper": "dataTables_wrapper",
+		"sFilter": "dataTables_filter",
+		"sInfo": "dataTables_info",
+		"sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
+		"sLength": "dataTables_length",
+		"sProcessing": "dataTables_processing",
+		
+		/* Sorting */
+		"sSortAsc": "sorting_asc",
+		"sSortDesc": "sorting_desc",
+		"sSortable": "sorting", /* Sortable in both directions */
+		"sSortableAsc": "sorting_asc_disabled",
+		"sSortableDesc": "sorting_desc_disabled",
+		"sSortableNone": "sorting_disabled",
+		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
+		"sSortJUIAsc": "",
+		"sSortJUIDesc": "",
+		"sSortJUI": "",
+		"sSortJUIAscAllowed": "",
+		"sSortJUIDescAllowed": "",
+		"sSortJUIWrapper": "",
+		
+		/* Scrolling */
+		"sScrollWrapper": "dataTables_scroll",
+		"sScrollHead": "dataTables_scrollHead",
+		"sScrollHeadInner": "dataTables_scrollHeadInner",
+		"sScrollBody": "dataTables_scrollBody",
+		"sScrollFoot": "dataTables_scrollFoot",
+		"sScrollFootInner": "dataTables_scrollFootInner",
+		
+		/* Misc */
+		"sFooterTH": ""
+	};
+	
+	/*
+	 * Variable: oJUIClasses
+	 * Purpose:  Storage for the various classes that DataTables uses - jQuery UI suitable
+	 * Scope:    jQuery.fn.dataTableExt
+	 */
+	_oExt.oJUIClasses = {
+		/* Two buttons buttons */
+		"sPagePrevEnabled": "fg-button ui-button ui-state-default ui-corner-left",
+		"sPagePrevDisabled": "fg-button ui-button ui-state-default ui-corner-left ui-state-disabled",
+		"sPageNextEnabled": "fg-button ui-button ui-state-default ui-corner-right",
+		"sPageNextDisabled": "fg-button ui-button ui-state-default ui-corner-right ui-state-disabled",
+		"sPageJUINext": "ui-icon ui-icon-circle-arrow-e",
+		"sPageJUIPrev": "ui-icon ui-icon-circle-arrow-w",
+		
+		/* Full numbers paging buttons */
+		"sPageButton": "fg-button ui-button ui-state-default",
+		"sPageButtonActive": "fg-button ui-button ui-state-default ui-state-disabled",
+		"sPageButtonStaticDisabled": "fg-button ui-button ui-state-default ui-state-disabled",
+		"sPageFirst": "first ui-corner-tl ui-corner-bl",
+		"sPagePrevious": "previous",
+		"sPageNext": "next",
+		"sPageLast": "last ui-corner-tr ui-corner-br",
+		
+		/* Stripping classes */
+		"sStripOdd": "odd",
+		"sStripEven": "even",
+		
+		/* Empty row */
+		"sRowEmpty": "dataTables_empty",
+		
+		/* Features */
+		"sWrapper": "dataTables_wrapper",
+		"sFilter": "dataTables_filter",
+		"sInfo": "dataTables_info",
+		"sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
+			"ui-buttonset-multi paging_", /* Note that the type is postfixed */
+		"sLength": "dataTables_length",
+		"sProcessing": "dataTables_processing",
+		
+		/* Sorting */
+		"sSortAsc": "ui-state-default",
+		"sSortDesc": "ui-state-default",
+		"sSortable": "ui-state-default",
+		"sSortableAsc": "ui-state-default",
+		"sSortableDesc": "ui-state-default",
+		"sSortableNone": "ui-state-default",
+		"sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
+		"sSortJUIAsc": "css_right ui-icon ui-icon-triangle-1-n",
+		"sSortJUIDesc": "css_right ui-icon ui-icon-triangle-1-s",
+		"sSortJUI": "css_right ui-icon ui-icon-carat-2-n-s",
+		"sSortJUIAscAllowed": "css_right ui-icon ui-icon-carat-1-n",
+		"sSortJUIDescAllowed": "css_right ui-icon ui-icon-carat-1-s",
+		"sSortJUIWrapper": "DataTables_sort_wrapper",
+		
+		/* Scrolling */
+		"sScrollWrapper": "dataTables_scroll",
+		"sScrollHead": "dataTables_scrollHead ui-state-default",
+		"sScrollHeadInner": "dataTables_scrollHeadInner",
+		"sScrollBody": "dataTables_scrollBody",
+		"sScrollFoot": "dataTables_scrollFoot ui-state-default",
+		"sScrollFootInner": "dataTables_scrollFootInner",
+		
+		/* Misc */
+		"sFooterTH": "ui-state-default"
+	};
+	
+	/*
+	 * Variable: oPagination
+	 * Purpose:  Container for the various type of pagination that dataTables supports
+	 * Scope:    jQuery.fn.dataTableExt
+	 */
+	_oExt.oPagination = {
+		/*
+		 * Variable: two_button
+		 * Purpose:  Standard two button (forward/back) pagination
+	 	 * Scope:    jQuery.fn.dataTableExt.oPagination
+		 */
+		"two_button": {
+			/*
+			 * Function: oPagination.two_button.fnInit
+			 * Purpose:  Initalise dom elements required for pagination with forward/back buttons only
+			 * 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 nPrevious, nNext, nPreviousInner, nNextInner;
+				
+				/* Store the next and previous elements in the oSettings object as they can be very
+				 * usful for automation - particularly testing
+				 */
+				if ( !oSettings.bJUI )
+				{
+					nPrevious = document.createElement( 'div' );
+					nNext = document.createElement( 'div' );
+				}
+				else
+				{
+					nPrevious = document.createElement( 'a' );
+					nNext = document.createElement( 'a' );
+					
+					nNextInner = document.createElement('span');
+					nNextInner.className = oSettings.oClasses.sPageJUINext;
+					nNext.appendChild( nNextInner );
+					
+					nPreviousInner = document.createElement('span');
+					nPreviousInner.className = oSettings.oClasses.sPageJUIPrev;
+					nPrevious.appendChild( nPreviousInner );
+				}
+				
+				nPrevious.className = oSettings.oClasses.sPagePrevDisabled;
+				nNext.className = oSettings.oClasses.sPageNextDisabled;
+				
+				nPrevious.title = oSettings.oLanguage.oPaginate.sPrevious;
+				nNext.title = oSettings.oLanguage.oPaginate.sNext;
+				
+				nPaging.appendChild( nPrevious );
+				nPaging.appendChild( nNext );
+				
+				$(nPrevious).click( function() {
+					if ( oSettings.oApi._fnPageChange( oSettings, "previous" ) )
+					{
+						/* Only draw when the page has actually changed */
+						fnCallbackDraw( oSettings );
+					}
+				} );
+				
+				$(nNext).click( function() {
+					if ( oSettings.oApi._fnPageChange( oSettings, "next" ) )
+					{
+						fnCallbackDraw( oSettings );
+					}
+				} );
+				
+				/* Take the brutal approach to cancelling text selection */
+				$(nPrevious).bind( 'selectstart', function () { return false; } );
+				$(nNext).bind( 'selectstart', function () { return false; } );
+				
+				/* ID the first elements only */
+				if ( oSettings.sTableId !== '' && typeof oSettings.aanFeatures.p == "undefined" )
+				{
+					nPaging.setAttribute( 'id', oSettings.sTableId+'_paginate' );
+					nPrevious.setAttribute( 'id', oSettings.sTableId+'_previous' );
+					nNext.setAttribute( 'id', oSettings.sTableId+'_next' );
+				}
+			},
+			
+			/*
+			 * Function: oPagination.two_button.fnUpdate
+			 * Purpose:  Update the two button pagination at the end of the draw
+			 * Returns:  -
+	 		 * Inputs:   object:oSettings - dataTables settings object
+			 *           function:fnCallbackDraw - draw function to call on page change
+			 */
+			"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;
+					}
+				}
+			}
+		},
+		
+		
+		/*
+		 * Variable: iFullNumbersShowPages
+		 * Purpose:  Change the number of pages which can be seen
+	 	 * Scope:    jQuery.fn.dataTableExt.oPagination
+		 */
+		"iFullNumbersShowPages": 5,
+		
+		/*
+		 * Variable: full_numbers
+		 * Purpose:  Full numbers pagination
+	 	 * Scope:    jQuery.fn.dataTableExt.oPagination
+		 */
+		"full_numbers": {
+			/*
+			 * Function: oPagination.full_numbers.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 )
+			{
+				var nFirst = document.createElement( 'span' );
+				var nPrevious = document.createElement( 'span' );
+				var nList = document.createElement( 'span' );
+				var nNext = document.createElement( 'span' );
+				var nLast = 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;
+				
+				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).click( function () {
+					if ( oSettings.oApi._fnPageChange( oSettings, "first" ) )
+					{
+						fnCallbackDraw( oSettings );
+					}
+				} );
+				
+				$(nPrevious).click( function() {
+					if ( oSettings.oApi._fnPageChange( oSettings, "previous" ) )
+					{
+						fnCallbackDraw( oSettings );
+					}
+				} );
+				
+				$(nNext).click( function() {
+					if ( oSettings.oApi._fnPageChange( oSettings, "next" ) )
+					{
+						fnCallbackDraw( oSettings );
+					}
+				} );
+				
+				$(nLast).click( function() {
+					if ( oSettings.oApi._fnPageChange( oSettings, "last" ) )
+					{
+						fnCallbackDraw( oSettings );
+					}
+				} );
+				
+				/* Take the brutal approach to cancelling text selection */
+				$('span', nPaging)
+					.bind( 'mousedown', function () { return false; } )
+					.bind( 'selectstart', 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' );
+				}
+			},
+			
+			/*
+			 * Function: oPagination.full_numbers.fnUpdate
+			 * Purpose:  Update the list of page buttons shows
+			 * Returns:  -
+	 		 * Inputs:   object:oSettings - dataTables settings object
+			 *           function:fnCallbackDraw - draw function to call on page change
+			 */
+			"fnUpdate": function ( oSettings, fnCallbackDraw )
+			{
+				if ( !oSettings.aanFeatures.p )
+				{
+					return;
+				}
+				
+				var iPageCount = _oExt.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 += '<span class="'+oClasses.sPageButton+'">'+i+'</span>';
+					}
+					else
+					{
+						sList += '<span class="'+oClasses.sPageButtonActive+'">'+i+'</span>';
+					}
+				}
+				
+				/* Loop over each instance of the pager */
+				var an = oSettings.aanFeatures.p;
+				var anButtons, anStatic, nPaginateList;
+				var fnClick = function() {
+					/* 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 );
+					return false;
+				};
+				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(2)', an[i]);
+					qjPaginateList.html( sList );
+					$('span', qjPaginateList).click( fnClick ).bind( 'mousedown', fnFalse )
+						.bind( 'selectstart', fnFalse );
+					
+					/* Update the 'premanent botton's classes */
+					anButtons = an[i].getElementsByTagName('span');
+					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;
+					}
+				}
+			}
+		}
+	};
+	
+	/*
+	 * Variable: oSort
+	 * Purpose:  Wrapper for the sorting functions that can be used in DataTables
+	 * Scope:    jQuery.fn.dataTableExt
+	 * Notes:    The functions provided in this object are basically standard javascript sort
+	 *   functions - they expect two inputs which they then compare and then return a priority
+	 *   result. For each sort method added, two functions need to be defined, an ascending sort and
+	 *   a descending sort.
+	 */
+	_oExt.oSort = {
+		/*
+		 * text sorting
+		 */
+		"string-asc": function ( a, b )
+		{
+			var x = a.toLowerCase();
+			var y = b.toLowerCase();
+			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+		},
+		
+		"string-desc": function ( a, b )
+		{
+			var x = a.toLowerCase();
+			var y = b.toLowerCase();
+			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
+		},
+		
+		
+		/*
+		 * html sorting (ignore html tags)
+		 */
+		"html-asc": function ( a, b )
+		{
+			var x = a.replace( /<.*?>/g, "" ).toLowerCase();
+			var y = b.replace( /<.*?>/g, "" ).toLowerCase();
+			return ((x < y) ? -1 : ((x > y) ? 1 : 0));
+		},
+		
+		"html-desc": function ( a, b )
+		{
+			var x = a.replace( /<.*?>/g, "" ).toLowerCase();
+			var y = b.replace( /<.*?>/g, "" ).toLowerCase();
+			return ((x < y) ? 1 : ((x > y) ? -1 : 0));
+		},
+		
+		
+		/*
+		 * date sorting
+		 */
+		"date-asc": function ( a, b )
+		{
+			var x = Date.parse( a );
+			var y = Date.parse( b );
+			
+			if ( isNaN(x) || x==="" )
+			{
+    		x = Date.parse( "01/01/1970 00:00:00" );
+			}
+			if ( isNaN(y) || y==="" )
+			{
+				y =	Date.parse( "01/01/1970 00:00:00" );
+			}
+			
+			return x - y;
+		},
+		
+		"date-desc": function ( a, b )
+		{
+			var x = Date.parse( a );
+			var y = Date.parse( b );
+			
+			if ( isNaN(x) || x==="" )
+			{
+    		x = Date.parse( "01/01/1970 00:00:00" );
+			}
+			if ( isNaN(y) || y==="" )
+			{
+				y =	Date.parse( "01/01/1970 00:00:00" );
+			}
+			
+			return y - x;
+		},
+		
+		
+		/*
+		 * numerical sorting
+		 */
+		"numeric-asc": function ( a, b )
+		{
+			var x = (a=="-" || a==="") ? 0 : a*1;
+			var y = (b=="-" || b==="") ? 0 : b*1;
+			return x - y;
+		},
+		
+		"numeric-desc": function ( a, b )
+		{
+			var x = (a=="-" || a==="") ? 0 : a*1;
+			var y = (b=="-" || b==="") ? 0 : b*1;
+			return y - x;
+		}
+	};
+	
+	
+	/*
+	 * Variable: aTypes
+	 * Purpose:  Container for the various type of type detection that dataTables supports
+	 * Scope:    jQuery.fn.dataTableExt
+	 * Notes:    The functions in this array are expected to parse a string to see if it is a data
+	 *   type that it recognises. If so then the function should return the name of the type (a
+	 *   corresponding sort function should be defined!), if the type is not recognised then the
+	 *   function should return null such that the parser and move on to check the next type.
+	 *   Note that ordering is important in this array - the functions are processed linearly,
+	 *   starting at index 0.
+	 *   Note that the input for these functions is always a string! It cannot be any other data
+	 *   type
+	 */
+	_oExt.aTypes = [
+		/*
+		 * Function: -
+		 * Purpose:  Check to see if a string is numeric
+		 * Returns:  string:'numeric' or null
+		 * Inputs:   string:sText - string to check
+		 */
+		function ( sData )
+		{
+			/* Allow zero length strings as a number */
+			if ( sData.length === 0 )
+			{
+				return 'numeric';
+			}
+			
+			var sValidFirstChars = "0123456789-";
+			var sValidChars = "0123456789.";
+			var Char;
+			var bDecimal = false;
+			
+			/* Check for a valid first char (no period and allow negatives) */
+			Char = sData.charAt(0); 
+			if (sValidFirstChars.indexOf(Char) == -1) 
+			{
+				return null;
+			}
+			
+			/* Check all the other characters are valid */
+			for ( var i=1 ; i<sData.length ; i++ ) 
+			{
+				Char = sData.charAt(i); 
+				if (sValidChars.indexOf(Char) == -1) 
+				{
+					return null;
+				}
+				
+				/* Only allowed one decimal place... */
+				if ( Char == "." )
+				{
+					if ( bDecimal )
+					{
+						return null;
+					}
+					bDecimal = true;
+				}
+			}
+			
+			return 'numeric';
+		},
+		
+		/*
+		 * Function: -
+		 * Purpose:  Check to see if a string is actually a formatted date
+		 * Returns:  string:'date' or null
+		 * Inputs:   string:sText - string to check
+		 */
+		function ( sData )
+		{
+			var iParse = Date.parse(sData);
+			if ( (iParse !== null && !isNaN(iParse)) || sData.length === 0 )
+			{
+				return 'date';
+			}
+			return null;
+		},
+		
+		/*
+		 * Function: -
+		 * Purpose:  Check to see if a string should be treated as an HTML string
+		 * Returns:  string:'html' or null
+		 * Inputs:   string:sText - string to check
+		 */
+		function ( sData )
+		{
+			if ( sData.indexOf('<') != -1 && sData.indexOf('>') != -1 )
+			{
+				return 'html';
+			}
+			return null;
+		}
+	];
+	
+	/*
+	 * Function: fnVersionCheck
+	 * Purpose:  Check a version string against this version of DataTables. Useful for plug-ins
+	 * Returns:  bool:true -this version of DataTables is greater or equal to the required version
+	 *                false -this version of DataTales is not suitable
+	 * Inputs:   string:sVersion - the version to check against. May be in the following formats:
+	 *             "a", "a.b" or "a.b.c"
+	 * Notes:    This function will only check the first three parts of a version string. It is
+	 *   assumed that beta and dev versions will meet the requirements. This might change in future
+	 */
+	_oExt.fnVersionCheck = function( sVersion )
+	{
+		/* This is cheap, but very effective */
+		var fnZPad = function (Zpad, count)
+		{
+			while(Zpad.length < count) {
+				Zpad += '0';
+			}
+			return Zpad;
+		};
+		var aThis = _oExt.sVersion.split('.');
+		var aThat = sVersion.split('.');
+		var sThis = '', sThat = '';
+		
+		for ( var i=0, iLen=aThat.length ; i<iLen ; i++ )
+		{
+			sThis += fnZPad( aThis[i], 3 );
+			sThat += fnZPad( aThat[i], 3 );
+		}
+		
+		return parseInt(sThis, 10) >= parseInt(sThat, 10);
+	};
+	
+	/*
+	 * Variable: _oExternConfig
+	 * Purpose:  Store information for DataTables to access globally about other instances
+	 * Scope:    jQuery.fn.dataTableExt
+	 */
+	_oExt._oExternConfig = {
+		/* int:iNextUnique - next unique number for an instance */
+		"iNextUnique": 0
+	};
+	
+	
+	/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
+	 * Section - DataTables prototype
+	 * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
+	
+	/*
+	 * Function: dataTable
+	 * Purpose:  DataTables information
+	 * Returns:  -
+	 * Inputs:   object:oInit - initalisation options for the table
+	 */
+	$.fn.dataTable = function( oInit )
+	{
+		/*
+		 * Function: classSettings
+		 * Purpose:  Settings container function for all 'class' properties which are required
+		 *   by dataTables
+		 * Returns:  -
+		 * Inputs:   -
+		 */
+		function classSettings ()
+		{
+			this.fnRecordsTotal = function ()
+			{
+				if ( this.oFeatures.bServerSide ) {
+					return parseInt(this._iRecordsTotal, 10);
+				} else {
+					return this.aiDisplayMaster.length;
+				}
+			};
+			
+			this.fnRecordsDisplay = function ()
+			{
+				if ( this.oFeatures.bServerSide ) {
+					return parseInt(this._iRecordsDisplay, 10);
+				} else {
+					return this.aiDisplay.length;
+				}
+			};
+			
+			this.fnDisplayEnd = function ()
+			{