Upgrade datatables, load courses over ajax
[oweals/karmaworld.git] / karmaworld / assets / js / jquery.dataTables.js
1 /*! DataTables 1.10.0
2  * ©2008-2014 SpryMedia Ltd - datatables.net/license
3  */
4
5 /**
6  * @summary     DataTables
7  * @description Paginate, search and order HTML tables
8  * @version     1.10.0
9  * @file        jquery.dataTables.js
10  * @author      SpryMedia Ltd (www.sprymedia.co.uk)
11  * @contact     www.sprymedia.co.uk/contact
12  * @copyright   Copyright 2008-2014 SpryMedia Ltd.
13  *
14  * This source file is free software, available under the following license:
15  *   MIT license - http://datatables.net/license
16  *
17  * This source file is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19  * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
20  *
21  * For details please refer to: http://www.datatables.net
22  */
23
24 /*jslint evil: true, undef: true, browser: true */
25 /*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidateRow,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnScrollBarWidth,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
26
27 (/** @lends <global> */function( window, document, undefined ) {
28
29 (function( factory ) {
30         "use strict";
31
32         if ( typeof define === 'function' && define.amd ) {
33                 // Define as an AMD module if possible
34                 define( 'datatables', ['jquery'], factory );
35         }
36     else if ( typeof exports === 'object' ) {
37         // Node/CommonJS
38         factory( require( 'jquery' ) );
39     }
40         else if ( jQuery && !jQuery.fn.dataTable ) {
41                 // Define using browser globals otherwise
42                 // Prevent multiple instantiations if the script is loaded twice
43                 factory( jQuery );
44         }
45 }
46 (/** @lends <global> */function( $ ) {
47         "use strict";
48
49         /**
50          * DataTables is a plug-in for the jQuery Javascript library. It is a highly
51          * flexible tool, based upon the foundations of progressive enhancement,
52          * which will add advanced interaction controls to any HTML table. For a
53          * full list of features please refer to
54          * [DataTables.net](href="http://datatables.net).
55          *
56          * Note that the `DataTable` object is not a global variable but is aliased
57          * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
58          * be  accessed.
59          *
60          *  @class
61          *  @param {object} [init={}] Configuration object for DataTables. Options
62          *    are defined by {@link DataTable.defaults}
63          *  @requires jQuery 1.7+
64          *
65          *  @example
66          *    // Basic initialisation
67          *    $(document).ready( function {
68          *      $('#example').dataTable();
69          *    } );
70          *
71          *  @example
72          *    // Initialisation with configuration options - in this case, disable
73          *    // pagination and sorting.
74          *    $(document).ready( function {
75          *      $('#example').dataTable( {
76          *        "paginate": false,
77          *        "sort": false
78          *      } );
79          *    } );
80          */
81         var DataTable;
82
83         
84         /*
85          * It is useful to have variables which are scoped locally so only the
86          * DataTables functions can access them and they don't leak into global space.
87          * At the same time these functions are often useful over multiple files in the
88          * core and API, so we list, or at least document, all variables which are used
89          * by DataTables as private variables here. This also ensures that there is no
90          * clashing of variable names and that they can easily referenced for reuse.
91          */
92         
93         
94         // Defined else where
95         //  _selector_run
96         //  _selector_opts
97         //  _selector_first
98         //  _selector_row_indexes
99         
100         var _ext; // DataTable.ext
101         var _Api; // DataTable.Api
102         var _api_register; // DataTable.Api.register
103         var _api_registerPlural; // DataTable.Api.registerPlural
104         
105         var _re_dic = {};
106         var _re_new_lines = /[\r\n]/g;
107         var _re_html = /<.*?>/g;
108         var _re_date_start = /^[\d\+\-a-zA-Z]/;
109         
110         // Escape regular expression special characters
111         var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
112         
113         // U+2009 is thin space and U+202F is narrow no-break space, both used in many
114         // standards as thousands separators
115         var _re_formatted_numeric = /[',$£€¥%\u2009\u202F]/g;
116         
117         
118         var _empty = function ( d ) {
119                 return !d || d === '-' ? true : false;
120         };
121         
122         
123         var _intVal = function ( s ) {
124                 var integer = parseInt( s, 10 );
125                 return !isNaN(integer) && isFinite(s) ? integer : null;
126         };
127         
128         // Convert from a formatted number with characters other than `.` as the
129         // decimal place, to a Javascript number
130         var _numToDecimal = function ( num, decimalPoint ) {
131                 // Cache created regular expressions for speed as this function is called often
132                 if ( ! _re_dic[ decimalPoint ] ) {
133                         _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
134                 }
135                 return typeof num === 'string' ?
136                         num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
137                         num;
138         };
139         
140         
141         var _isNumber = function ( d, decimalPoint, formatted ) {
142                 var strType = typeof d === 'string';
143         
144                 if ( decimalPoint && strType ) {
145                         d = _numToDecimal( d, decimalPoint );
146                 }
147         
148                 if ( formatted && strType ) {
149                         d = d.replace( _re_formatted_numeric, '' );
150                 }
151         
152                 return !d || d==='-' || (!isNaN( parseFloat(d) ) && isFinite( d ));
153         };
154         
155         
156         // A string without HTML in it can be considered to be HTML still
157         var _isHtml = function ( d ) {
158                 return !d || typeof d === 'string';
159         };
160         
161         
162         var _htmlNumeric = function ( d, decimalPoint, formatted ) {
163                 if ( _empty( d ) ) {
164                         return true;
165                 }
166         
167                 var html = _isHtml( d );
168                 return ! html ?
169                         null :
170                         _isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
171                                 true :
172                                 null;
173         };
174         
175         
176         var _pluck = function ( a, prop, prop2 ) {
177                 var out = [];
178                 var i=0, ien=a.length;
179         
180                 // Could have the test in the loop for slightly smaller code, but speed
181                 // is essential here
182                 if ( prop2 !== undefined ) {
183                         for ( ; i<ien ; i++ ) {
184                                 if ( a[i] && a[i][ prop ] ) {
185                                         out.push( a[i][ prop ][ prop2 ] );
186                                 }
187                         }
188                 }
189                 else {
190                         for ( ; i<ien ; i++ ) {
191                                 if ( a[i] ) {
192                                         out.push( a[i][ prop ] );
193                                 }
194                         }
195                 }
196         
197                 return out;
198         };
199         
200         
201         // Basically the same as _pluck, but rather than looping over `a` we use `order`
202         // as the indexes to pick from `a`
203         var _pluck_order = function ( a, order, prop, prop2 )
204         {
205                 var out = [];
206                 var i=0, ien=order.length;
207         
208                 // Could have the test in the loop for slightly smaller code, but speed
209                 // is essential here
210                 if ( prop2 !== undefined ) {
211                         for ( ; i<ien ; i++ ) {
212                                 out.push( a[ order[i] ][ prop ][ prop2 ] );
213                         }
214                 }
215                 else {
216                         for ( ; i<ien ; i++ ) {
217                                 out.push( a[ order[i] ][ prop ] );
218                         }
219                 }
220         
221                 return out;
222         };
223         
224         
225         var _range = function ( len, start )
226         {
227                 var out = [];
228                 var end;
229         
230                 if ( start === undefined ) {
231                         start = 0;
232                         end = len;
233                 }
234                 else {
235                         end = start;
236                         start = len;
237                 }
238         
239                 for ( var i=start ; i<end ; i++ ) {
240                         out.push( i );
241                 }
242         
243                 return out;
244         };
245         
246         
247         var _stripHtml = function ( d ) {
248                 return d.replace( _re_html, '' );
249         };
250         
251         
252         /**
253          * Find the unique elements in a source array.
254          *
255          * @param  {array} src Source array
256          * @return {array} Array of unique items
257          * @ignore
258          */
259         var _unique = function ( src )
260         {
261                 // A faster unique method is to use object keys to identify used values,
262                 // but this doesn't work with arrays or objects, which we must also
263                 // consider. See jsperf.com/compare-array-unique-versions/4 for more
264                 // information.
265                 var
266                         out = [],
267                         val,
268                         i, ien=src.length,
269                         j, k=0;
270         
271                 again: for ( i=0 ; i<ien ; i++ ) {
272                         val = src[i];
273         
274                         for ( j=0 ; j<k ; j++ ) {
275                                 if ( out[j] === val ) {
276                                         continue again;
277                                 }
278                         }
279         
280                         out.push( val );
281                         k++;
282                 }
283         
284                 return out;
285         };
286         
287         
288         
289         /**
290          * Create a mapping object that allows camel case parameters to be looked up
291          * for their Hungarian counterparts. The mapping is stored in a private
292          * parameter called `_hungarianMap` which can be accessed on the source object.
293          *  @param {object} o
294          *  @memberof DataTable#oApi
295          */
296         function _fnHungarianMap ( o )
297         {
298                 var
299                         hungarian = 'a aa ai ao as b fn i m o s ',
300                         match,
301                         newKey,
302                         map = {};
303         
304                 $.each( o, function (key, val) {
305                         match = key.match(/^([^A-Z]+?)([A-Z])/);
306         
307                         if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
308                         {
309                                 newKey = key.replace( match[0], match[2].toLowerCase() );
310                                 map[ newKey ] = key;
311         
312                                 //console.log( key, match );
313                                 if ( match[1] === 'o' )
314                                 {
315                                         _fnHungarianMap( o[key] );
316                                 }
317                         }
318                 } );
319         
320                 o._hungarianMap = map;
321         }
322         
323         
324         /**
325          * Convert from camel case parameters to Hungarian, based on a Hungarian map
326          * created by _fnHungarianMap.
327          *  @param {object} src The model object which holds all parameters that can be
328          *    mapped.
329          *  @param {object} user The object to convert from camel case to Hungarian.
330          *  @param {boolean} force When set to `true`, properties which already have a
331          *    Hungarian value in the `user` object will be overwritten. Otherwise they
332          *    won't be.
333          *  @memberof DataTable#oApi
334          */
335         function _fnCamelToHungarian ( src, user, force )
336         {
337                 if ( ! src._hungarianMap ) {
338                         _fnHungarianMap( src );
339                 }
340         
341                 var hungarianKey;
342         
343                 $.each( user, function (key, val) {
344                         hungarianKey = src._hungarianMap[ key ];
345         
346                         if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
347                         {
348                                 // For objects, we need to buzz down into the object to copy parameters
349                                 if ( hungarianKey.charAt(0) === 'o' )
350                                 {
351                                         // Copy the camelCase options over to the hungarian
352                                         if ( ! user[ hungarianKey ] ) {
353                                                 user[ hungarianKey ] = {};
354                                         }
355                                         $.extend( true, user[hungarianKey], user[key] );
356         
357                                         _fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
358                                 }
359                                 else {
360                                         user[hungarianKey] = user[ key ];
361                                 }
362                         }
363                 } );
364         }
365         
366         
367         /**
368          * Language compatibility - when certain options are given, and others aren't, we
369          * need to duplicate the values over, in order to provide backwards compatibility
370          * with older language files.
371          *  @param {object} oSettings dataTables settings object
372          *  @memberof DataTable#oApi
373          */
374         function _fnLanguageCompat( lang )
375         {
376                 var defaults = DataTable.defaults.oLanguage;
377                 var zeroRecords = lang.sZeroRecords;
378         
379                 /* Backwards compatibility - if there is no sEmptyTable given, then use the same as
380                  * sZeroRecords - assuming that is given.
381                  */
382                 if ( ! lang.sEmptyTable && zeroRecords &&
383                         defaults.sEmptyTable === "No data available in table" )
384                 {
385                         _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
386                 }
387         
388                 /* Likewise with loading records */
389                 if ( ! lang.sLoadingRecords && zeroRecords &&
390                         defaults.sLoadingRecords === "Loading..." )
391                 {
392                         _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
393                 }
394         
395                 // Old parameter name of the thousands separator mapped onto the new
396                 if ( lang.sInfoThousands ) {
397                         lang.sThousands = lang.sInfoThousands;
398                 }
399         
400                 var decimal = lang.sDecimal;
401                 if ( decimal ) {
402                         _addNumericSort( decimal );
403                 }
404         }
405         
406         
407         /**
408          * Map one parameter onto another
409          *  @param {object} o Object to map
410          *  @param {*} knew The new parameter name
411          *  @param {*} old The old parameter name
412          */
413         var _fnCompatMap = function ( o, knew, old ) {
414                 if ( o[ knew ] !== undefined ) {
415                         o[ old ] = o[ knew ];
416                 }
417         };
418         
419         
420         /**
421          * Provide backwards compatibility for the main DT options. Note that the new
422          * options are mapped onto the old parameters, so this is an external interface
423          * change only.
424          *  @param {object} init Object to map
425          */
426         function _fnCompatOpts ( init )
427         {
428                 _fnCompatMap( init, 'ordering',      'bSort' );
429                 _fnCompatMap( init, 'orderMulti',    'bSortMulti' );
430                 _fnCompatMap( init, 'orderClasses',  'bSortClasses' );
431                 _fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
432                 _fnCompatMap( init, 'order',         'aaSorting' );
433                 _fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
434                 _fnCompatMap( init, 'paging',        'bPaginate' );
435                 _fnCompatMap( init, 'pagingType',    'sPaginationType' );
436                 _fnCompatMap( init, 'pageLength',    'iDisplayLength' );
437                 _fnCompatMap( init, 'searching',     'bFilter' );
438         }
439         
440         
441         /**
442          * Provide backwards compatibility for column options. Note that the new options
443          * are mapped onto the old parameters, so this is an external interface change
444          * only.
445          *  @param {object} init Object to map
446          */
447         function _fnCompatCols ( init )
448         {
449                 _fnCompatMap( init, 'orderable',     'bSortable' );
450                 _fnCompatMap( init, 'orderData',     'aDataSort' );
451                 _fnCompatMap( init, 'orderSequence', 'asSorting' );
452                 _fnCompatMap( init, 'orderDataType', 'sortDataType' );
453         }
454         
455         
456         /**
457          * Browser feature detection for capabilities, quirks
458          *  @param {object} settings dataTables settings object
459          *  @memberof DataTable#oApi
460          */
461         function _fnBrowserDetect( settings )
462         {
463                 var browser = settings.oBrowser;
464         
465                 // Scrolling feature / quirks detection
466                 var n = $('<div/>')
467                         .css( {
468                                 position: 'absolute',
469                                 top: 0,
470                                 left: 0,
471                                 height: 1,
472                                 width: 1,
473                                 overflow: 'hidden'
474                         } )
475                         .append(
476                                 $('<div/>')
477                                         .css( {
478                                                 position: 'absolute',
479                                                 top: 1,
480                                                 left: 1,
481                                                 width: 100,
482                                                 overflow: 'scroll'
483                                         } )
484                                         .append(
485                                                 $('<div class="test"/>')
486                                                         .css( {
487                                                                 width: '100%',
488                                                                 height: 10
489                                                         } )
490                                         )
491                         )
492                         .appendTo( 'body' );
493         
494                 var test = n.find('.test');
495         
496                 // IE6/7 will oversize a width 100% element inside a scrolling element, to
497                 // include the width of the scrollbar, while other browsers ensure the inner
498                 // element is contained without forcing scrolling
499                 browser.bScrollOversize = test[0].offsetWidth === 100;
500         
501                 // In rtl text layout, some browsers (most, but not all) will place the
502                 // scrollbar on the left, rather than the right.
503                 browser.bScrollbarLeft = test.offset().left !== 1;
504         
505                 n.remove();
506         }
507         
508         
509         /**
510          * Array.prototype reduce[Right] method, used for browsers which don't support
511          * JS 1.6. Done this way to reduce code size, since we iterate either way
512          *  @param {object} settings dataTables settings object
513          *  @memberof DataTable#oApi
514          */
515         function _fnReduce ( that, fn, init, start, end, inc )
516         {
517                 var
518                         i = start,
519                         value,
520                         isSet = false;
521         
522                 if ( init !== undefined ) {
523                         value = init;
524                         isSet = true;
525                 }
526         
527                 while ( i !== end ) {
528                         if ( ! that.hasOwnProperty(i) ) {
529                                 continue;
530                         }
531         
532                         value = isSet ?
533                                 fn( value, that[i], i, that ) :
534                                 that[i];
535         
536                         isSet = true;
537                         i += inc;
538                 }
539         
540                 return value;
541         }
542         
543         /**
544          * Add a column to the list used for the table with default values
545          *  @param {object} oSettings dataTables settings object
546          *  @param {node} nTh The th element for this column
547          *  @memberof DataTable#oApi
548          */
549         function _fnAddColumn( oSettings, nTh )
550         {
551                 // Add column to aoColumns array
552                 var oDefaults = DataTable.defaults.column;
553                 var iCol = oSettings.aoColumns.length;
554                 var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
555                         "nTh": nTh ? nTh : document.createElement('th'),
556                         "sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
557                         "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
558                         "mData": oDefaults.mData ? oDefaults.mData : iCol,
559                         idx: iCol
560                 } );
561                 oSettings.aoColumns.push( oCol );
562         
563                 // Add search object for column specific search. Note that the `searchCols[ iCol ]`
564                 // passed into extend can be undefined. This allows the user to give a default
565                 // with only some of the parameters defined, and also not give a default
566                 var searchCols = oSettings.aoPreSearchCols;
567                 searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
568         
569                 // Use the default column options function to initialise classes etc
570                 _fnColumnOptions( oSettings, iCol, null );
571         }
572         
573         
574         /**
575          * Apply options for a column
576          *  @param {object} oSettings dataTables settings object
577          *  @param {int} iCol column index to consider
578          *  @param {object} oOptions object with sType, bVisible and bSearchable etc
579          *  @memberof DataTable#oApi
580          */
581         function _fnColumnOptions( oSettings, iCol, oOptions )
582         {
583                 var oCol = oSettings.aoColumns[ iCol ];
584                 var oClasses = oSettings.oClasses;
585                 var th = $(oCol.nTh);
586         
587                 // Try to get width information from the DOM. We can't get it from CSS
588                 // as we'd need to parse the CSS stylesheet. `width` option can override
589                 if ( ! oCol.sWidthOrig ) {
590                         // Width attribute
591                         oCol.sWidthOrig = th.attr('width') || null;
592         
593                         // Style attribute
594                         var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%])/);
595                         if ( t ) {
596                                 oCol.sWidthOrig = t[1];
597                         }
598                 }
599         
600                 /* User specified column options */
601                 if ( oOptions !== undefined && oOptions !== null )
602                 {
603                         // Backwards compatibility
604                         _fnCompatCols( oOptions );
605         
606                         // Map camel case parameters to their Hungarian counterparts
607                         _fnCamelToHungarian( DataTable.defaults.column, oOptions );
608         
609                         /* Backwards compatibility for mDataProp */
610                         if ( oOptions.mDataProp !== undefined && !oOptions.mData )
611                         {
612                                 oOptions.mData = oOptions.mDataProp;
613                         }
614         
615                         if ( oOptions.sType )
616                         {
617                                 oCol._sManualType = oOptions.sType;
618                         }
619         
620                         // `class` is a reserved word in Javascript, so we need to provide
621                         // the ability to use a valid name for the camel case input
622                         if ( oOptions.className && ! oOptions.sClass )
623                         {
624                                 oOptions.sClass = oOptions.className;
625                         }
626         
627                         $.extend( oCol, oOptions );
628                         _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
629         
630                         /* iDataSort to be applied (backwards compatibility), but aDataSort will take
631                          * priority if defined
632                          */
633                         if ( typeof oOptions.iDataSort === 'number' )
634                         {
635                                 oCol.aDataSort = [ oOptions.iDataSort ];
636                         }
637                         _fnMap( oCol, oOptions, "aDataSort" );
638                 }
639         
640                 /* Cache the data get and set functions for speed */
641                 var mDataSrc = oCol.mData;
642                 var mData = _fnGetObjectDataFn( mDataSrc );
643                 var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
644         
645                 var attrTest = function( src ) {
646                         return typeof src === 'string' && src.indexOf('@') !== -1;
647                 };
648                 oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
649                         attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
650                 );
651         
652                 oCol.fnGetData = function (oData, sSpecific) {
653                         var innerData = mData( oData, sSpecific );
654         
655                         if ( oCol.mRender && (sSpecific && sSpecific !== '') )
656                         {
657                                 return mRender( innerData, sSpecific, oData );
658                         }
659                         return innerData;
660                 };
661                 oCol.fnSetData = _fnSetObjectDataFn( mDataSrc );
662         
663                 /* Feature sorting overrides column specific when off */
664                 if ( !oSettings.oFeatures.bSort )
665                 {
666                         oCol.bSortable = false;
667                         th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
668                 }
669         
670                 /* Check that the class assignment is correct for sorting */
671                 var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
672                 var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
673                 if ( !oCol.bSortable || (!bAsc && !bDesc) )
674                 {
675                         oCol.sSortingClass = oClasses.sSortableNone;
676                         oCol.sSortingClassJUI = "";
677                 }
678                 else if ( bAsc && !bDesc )
679                 {
680                         oCol.sSortingClass = oClasses.sSortableAsc;
681                         oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
682                 }
683                 else if ( !bAsc && bDesc )
684                 {
685                         oCol.sSortingClass = oClasses.sSortableDesc;
686                         oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
687                 }
688                 else
689                 {
690                         oCol.sSortingClass = oClasses.sSortable;
691                         oCol.sSortingClassJUI = oClasses.sSortJUI;
692                 }
693         }
694         
695         
696         /**
697          * Adjust the table column widths for new data. Note: you would probably want to
698          * do a redraw after calling this function!
699          *  @param {object} settings dataTables settings object
700          *  @memberof DataTable#oApi
701          */
702         function _fnAdjustColumnSizing ( settings )
703         {
704                 /* Not interested in doing column width calculation if auto-width is disabled */
705                 if ( settings.oFeatures.bAutoWidth !== false )
706                 {
707                         var columns = settings.aoColumns;
708         
709                         _fnCalculateColumnWidths( settings );
710                         for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
711                         {
712                                 columns[i].nTh.style.width = columns[i].sWidth;
713                         }
714                 }
715         
716                 var scroll = settings.oScroll;
717                 if ( scroll.sY !== '' || scroll.sX !== '')
718                 {
719                         _fnScrollDraw( settings );
720                 }
721         
722                 _fnCallbackFire( settings, null, 'column-sizing', [settings] );
723         }
724         
725         
726         /**
727          * Covert the index of a visible column to the index in the data array (take account
728          * of hidden columns)
729          *  @param {object} oSettings dataTables settings object
730          *  @param {int} iMatch Visible column index to lookup
731          *  @returns {int} i the data index
732          *  @memberof DataTable#oApi
733          */
734         function _fnVisibleToColumnIndex( oSettings, iMatch )
735         {
736                 var aiVis = _fnGetColumns( oSettings, 'bVisible' );
737         
738                 return typeof aiVis[iMatch] === 'number' ?
739                         aiVis[iMatch] :
740                         null;
741         }
742         
743         
744         /**
745          * Covert the index of an index in the data array and convert it to the visible
746          *   column index (take account of hidden columns)
747          *  @param {int} iMatch Column index to lookup
748          *  @param {object} oSettings dataTables settings object
749          *  @returns {int} i the data index
750          *  @memberof DataTable#oApi
751          */
752         function _fnColumnIndexToVisible( oSettings, iMatch )
753         {
754                 var aiVis = _fnGetColumns( oSettings, 'bVisible' );
755                 var iPos = $.inArray( iMatch, aiVis );
756         
757                 return iPos !== -1 ? iPos : null;
758         }
759         
760         
761         /**
762          * Get the number of visible columns
763          *  @param {object} oSettings dataTables settings object
764          *  @returns {int} i the number of visible columns
765          *  @memberof DataTable#oApi
766          */
767         function _fnVisbleColumns( oSettings )
768         {
769                 return _fnGetColumns( oSettings, 'bVisible' ).length;
770         }
771         
772         
773         /**
774          * Get an array of column indexes that match a given property
775          *  @param {object} oSettings dataTables settings object
776          *  @param {string} sParam Parameter in aoColumns to look for - typically
777          *    bVisible or bSearchable
778          *  @returns {array} Array of indexes with matched properties
779          *  @memberof DataTable#oApi
780          */
781         function _fnGetColumns( oSettings, sParam )
782         {
783                 var a = [];
784         
785                 $.map( oSettings.aoColumns, function(val, i) {
786                         if ( val[sParam] ) {
787                                 a.push( i );
788                         }
789                 } );
790         
791                 return a;
792         }
793         
794         
795         /**
796          * Calculate the 'type' of a column
797          *  @param {object} settings dataTables settings object
798          *  @memberof DataTable#oApi
799          */
800         function _fnColumnTypes ( settings )
801         {
802                 var columns = settings.aoColumns;
803                 var data = settings.aoData;
804                 var types = DataTable.ext.type.detect;
805                 var i, ien, j, jen, k, ken;
806                 var col, cell, detectedType, cache;
807         
808                 // For each column, spin over the 
809                 for ( i=0, ien=columns.length ; i<ien ; i++ ) {
810                         col = columns[i];
811                         cache = [];
812         
813                         if ( ! col.sType && col._sManualType ) {
814                                 col.sType = col._sManualType;
815                         }
816                         else if ( ! col.sType ) {
817                                 for ( j=0, jen=types.length ; j<jen ; j++ ) {
818                                         for ( k=0, ken=data.length ; k<ken ; k++ ) {
819                                                 // Use a cache array so we only need to get the type data
820                                                 // from the formatter once (when using multiple detectors)
821                                                 if ( cache[k] === undefined ) {
822                                                         cache[k] = _fnGetCellData( settings, k, i, 'type' );
823                                                 }
824         
825                                                 detectedType = types[j]( cache[k], settings );
826         
827                                                 // Doesn't match, so break early, since this type can't
828                                                 // apply to this column. Also, HTML is a special case since
829                                                 // it is so similar to `string`. Just a single match is
830                                                 // needed for a column to be html type
831                                                 if ( ! detectedType || detectedType === 'html' ) {
832                                                         break;
833                                                 }
834                                         }
835         
836                                         // Type is valid for all data points in the column - use this
837                                         // type
838                                         if ( detectedType ) {
839                                                 col.sType = detectedType;
840                                                 break;
841                                         }
842                                 }
843         
844                                 // Fall back - if no type was detected, always use string
845                                 if ( ! col.sType ) {
846                                         col.sType = 'string';
847                                 }
848                         }
849                 }
850         }
851         
852         
853         /**
854          * Take the column definitions and static columns arrays and calculate how
855          * they relate to column indexes. The callback function will then apply the
856          * definition found for a column to a suitable configuration object.
857          *  @param {object} oSettings dataTables settings object
858          *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
859          *  @param {array} aoCols The aoColumns array that defines columns individually
860          *  @param {function} fn Callback function - takes two parameters, the calculated
861          *    column index and the definition for that column.
862          *  @memberof DataTable#oApi
863          */
864         function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
865         {
866                 var i, iLen, j, jLen, k, kLen, def;
867                 var columns = oSettings.aoColumns;
868         
869                 // Column definitions with aTargets
870                 if ( aoColDefs )
871                 {
872                         /* Loop over the definitions array - loop in reverse so first instance has priority */
873                         for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
874                         {
875                                 def = aoColDefs[i];
876         
877                                 /* Each definition can target multiple columns, as it is an array */
878                                 var aTargets = def.targets !== undefined ?
879                                         def.targets :
880                                         def.aTargets;
881         
882                                 if ( ! $.isArray( aTargets ) )
883                                 {
884                                         aTargets = [ aTargets ];
885                                 }
886         
887                                 for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
888                                 {
889                                         if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
890                                         {
891                                                 /* Add columns that we don't yet know about */
892                                                 while( columns.length <= aTargets[j] )
893                                                 {
894                                                         _fnAddColumn( oSettings );
895                                                 }
896         
897                                                 /* Integer, basic index */
898                                                 fn( aTargets[j], def );
899                                         }
900                                         else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
901                                         {
902                                                 /* Negative integer, right to left column counting */
903                                                 fn( columns.length+aTargets[j], def );
904                                         }
905                                         else if ( typeof aTargets[j] === 'string' )
906                                         {
907                                                 /* Class name matching on TH element */
908                                                 for ( k=0, kLen=columns.length ; k<kLen ; k++ )
909                                                 {
910                                                         if ( aTargets[j] == "_all" ||
911                                                              $(columns[k].nTh).hasClass( aTargets[j] ) )
912                                                         {
913                                                                 fn( k, def );
914                                                         }
915                                                 }
916                                         }
917                                 }
918                         }
919                 }
920         
921                 // Statically defined columns array
922                 if ( aoCols )
923                 {
924                         for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
925                         {
926                                 fn( i, aoCols[i] );
927                         }
928                 }
929         }
930         
931         /**
932          * Add a data array to the table, creating DOM node etc. This is the parallel to
933          * _fnGatherData, but for adding rows from a Javascript source, rather than a
934          * DOM source.
935          *  @param {object} oSettings dataTables settings object
936          *  @param {array} aData data array to be added
937          *  @param {node} [nTr] TR element to add to the table - optional. If not given,
938          *    DataTables will create a row automatically
939          *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
940          *    if nTr is.
941          *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
942          *  @memberof DataTable#oApi
943          */
944         function _fnAddData ( oSettings, aDataIn, nTr, anTds )
945         {
946                 /* Create the object for storing information about this new row */
947                 var iRow = oSettings.aoData.length;
948                 var oData = $.extend( true, {}, DataTable.models.oRow, {
949                         src: nTr ? 'dom' : 'data'
950                 } );
951         
952                 oData._aData = aDataIn;
953                 oSettings.aoData.push( oData );
954         
955                 /* Create the cells */
956                 var nTd, sThisType;
957                 var columns = oSettings.aoColumns;
958                 for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
959                 {
960                         // When working with a row, the data source object must be populated. In
961                         // all other cases, the data source object is already populated, so we
962                         // don't overwrite it, which might break bindings etc
963                         if ( nTr ) {
964                                 _fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) );
965                         }
966                         columns[i].sType = null;
967                 }
968         
969                 /* Add to the display array */
970                 oSettings.aiDisplayMaster.push( iRow );
971         
972                 /* Create the DOM information */
973                 if ( !oSettings.oFeatures.bDeferRender )
974                 {
975                         _fnCreateTr( oSettings, iRow, nTr, anTds );
976                 }
977         
978                 return iRow;
979         }
980         
981         
982         /**
983          * Add one or more TR elements to the table. Generally we'd expect to
984          * use this for reading data from a DOM sourced table, but it could be
985          * used for an TR element. Note that if a TR is given, it is used (i.e.
986          * it is not cloned).
987          *  @param {object} settings dataTables settings object
988          *  @param {array|node|jQuery} trs The TR element(s) to add to the table
989          *  @returns {array} Array of indexes for the added rows
990          *  @memberof DataTable#oApi
991          */
992         function _fnAddTr( settings, trs )
993         {
994                 var row;
995         
996                 // Allow an individual node to be passed in
997                 if ( ! (trs instanceof $) ) {
998                         trs = $(trs);
999                 }
1000         
1001                 return trs.map( function (i, el) {
1002                         row = _fnGetRowElements( settings, el );
1003                         return _fnAddData( settings, row.data, el, row.cells );
1004                 } );
1005         }
1006         
1007         
1008         /**
1009          * Take a TR element and convert it to an index in aoData
1010          *  @param {object} oSettings dataTables settings object
1011          *  @param {node} n the TR element to find
1012          *  @returns {int} index if the node is found, null if not
1013          *  @memberof DataTable#oApi
1014          */
1015         function _fnNodeToDataIndex( oSettings, n )
1016         {
1017                 return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
1018         }
1019         
1020         
1021         /**
1022          * Take a TD element and convert it into a column data index (not the visible index)
1023          *  @param {object} oSettings dataTables settings object
1024          *  @param {int} iRow The row number the TD/TH can be found in
1025          *  @param {node} n The TD/TH element to find
1026          *  @returns {int} index if the node is found, -1 if not
1027          *  @memberof DataTable#oApi
1028          */
1029         function _fnNodeToColumnIndex( oSettings, iRow, n )
1030         {
1031                 return $.inArray( n, oSettings.aoData[ iRow ].anCells );
1032         }
1033         
1034         
1035         /**
1036          * Get the data for a given cell from the internal cache, taking into account data mapping
1037          *  @param {object} oSettings dataTables settings object
1038          *  @param {int} iRow aoData row id
1039          *  @param {int} iCol Column index
1040          *  @param {string} sSpecific data get type ('display', 'type' 'filter' 'sort')
1041          *  @returns {*} Cell data
1042          *  @memberof DataTable#oApi
1043          */
1044         function _fnGetCellData( oSettings, iRow, iCol, sSpecific )
1045         {
1046                 var oCol = oSettings.aoColumns[iCol];
1047                 var oData = oSettings.aoData[iRow]._aData;
1048                 var sData = oCol.fnGetData( oData, sSpecific );
1049         
1050                 if ( sData === undefined )
1051                 {
1052                         if ( oSettings.iDrawError != oSettings.iDraw && oCol.sDefaultContent === null )
1053                         {
1054                                 _fnLog( oSettings, 0, "Requested unknown parameter "+
1055                                         (typeof oCol.mData=='function' ? '{function}' : "'"+oCol.mData+"'")+
1056                                         " for row "+iRow, 4 );
1057                                 oSettings.iDrawError = oSettings.iDraw;
1058                         }
1059                         return oCol.sDefaultContent;
1060                 }
1061         
1062                 /* When the data source is null, we can use default column data */
1063                 if ( (sData === oData || sData === null) && oCol.sDefaultContent !== null )
1064                 {
1065                         sData = oCol.sDefaultContent;
1066                 }
1067                 else if ( typeof sData === 'function' )
1068                 {
1069                         // If the data source is a function, then we run it and use the return
1070                         return sData();
1071                 }
1072         
1073                 if ( sData === null && sSpecific == 'display' )
1074                 {
1075                         return '';
1076                 }
1077                 return sData;
1078         }
1079         
1080         
1081         /**
1082          * Set the value for a specific cell, into the internal data cache
1083          *  @param {object} oSettings dataTables settings object
1084          *  @param {int} iRow aoData row id
1085          *  @param {int} iCol Column index
1086          *  @param {*} val Value to set
1087          *  @memberof DataTable#oApi
1088          */
1089         function _fnSetCellData( oSettings, iRow, iCol, val )
1090         {
1091                 var oCol = oSettings.aoColumns[iCol];
1092                 var oData = oSettings.aoData[iRow]._aData;
1093         
1094                 oCol.fnSetData( oData, val );
1095         }
1096         
1097         
1098         // Private variable that is used to match action syntax in the data property object
1099         var __reArray = /\[.*?\]$/;
1100         var __reFn = /\(\)$/;
1101         
1102         /**
1103          * Split string on periods, taking into account escaped periods
1104          * @param  {string} str String to split
1105          * @return {array} Split string
1106          */
1107         function _fnSplitObjNotation( str )
1108         {
1109                 return $.map( str.match(/(\\.|[^\.])+/g), function ( s ) {
1110                         return s.replace('\\.', '.');
1111                 } );
1112         }
1113         
1114         
1115         /**
1116          * Return a function that can be used to get data from a source object, taking
1117          * into account the ability to use nested objects as a source
1118          *  @param {string|int|function} mSource The data source for the object
1119          *  @returns {function} Data get function
1120          *  @memberof DataTable#oApi
1121          */
1122         function _fnGetObjectDataFn( mSource )
1123         {
1124                 if ( $.isPlainObject( mSource ) )
1125                 {
1126                         /* Build an object of get functions, and wrap them in a single call */
1127                         var o = {};
1128                         $.each( mSource, function (key, val) {
1129                                 if ( val ) {
1130                                         o[key] = _fnGetObjectDataFn( val );
1131                                 }
1132                         } );
1133         
1134                         return function (data, type, extra) {
1135                                 var t = o[type] || o._;
1136                                 return t !== undefined ?
1137                                         t(data, type, extra) :
1138                                         data;
1139                         };
1140                 }
1141                 else if ( mSource === null )
1142                 {
1143                         /* Give an empty string for rendering / sorting etc */
1144                         return function (data, type) {
1145                                 return data;
1146                         };
1147                 }
1148                 else if ( typeof mSource === 'function' )
1149                 {
1150                         return function (data, type, extra) {
1151                                 return mSource( data, type, extra );
1152                         };
1153                 }
1154                 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
1155                               mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
1156                 {
1157                         /* If there is a . in the source string then the data source is in a
1158                          * nested object so we loop over the data for each level to get the next
1159                          * level down. On each loop we test for undefined, and if found immediately
1160                          * return. This allows entire objects to be missing and sDefaultContent to
1161                          * be used if defined, rather than throwing an error
1162                          */
1163                         var fetchData = function (data, type, src) {
1164                                 var arrayNotation, funcNotation, out, innerSrc;
1165         
1166                                 if ( src !== "" )
1167                                 {
1168                                         var a = _fnSplitObjNotation( src );
1169         
1170                                         for ( var i=0, iLen=a.length ; i<iLen ; i++ )
1171                                         {
1172                                                 // Check if we are dealing with special notation
1173                                                 arrayNotation = a[i].match(__reArray);
1174                                                 funcNotation = a[i].match(__reFn);
1175         
1176                                                 if ( arrayNotation )
1177                                                 {
1178                                                         // Array notation
1179                                                         a[i] = a[i].replace(__reArray, '');
1180         
1181                                                         // Condition allows simply [] to be passed in
1182                                                         if ( a[i] !== "" ) {
1183                                                                 data = data[ a[i] ];
1184                                                         }
1185                                                         out = [];
1186         
1187                                                         // Get the remainder of the nested object to get
1188                                                         a.splice( 0, i+1 );
1189                                                         innerSrc = a.join('.');
1190         
1191                                                         // Traverse each entry in the array getting the properties requested
1192                                                         for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
1193                                                                 out.push( fetchData( data[j], type, innerSrc ) );
1194                                                         }
1195         
1196                                                         // If a string is given in between the array notation indicators, that
1197                                                         // is used to join the strings together, otherwise an array is returned
1198                                                         var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
1199                                                         data = (join==="") ? out : out.join(join);
1200         
1201                                                         // The inner call to fetchData has already traversed through the remainder
1202                                                         // of the source requested, so we exit from the loop
1203                                                         break;
1204                                                 }
1205                                                 else if ( funcNotation )
1206                                                 {
1207                                                         // Function call
1208                                                         a[i] = a[i].replace(__reFn, '');
1209                                                         data = data[ a[i] ]();
1210                                                         continue;
1211                                                 }
1212         
1213                                                 if ( data === null || data[ a[i] ] === undefined )
1214                                                 {
1215                                                         return undefined;
1216                                                 }
1217                                                 data = data[ a[i] ];
1218                                         }
1219                                 }
1220         
1221                                 return data;
1222                         };
1223         
1224                         return function (data, type) {
1225                                 return fetchData( data, type, mSource );
1226                         };
1227                 }
1228                 else
1229                 {
1230                         /* Array or flat object mapping */
1231                         return function (data, type) {
1232                                 return data[mSource];
1233                         };
1234                 }
1235         }
1236         
1237         
1238         /**
1239          * Return a function that can be used to set data from a source object, taking
1240          * into account the ability to use nested objects as a source
1241          *  @param {string|int|function} mSource The data source for the object
1242          *  @returns {function} Data set function
1243          *  @memberof DataTable#oApi
1244          */
1245         function _fnSetObjectDataFn( mSource )
1246         {
1247                 if ( $.isPlainObject( mSource ) )
1248                 {
1249                         /* Unlike get, only the underscore (global) option is used for for
1250                          * setting data since we don't know the type here. This is why an object
1251                          * option is not documented for `mData` (which is read/write), but it is
1252                          * for `mRender` which is read only.
1253                          */
1254                         return _fnSetObjectDataFn( mSource._ );
1255                 }
1256                 else if ( mSource === null )
1257                 {
1258                         /* Nothing to do when the data source is null */
1259                         return function (data, val) {};
1260                 }
1261                 else if ( typeof mSource === 'function' )
1262                 {
1263                         return function (data, val) {
1264                                 mSource( data, 'set', val );
1265                         };
1266                 }
1267                 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
1268                               mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
1269                 {
1270                         /* Like the get, we need to get data from a nested object */
1271                         var setData = function (data, val, src) {
1272                                 var a = _fnSplitObjNotation( src ), b;
1273                                 var aLast = a[a.length-1];
1274                                 var arrayNotation, funcNotation, o, innerSrc;
1275         
1276                                 for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
1277                                 {
1278                                         // Check if we are dealing with an array notation request
1279                                         arrayNotation = a[i].match(__reArray);
1280                                         funcNotation = a[i].match(__reFn);
1281         
1282                                         if ( arrayNotation )
1283                                         {
1284                                                 a[i] = a[i].replace(__reArray, '');
1285                                                 data[ a[i] ] = [];
1286         
1287                                                 // Get the remainder of the nested object to set so we can recurse
1288                                                 b = a.slice();
1289                                                 b.splice( 0, i+1 );
1290                                                 innerSrc = b.join('.');
1291         
1292                                                 // Traverse each entry in the array setting the properties requested
1293                                                 for ( var j=0, jLen=val.length ; j<jLen ; j++ )
1294                                                 {
1295                                                         o = {};
1296                                                         setData( o, val[j], innerSrc );
1297                                                         data[ a[i] ].push( o );
1298                                                 }
1299         
1300                                                 // The inner call to setData has already traversed through the remainder
1301                                                 // of the source and has set the data, thus we can exit here
1302                                                 return;
1303                                         }
1304                                         else if ( funcNotation )
1305                                         {
1306                                                 // Function call
1307                                                 a[i] = a[i].replace(__reFn, '');
1308                                                 data = data[ a[i] ]( val );
1309                                         }
1310         
1311                                         // If the nested object doesn't currently exist - since we are
1312                                         // trying to set the value - create it
1313                                         if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
1314                                         {
1315                                                 data[ a[i] ] = {};
1316                                         }
1317                                         data = data[ a[i] ];
1318                                 }
1319         
1320                                 // Last item in the input - i.e, the actual set
1321                                 if ( aLast.match(__reFn ) )
1322                                 {
1323                                         // Function call
1324                                         data = data[ aLast.replace(__reFn, '') ]( val );
1325                                 }
1326                                 else
1327                                 {
1328                                         // If array notation is used, we just want to strip it and use the property name
1329                                         // and assign the value. If it isn't used, then we get the result we want anyway
1330                                         data[ aLast.replace(__reArray, '') ] = val;
1331                                 }
1332                         };
1333         
1334                         return function (data, val) {
1335                                 return setData( data, val, mSource );
1336                         };
1337                 }
1338                 else
1339                 {
1340                         /* Array or flat object mapping */
1341                         return function (data, val) {
1342                                 data[mSource] = val;
1343                         };
1344                 }
1345         }
1346         
1347         
1348         /**
1349          * Return an array with the full table data
1350          *  @param {object} oSettings dataTables settings object
1351          *  @returns array {array} aData Master data array
1352          *  @memberof DataTable#oApi
1353          */
1354         function _fnGetDataMaster ( settings )
1355         {
1356                 return _pluck( settings.aoData, '_aData' );
1357         }
1358         
1359         
1360         /**
1361          * Nuke the table
1362          *  @param {object} oSettings dataTables settings object
1363          *  @memberof DataTable#oApi
1364          */
1365         function _fnClearTable( settings )
1366         {
1367                 settings.aoData.length = 0;
1368                 settings.aiDisplayMaster.length = 0;
1369                 settings.aiDisplay.length = 0;
1370         }
1371         
1372         
1373          /**
1374          * Take an array of integers (index array) and remove a target integer (value - not
1375          * the key!)
1376          *  @param {array} a Index array to target
1377          *  @param {int} iTarget value to find
1378          *  @memberof DataTable#oApi
1379          */
1380         function _fnDeleteIndex( a, iTarget, splice )
1381         {
1382                 var iTargetIndex = -1;
1383         
1384                 for ( var i=0, iLen=a.length ; i<iLen ; i++ )
1385                 {
1386                         if ( a[i] == iTarget )
1387                         {
1388                                 iTargetIndex = i;
1389                         }
1390                         else if ( a[i] > iTarget )
1391                         {
1392                                 a[i]--;
1393                         }
1394                 }
1395         
1396                 if ( iTargetIndex != -1 && splice === undefined )
1397                 {
1398                         a.splice( iTargetIndex, 1 );
1399                 }
1400         }
1401         
1402         
1403         /**
1404          * Mark cached data as invalid such that a re-read of the data will occur when
1405          * the cached data is next requested. Also update from the data source object.
1406          *
1407          * @param {object} settings DataTables settings object
1408          * @param  {int}    rowIdx   Row index to invalidate
1409          * @memberof DataTable#oApi
1410          *
1411          * @todo For the modularisation of v1.11 this will need to become a callback, so
1412          *   the sort and filter methods can subscribe to it. That will required
1413          *   initialisation options for sorting, which is why it is not already baked in
1414          */
1415         function _fnInvalidateRow( settings, rowIdx, src, column )
1416         {
1417                 var row = settings.aoData[ rowIdx ];
1418                 var i, ien;
1419         
1420                 // Are we reading last data from DOM or the data object?
1421                 if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
1422                         // Read the data from the DOM
1423                         row._aData = _fnGetRowElements( settings, row ).data;
1424                 }
1425                 else {
1426                         // Reading from data object, update the DOM
1427                         var cells = row.anCells;
1428         
1429                         if ( cells ) {
1430                                 for ( i=0, ien=cells.length ; i<ien ; i++ ) {
1431                                         cells[i].innerHTML = _fnGetCellData( settings, rowIdx, i, 'display' );
1432                                 }
1433                         }
1434                 }
1435         
1436                 row._aSortData = null;
1437                 row._aFilterData = null;
1438         
1439                 // Invalidate the type for a specific column (if given) or all columns since
1440                 // the data might have changed
1441                 var cols = settings.aoColumns;
1442                 if ( column !== undefined ) {
1443                         cols[ column ].sType = null;
1444                 }
1445                 else {
1446                         for ( i=0, ien=cols.length ; i<ien ; i++ ) {
1447                                 cols[i].sType = null;
1448                         }
1449                 }
1450         
1451                 // Update DataTables special `DT_*` attributes for the row
1452                 _fnRowAttributes( row );
1453         }
1454         
1455         
1456         /**
1457          * Build a data source object from an HTML row, reading the contents of the
1458          * cells that are in the row.
1459          *
1460          * @param {object} settings DataTables settings object
1461          * @param {node|object} TR element from which to read data or existing row
1462          *   object from which to re-read the data from the cells
1463          * @returns {object} Object with two parameters: `data` the data read, in
1464          *   document order, and `cells` and array of nodes (they can be useful to the
1465          *   caller, so rather than needing a second traversal to get them, just return
1466          *   them from here).
1467          * @memberof DataTable#oApi
1468          */
1469         function _fnGetRowElements( settings, row )
1470         {
1471                 var
1472                         d = [],
1473                         tds = [],
1474                         td = row.firstChild,
1475                         name, col, o, i=0, contents,
1476                         columns = settings.aoColumns;
1477         
1478                 var attr = function ( str, data, td  ) {
1479                         if ( typeof str === 'string' ) {
1480                                 var idx = str.indexOf('@');
1481         
1482                                 if ( idx !== -1 ) {
1483                                         var src = str.substring( idx+1 );
1484                                         o[ '@'+src ] = td.getAttribute( src );
1485                                 }
1486                         }
1487                 };
1488         
1489                 var cellProcess = function ( cell ) {
1490                         col = columns[i];
1491                         contents = $.trim(cell.innerHTML);
1492         
1493                         if ( col && col._bAttrSrc ) {
1494                                 o = {
1495                                         display: contents
1496                                 };
1497         
1498                                 attr( col.mData.sort, o, cell );
1499                                 attr( col.mData.type, o, cell );
1500                                 attr( col.mData.filter, o, cell );
1501         
1502                                 d.push( o );
1503                         }
1504                         else {
1505                                 d.push( contents );
1506                         }
1507         
1508                         tds.push( cell );
1509                         i++;
1510                 };
1511         
1512                 if ( td ) {
1513                         // `tr` element passed in
1514                         while ( td ) {
1515                                 name = td.nodeName.toUpperCase();
1516         
1517                                 if ( name == "TD" || name == "TH" ) {
1518                                         cellProcess( td );
1519                                 }
1520         
1521                                 td = td.nextSibling;
1522                         }
1523                 }
1524                 else {
1525                         // Existing row object passed in
1526                         tds = row.anCells;
1527                         
1528                         for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
1529                                 cellProcess( tds[j] );
1530                         }
1531                 }
1532         
1533                 return {
1534                         data: d,
1535                         cells: tds
1536                 };
1537         }
1538         /**
1539          * Create a new TR element (and it's TD children) for a row
1540          *  @param {object} oSettings dataTables settings object
1541          *  @param {int} iRow Row to consider
1542          *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
1543          *    DataTables will create a row automatically
1544          *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
1545          *    if nTr is.
1546          *  @memberof DataTable#oApi
1547          */
1548         function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
1549         {
1550                 var
1551                         row = oSettings.aoData[iRow],
1552                         rowData = row._aData,
1553                         cells = [],
1554                         nTr, nTd, oCol,
1555                         i, iLen;
1556         
1557                 if ( row.nTr === null )
1558                 {
1559                         nTr = nTrIn || document.createElement('tr');
1560         
1561                         row.nTr = nTr;
1562                         row.anCells = cells;
1563         
1564                         /* Use a private property on the node to allow reserve mapping from the node
1565                          * to the aoData array for fast look up
1566                          */
1567                         nTr._DT_RowIndex = iRow;
1568         
1569                         /* Special parameters can be given by the data source to be used on the row */
1570                         _fnRowAttributes( row );
1571         
1572                         /* Process each column */
1573                         for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
1574                         {
1575                                 oCol = oSettings.aoColumns[i];
1576         
1577                                 nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
1578                                 cells.push( nTd );
1579         
1580                                 // Need to create the HTML if new, or if a rendering function is defined
1581                                 if ( !nTrIn || oCol.mRender || oCol.mData !== i )
1582                                 {
1583                                         nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
1584                                 }
1585         
1586                                 /* Add user defined class */
1587                                 if ( oCol.sClass )
1588                                 {
1589                                         nTd.className += ' '+oCol.sClass;
1590                                 }
1591         
1592                                 // Visibility - add or remove as required
1593                                 if ( oCol.bVisible && ! nTrIn )
1594                                 {
1595                                         nTr.appendChild( nTd );
1596                                 }
1597                                 else if ( ! oCol.bVisible && nTrIn )
1598                                 {
1599                                         nTd.parentNode.removeChild( nTd );
1600                                 }
1601         
1602                                 if ( oCol.fnCreatedCell )
1603                                 {
1604                                         oCol.fnCreatedCell.call( oSettings.oInstance,
1605                                                 nTd, _fnGetCellData( oSettings, iRow, i, 'display' ), rowData, iRow, i
1606                                         );
1607                                 }
1608                         }
1609         
1610                         _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
1611                 }
1612         
1613                 // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
1614                 // and deployed
1615                 row.nTr.setAttribute( 'role', 'row' );
1616         }
1617         
1618         
1619         /**
1620          * Add attributes to a row based on the special `DT_*` parameters in a data
1621          * source object.
1622          *  @param {object} DataTables row object for the row to be modified
1623          *  @memberof DataTable#oApi
1624          */
1625         function _fnRowAttributes( row )
1626         {
1627                 var tr = row.nTr;
1628                 var data = row._aData;
1629         
1630                 if ( tr ) {
1631                         if ( data.DT_RowId ) {
1632                                 tr.id = data.DT_RowId;
1633                         }
1634         
1635                         if ( data.DT_RowClass ) {
1636                                 // Remove any classes added by DT_RowClass before
1637                                 var a = data.DT_RowClass.split(' ');
1638                                 row.__rowc = row.__rowc ?
1639                                         _unique( row.__rowc.concat( a ) ) :
1640                                         a;
1641         
1642                                 $(tr)
1643                                         .removeClass( row.__rowc.join(' ') )
1644                                         .addClass( data.DT_RowClass );
1645                         }
1646         
1647                         if ( data.DT_RowData ) {
1648                                 $(tr).data( data.DT_RowData );
1649                         }
1650                 }
1651         }
1652         
1653         
1654         /**
1655          * Create the HTML header for the table
1656          *  @param {object} oSettings dataTables settings object
1657          *  @memberof DataTable#oApi
1658          */
1659         function _fnBuildHead( oSettings )
1660         {
1661                 var i, ien, cell, row, column;
1662                 var thead = oSettings.nTHead;
1663                 var tfoot = oSettings.nTFoot;
1664                 var createHeader = $('th, td', thead).length === 0;
1665                 var classes = oSettings.oClasses;
1666                 var columns = oSettings.aoColumns;
1667         
1668                 if ( createHeader ) {
1669                         row = $('<tr/>').appendTo( thead );
1670                 }
1671         
1672                 for ( i=0, ien=columns.length ; i<ien ; i++ ) {
1673                         column = columns[i];
1674                         cell = $( column.nTh ).addClass( column.sClass );
1675         
1676                         if ( createHeader ) {
1677                                 cell.appendTo( row );
1678                         }
1679         
1680                         // 1.11 move into sorting
1681                         if ( oSettings.oFeatures.bSort ) {
1682                                 cell.addClass( column.sSortingClass );
1683         
1684                                 if ( column.bSortable !== false ) {
1685                                         cell
1686                                                 .attr( 'tabindex', oSettings.iTabIndex )
1687                                                 .attr( 'aria-controls', oSettings.sTableId );
1688         
1689                                         _fnSortAttachListener( oSettings, column.nTh, i );
1690                                 }
1691                         }
1692         
1693                         if ( column.sTitle != cell.html() ) {
1694                                 cell.html( column.sTitle );
1695                         }
1696         
1697                         _fnRenderer( oSettings, 'header' )(
1698                                 oSettings, cell, column, classes
1699                         );
1700                 }
1701         
1702                 if ( createHeader ) {
1703                         _fnDetectHeader( oSettings.aoHeader, thead );
1704                 }
1705                 
1706                 /* ARIA role for the rows */
1707                 $(thead).find('>tr').attr('role', 'row');
1708         
1709                 /* Deal with the footer - add classes if required */
1710                 $(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
1711                 $(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
1712         
1713                 // Cache the footer cells. Note that we only take the cells from the first
1714                 // row in the footer. If there is more than one row the user wants to
1715                 // interact with, they need to use the table().foot() method. Note also this
1716                 // allows cells to be used for multiple columns using colspan
1717                 if ( tfoot !== null ) {
1718                         var cells = oSettings.aoFooter[0];
1719         
1720                         for ( i=0, ien=cells.length ; i<ien ; i++ ) {
1721                                 column = columns[i];
1722                                 column.nTf = cells[i].cell;
1723         
1724                                 if ( column.sClass ) {
1725                                         $(column.nTf).addClass( column.sClass );
1726                                 }
1727                         }
1728                 }
1729         }
1730         
1731         
1732         /**
1733          * Draw the header (or footer) element based on the column visibility states. The
1734          * methodology here is to use the layout array from _fnDetectHeader, modified for
1735          * the instantaneous column visibility, to construct the new layout. The grid is
1736          * traversed over cell at a time in a rows x columns grid fashion, although each
1737          * cell insert can cover multiple elements in the grid - which is tracks using the
1738          * aApplied array. Cell inserts in the grid will only occur where there isn't
1739          * already a cell in that position.
1740          *  @param {object} oSettings dataTables settings object
1741          *  @param array {objects} aoSource Layout array from _fnDetectHeader
1742          *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
1743          *  @memberof DataTable#oApi
1744          */
1745         function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
1746         {
1747                 var i, iLen, j, jLen, k, kLen, n, nLocalTr;
1748                 var aoLocal = [];
1749                 var aApplied = [];
1750                 var iColumns = oSettings.aoColumns.length;
1751                 var iRowspan, iColspan;
1752         
1753                 if ( ! aoSource )
1754                 {
1755                         return;
1756                 }
1757         
1758                 if (  bIncludeHidden === undefined )
1759                 {
1760                         bIncludeHidden = false;
1761                 }
1762         
1763                 /* Make a copy of the master layout array, but without the visible columns in it */
1764                 for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
1765                 {
1766                         aoLocal[i] = aoSource[i].slice();
1767                         aoLocal[i].nTr = aoSource[i].nTr;
1768         
1769                         /* Remove any columns which are currently hidden */
1770                         for ( j=iColumns-1 ; j>=0 ; j-- )
1771                         {
1772                                 if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
1773                                 {
1774                                         aoLocal[i].splice( j, 1 );
1775                                 }
1776                         }
1777         
1778                         /* Prep the applied array - it needs an element for each row */
1779                         aApplied.push( [] );
1780                 }
1781         
1782                 for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
1783                 {
1784                         nLocalTr = aoLocal[i].nTr;
1785         
1786                         /* All cells are going to be replaced, so empty out the row */
1787                         if ( nLocalTr )
1788                         {
1789                                 while( (n = nLocalTr.firstChild) )
1790                                 {
1791                                         nLocalTr.removeChild( n );
1792                                 }
1793                         }
1794         
1795                         for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
1796                         {
1797                                 iRowspan = 1;
1798                                 iColspan = 1;
1799         
1800                                 /* Check to see if there is already a cell (row/colspan) covering our target
1801                                  * insert point. If there is, then there is nothing to do.
1802                                  */
1803                                 if ( aApplied[i][j] === undefined )
1804                                 {
1805                                         nLocalTr.appendChild( aoLocal[i][j].cell );
1806                                         aApplied[i][j] = 1;
1807         
1808                                         /* Expand the cell to cover as many rows as needed */
1809                                         while ( aoLocal[i+iRowspan] !== undefined &&
1810                                                 aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
1811                                         {
1812                                                 aApplied[i+iRowspan][j] = 1;
1813                                                 iRowspan++;
1814                                         }
1815         
1816                                         /* Expand the cell to cover as many columns as needed */
1817                                         while ( aoLocal[i][j+iColspan] !== undefined &&
1818                                                 aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
1819                                         {
1820                                                 /* Must update the applied array over the rows for the columns */
1821                                                 for ( k=0 ; k<iRowspan ; k++ )
1822                                                 {
1823                                                         aApplied[i+k][j+iColspan] = 1;
1824                                                 }
1825                                                 iColspan++;
1826                                         }
1827         
1828                                         /* Do the actual expansion in the DOM */
1829                                         $(aoLocal[i][j].cell)
1830                                                 .attr('rowspan', iRowspan)
1831                                                 .attr('colspan', iColspan);
1832                                 }
1833                         }
1834                 }
1835         }
1836         
1837         
1838         /**
1839          * Insert the required TR nodes into the table for display
1840          *  @param {object} oSettings dataTables settings object
1841          *  @memberof DataTable#oApi
1842          */
1843         function _fnDraw( oSettings )
1844         {
1845                 /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
1846                 var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
1847                 if ( $.inArray( false, aPreDraw ) !== -1 )
1848                 {
1849                         _fnProcessingDisplay( oSettings, false );
1850                         return;
1851                 }
1852         
1853                 var i, iLen, n;
1854                 var anRows = [];
1855                 var iRowCount = 0;
1856                 var asStripeClasses = oSettings.asStripeClasses;
1857                 var iStripes = asStripeClasses.length;
1858                 var iOpenRows = oSettings.aoOpenRows.length;
1859                 var oLang = oSettings.oLanguage;
1860                 var iInitDisplayStart = oSettings.iInitDisplayStart;
1861                 var bServerSide = _fnDataSource( oSettings ) == 'ssp';
1862                 var aiDisplay = oSettings.aiDisplay;
1863         
1864                 oSettings.bDrawing = true;
1865         
1866                 /* Check and see if we have an initial draw position from state saving */
1867                 if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
1868                 {
1869                         oSettings._iDisplayStart = bServerSide ?
1870                                 iInitDisplayStart :
1871                                 iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
1872                                         0 :
1873                                         iInitDisplayStart;
1874         
1875                         oSettings.iInitDisplayStart = -1;
1876                 }
1877         
1878                 var iDisplayStart = oSettings._iDisplayStart;
1879                 var iDisplayEnd = oSettings.fnDisplayEnd();
1880         
1881                 /* Server-side processing draw intercept */
1882                 if ( oSettings.bDeferLoading )
1883                 {
1884                         oSettings.bDeferLoading = false;
1885                         oSettings.iDraw++;
1886                         _fnProcessingDisplay( oSettings, false );
1887                 }
1888                 else if ( !bServerSide )
1889                 {
1890                         oSettings.iDraw++;
1891                 }
1892                 else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
1893                 {
1894                         return;
1895                 }
1896         
1897                 if ( aiDisplay.length !== 0 )
1898                 {
1899                         var iStart = bServerSide ? 0 : iDisplayStart;
1900                         var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
1901         
1902                         for ( var j=iStart ; j<iEnd ; j++ )
1903                         {
1904                                 var iDataIndex = aiDisplay[j];
1905                                 var aoData = oSettings.aoData[ iDataIndex ];
1906                                 if ( aoData.nTr === null )
1907                                 {
1908                                         _fnCreateTr( oSettings, iDataIndex );
1909                                 }
1910         
1911                                 var nRow = aoData.nTr;
1912         
1913                                 /* Remove the old striping classes and then add the new one */
1914                                 if ( iStripes !== 0 )
1915                                 {
1916                                         var sStripe = asStripeClasses[ iRowCount % iStripes ];
1917                                         if ( aoData._sRowStripe != sStripe )
1918                                         {
1919                                                 $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
1920                                                 aoData._sRowStripe = sStripe;
1921                                         }
1922                                 }
1923         
1924                                 /* Row callback functions - might want to manipulate the row */
1925                                 _fnCallbackFire( oSettings, 'aoRowCallback', null,
1926                                         [nRow, aoData._aData, iRowCount, j] );
1927         
1928                                 anRows.push( nRow );
1929                                 iRowCount++;
1930                         }
1931                 }
1932                 else
1933                 {
1934                         /* Table is empty - create a row with an empty message in it */
1935                         var sZero = oLang.sZeroRecords;
1936                         if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
1937                         {
1938                                 sZero = oLang.sLoadingRecords;
1939                         }
1940                         else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
1941                         {
1942                                 sZero = oLang.sEmptyTable;
1943                         }
1944         
1945                         anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
1946                                 .append( $('<td />', {
1947                                         'valign':  'top',
1948                                         'colSpan': _fnVisbleColumns( oSettings ),
1949                                         'class':   oSettings.oClasses.sRowEmpty
1950                                 } ).html( sZero ) )[0];
1951                 }
1952         
1953                 /* Header and footer callbacks */
1954                 _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
1955                         _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
1956         
1957                 _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
1958                         _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
1959         
1960                 var body = $(oSettings.nTBody);
1961         
1962                 body.children().detach();
1963                 body.append( $(anRows) );
1964         
1965                 /* Call all required callback functions for the end of a draw */
1966                 _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
1967         
1968                 /* Draw is complete, sorting and filtering must be as well */
1969                 oSettings.bSorted = false;
1970                 oSettings.bFiltered = false;
1971                 oSettings.bDrawing = false;
1972         }
1973         
1974         
1975         /**
1976          * Redraw the table - taking account of the various features which are enabled
1977          *  @param {object} oSettings dataTables settings object
1978          *  @param {boolean} [holdPosition] Keep the current paging position. By default
1979          *    the paging is reset to the first page
1980          *  @memberof DataTable#oApi
1981          */
1982         function _fnReDraw( settings, holdPosition )
1983         {
1984                 var
1985                         features = settings.oFeatures,
1986                         sort     = features.bSort,
1987                         filter   = features.bFilter;
1988         
1989                 if ( sort ) {
1990                         _fnSort( settings );
1991                 }
1992         
1993                 if ( filter ) {
1994                         _fnFilterComplete( settings, settings.oPreviousSearch );
1995                 }
1996                 else {
1997                         // No filtering, so we want to just use the display master
1998                         settings.aiDisplay = settings.aiDisplayMaster.slice();
1999                 }
2000         
2001                 if ( holdPosition !== true ) {
2002                         settings._iDisplayStart = 0;
2003                 }
2004         
2005                 _fnDraw( settings );
2006         }
2007         
2008         
2009         /**
2010          * Add the options to the page HTML for the table
2011          *  @param {object} oSettings dataTables settings object
2012          *  @memberof DataTable#oApi
2013          */
2014         function _fnAddOptionsHtml ( oSettings )
2015         {
2016                 var classes = oSettings.oClasses;
2017                 var table = $(oSettings.nTable);
2018                 var holding = $('<div/>').insertBefore( table ); // Holding element for speed
2019                 var features = oSettings.oFeatures;
2020         
2021                 // All DataTables are wrapped in a div
2022                 var insert = $('<div/>', {
2023                         id:      oSettings.sTableId+'_wrapper',
2024                         'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
2025                 } );
2026         
2027                 oSettings.nHolding = holding[0];
2028                 oSettings.nTableWrapper = insert[0];
2029                 oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
2030         
2031                 /* Loop over the user set positioning and place the elements as needed */
2032                 var aDom = oSettings.sDom.split('');
2033                 var featureNode, cOption, nNewNode, cNext, sAttr, j;
2034                 for ( var i=0 ; i<aDom.length ; i++ )
2035                 {
2036                         featureNode = null;
2037                         cOption = aDom[i];
2038         
2039                         if ( cOption == '<' )
2040                         {
2041                                 /* New container div */
2042                                 nNewNode = $('<div/>')[0];
2043         
2044                                 /* Check to see if we should append an id and/or a class name to the container */
2045                                 cNext = aDom[i+1];
2046                                 if ( cNext == "'" || cNext == '"' )
2047                                 {
2048                                         sAttr = "";
2049                                         j = 2;
2050                                         while ( aDom[i+j] != cNext )
2051                                         {
2052                                                 sAttr += aDom[i+j];
2053                                                 j++;
2054                                         }
2055         
2056                                         /* Replace jQuery UI constants @todo depreciated */
2057                                         if ( sAttr == "H" )
2058                                         {
2059                                                 sAttr = classes.sJUIHeader;
2060                                         }
2061                                         else if ( sAttr == "F" )
2062                                         {
2063                                                 sAttr = classes.sJUIFooter;
2064                                         }
2065         
2066                                         /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
2067                                          * breaks the string into parts and applies them as needed
2068                                          */
2069                                         if ( sAttr.indexOf('.') != -1 )
2070                                         {
2071                                                 var aSplit = sAttr.split('.');
2072                                                 nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
2073                                                 nNewNode.className = aSplit[1];
2074                                         }
2075                                         else if ( sAttr.charAt(0) == "#" )
2076                                         {
2077                                                 nNewNode.id = sAttr.substr(1, sAttr.length-1);
2078                                         }
2079                                         else
2080                                         {
2081                                                 nNewNode.className = sAttr;
2082                                         }
2083         
2084                                         i += j; /* Move along the position array */
2085                                 }
2086         
2087                                 insert.append( nNewNode );
2088                                 insert = $(nNewNode);
2089                         }
2090                         else if ( cOption == '>' )
2091                         {
2092                                 /* End container div */
2093                                 insert = insert.parent();
2094                         }
2095                         // @todo Move options into their own plugins?
2096                         else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
2097                         {
2098                                 /* Length */
2099                                 featureNode = _fnFeatureHtmlLength( oSettings );
2100                         }
2101                         else if ( cOption == 'f' && features.bFilter )
2102                         {
2103                                 /* Filter */
2104                                 featureNode = _fnFeatureHtmlFilter( oSettings );
2105                         }
2106                         else if ( cOption == 'r' && features.bProcessing )
2107                         {
2108                                 /* pRocessing */
2109                                 featureNode = _fnFeatureHtmlProcessing( oSettings );
2110                         }
2111                         else if ( cOption == 't' )
2112                         {
2113                                 /* Table */
2114                                 featureNode = _fnFeatureHtmlTable( oSettings );
2115                         }
2116                         else if ( cOption ==  'i' && features.bInfo )
2117                         {
2118                                 /* Info */
2119                                 featureNode = _fnFeatureHtmlInfo( oSettings );
2120                         }
2121                         else if ( cOption == 'p' && features.bPaginate )
2122                         {
2123                                 /* Pagination */
2124                                 featureNode = _fnFeatureHtmlPaginate( oSettings );
2125                         }
2126                         else if ( DataTable.ext.feature.length !== 0 )
2127                         {
2128                                 /* Plug-in features */
2129                                 var aoFeatures = DataTable.ext.feature;
2130                                 for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
2131                                 {
2132                                         if ( cOption == aoFeatures[k].cFeature )
2133                                         {
2134                                                 featureNode = aoFeatures[k].fnInit( oSettings );
2135                                                 break;
2136                                         }
2137                                 }
2138                         }
2139         
2140                         /* Add to the 2D features array */
2141                         if ( featureNode )
2142                         {
2143                                 var aanFeatures = oSettings.aanFeatures;
2144         
2145                                 if ( ! aanFeatures[cOption] )
2146                                 {
2147                                         aanFeatures[cOption] = [];
2148                                 }
2149         
2150                                 aanFeatures[cOption].push( featureNode );
2151                                 insert.append( featureNode );
2152                         }
2153                 }
2154         
2155                 /* Built our DOM structure - replace the holding div with what we want */
2156                 holding.replaceWith( insert );
2157         }
2158         
2159         
2160         /**
2161          * Use the DOM source to create up an array of header cells. The idea here is to
2162          * create a layout grid (array) of rows x columns, which contains a reference
2163          * to the cell that that point in the grid (regardless of col/rowspan), such that
2164          * any column / row could be removed and the new grid constructed
2165          *  @param array {object} aLayout Array to store the calculated layout in
2166          *  @param {node} nThead The header/footer element for the table
2167          *  @memberof DataTable#oApi
2168          */
2169         function _fnDetectHeader ( aLayout, nThead )
2170         {
2171                 var nTrs = $(nThead).children('tr');
2172                 var nTr, nCell;
2173                 var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
2174                 var bUnique;
2175                 var fnShiftCol = function ( a, i, j ) {
2176                         var k = a[i];
2177                         while ( k[j] ) {
2178                                 j++;
2179                         }
2180                         return j;
2181                 };
2182         
2183                 aLayout.splice( 0, aLayout.length );
2184         
2185                 /* We know how many rows there are in the layout - so prep it */
2186                 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
2187                 {
2188                         aLayout.push( [] );
2189                 }
2190         
2191                 /* Calculate a layout array */
2192                 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
2193                 {
2194                         nTr = nTrs[i];
2195                         iColumn = 0;
2196         
2197                         /* For every cell in the row... */
2198                         nCell = nTr.firstChild;
2199                         while ( nCell ) {
2200                                 if ( nCell.nodeName.toUpperCase() == "TD" ||
2201                                      nCell.nodeName.toUpperCase() == "TH" )
2202                                 {
2203                                         /* Get the col and rowspan attributes from the DOM and sanitise them */
2204                                         iColspan = nCell.getAttribute('colspan') * 1;
2205                                         iRowspan = nCell.getAttribute('rowspan') * 1;
2206                                         iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
2207                                         iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
2208         
2209                                         /* There might be colspan cells already in this row, so shift our target
2210                                          * accordingly
2211                                          */
2212                                         iColShifted = fnShiftCol( aLayout, i, iColumn );
2213         
2214                                         /* Cache calculation for unique columns */
2215                                         bUnique = iColspan === 1 ? true : false;
2216         
2217                                         /* If there is col / rowspan, copy the information into the layout grid */
2218                                         for ( l=0 ; l<iColspan ; l++ )
2219                                         {
2220                                                 for ( k=0 ; k<iRowspan ; k++ )
2221                                                 {
2222                                                         aLayout[i+k][iColShifted+l] = {
2223                                                                 "cell": nCell,
2224                                                                 "unique": bUnique
2225                                                         };
2226                                                         aLayout[i+k].nTr = nTr;
2227                                                 }
2228                                         }
2229                                 }
2230                                 nCell = nCell.nextSibling;
2231                         }
2232                 }
2233         }
2234         
2235         
2236         /**
2237          * Get an array of unique th elements, one for each column
2238          *  @param {object} oSettings dataTables settings object
2239          *  @param {node} nHeader automatically detect the layout from this node - optional
2240          *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
2241          *  @returns array {node} aReturn list of unique th's
2242          *  @memberof DataTable#oApi
2243          */
2244         function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
2245         {
2246                 var aReturn = [];
2247                 if ( !aLayout )
2248                 {
2249                         aLayout = oSettings.aoHeader;
2250                         if ( nHeader )
2251                         {
2252                                 aLayout = [];
2253                                 _fnDetectHeader( aLayout, nHeader );
2254                         }
2255                 }
2256         
2257                 for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
2258                 {
2259                         for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
2260                         {
2261                                 if ( aLayout[i][j].unique &&
2262                                          (!aReturn[j] || !oSettings.bSortCellsTop) )
2263                                 {
2264                                         aReturn[j] = aLayout[i][j].cell;
2265                                 }
2266                         }
2267                 }
2268         
2269                 return aReturn;
2270         }
2271         
2272         
2273         
2274         /**
2275          * Create an Ajax call based on the table's settings, taking into account that
2276          * parameters can have multiple forms, and backwards compatibility.
2277          *
2278          * @param {object} oSettings dataTables settings object
2279          * @param {array} data Data to send to the server, required by
2280          *     DataTables - may be augmented by developer callbacks
2281          * @param {function} fn Callback function to run when data is obtained
2282          */
2283         function _fnBuildAjax( oSettings, data, fn )
2284         {
2285                 // Compatibility with 1.9-, allow fnServerData and event to manipulate
2286                 _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
2287         
2288                 // Convert to object based for 1.10+ if using the old array scheme which can
2289                 // come from server-side processing or serverParams
2290                 if ( data && $.isArray(data) ) {
2291                         var tmp = {};
2292                         var rbracket = /(.*?)\[\]$/;
2293         
2294                         $.each( data, function (key, val) {
2295                                 var match = val.name.match(rbracket);
2296         
2297                                 if ( match ) {
2298                                         // Support for arrays
2299                                         var name = match[0];
2300         
2301                                         if ( ! tmp[ name ] ) {
2302                                                 tmp[ name ] = [];
2303                                         }
2304                                         tmp[ name ].push( val.value );
2305                                 }
2306                                 else {
2307                                         tmp[val.name] = val.value;
2308                                 }
2309                         } );
2310                         data = tmp;
2311                 }
2312         
2313                 var ajaxData;
2314                 var ajax = oSettings.ajax;
2315                 var instance = oSettings.oInstance;
2316         
2317                 if ( $.isPlainObject( ajax ) && ajax.data )
2318                 {
2319                         ajaxData = ajax.data;
2320         
2321                         var newData = $.isFunction( ajaxData ) ?
2322                                 ajaxData( data ) :  // fn can manipulate data or return an object
2323                                 ajaxData;           // object or array to merge
2324         
2325                         // If the function returned an object, use that alone
2326                         data = $.isFunction( ajaxData ) && newData ?
2327                                 newData :
2328                                 $.extend( true, data, newData );
2329         
2330                         // Remove the data property as we've resolved it already and don't want
2331                         // jQuery to do it again (it is restored at the end of the function)
2332                         delete ajax.data;
2333                 }
2334         
2335                 var baseAjax = {
2336                         "data": data,
2337                         "success": function (json) {
2338                                 var error = json.error || json.sError;
2339                                 if ( error ) {
2340                                         oSettings.oApi._fnLog( oSettings, 0, error );
2341                                 }
2342         
2343                                 oSettings.json = json;
2344                                 _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json] );
2345                                 fn( json );
2346                         },
2347                         "dataType": "json",
2348                         "cache": false,
2349                         "type": oSettings.sServerMethod,
2350                         "error": function (xhr, error, thrown) {
2351                                 var log = oSettings.oApi._fnLog;
2352         
2353                                 if ( error == "parsererror" ) {
2354                                         log( oSettings, 0, 'Invalid JSON response', 1 );
2355                                 }
2356                                 else if ( xhr.readyState === 4 ) {
2357                                         log( oSettings, 0, 'Ajax error', 7 );
2358                                 }
2359         
2360                                 _fnProcessingDisplay( oSettings, false );
2361                         }
2362                 };
2363         
2364                 // Store the data submitted for the API
2365                 oSettings.oAjaxData = data;
2366         
2367                 // Allow plug-ins and external processes to modify the data
2368                 _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
2369         
2370                 if ( oSettings.fnServerData )
2371                 {
2372                         // DataTables 1.9- compatibility
2373                         oSettings.fnServerData.call( instance,
2374                                 oSettings.sAjaxSource,
2375                                 $.map( data, function (val, key) { // Need to convert back to 1.9 trad format
2376                                         return { name: key, value: val };
2377                                 } ),
2378                                 fn,
2379                                 oSettings
2380                         );
2381                 }
2382                 else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
2383                 {
2384                         // DataTables 1.9- compatibility
2385                         oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
2386                                 url: ajax || oSettings.sAjaxSource
2387                         } ) );
2388                 }
2389                 else if ( $.isFunction( ajax ) )
2390                 {
2391                         // Is a function - let the caller define what needs to be done
2392                         oSettings.jqXHR = ajax.call( instance, data, fn, oSettings );
2393                 }
2394                 else
2395                 {
2396                         // Object to extend the base settings
2397                         oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
2398         
2399                         // Restore for next time around
2400                         ajax.data = ajaxData;
2401                 }
2402         }
2403         
2404         
2405         /**
2406          * Update the table using an Ajax call
2407          *  @param {object} oSettings dataTables settings object
2408          *  @returns {boolean} Block the table drawing or not
2409          *  @memberof DataTable#oApi
2410          */
2411         function _fnAjaxUpdate( oSettings )
2412         {
2413                 if ( oSettings.bAjaxDataGet )
2414                 {
2415                         oSettings.iDraw++;
2416                         _fnProcessingDisplay( oSettings, true );
2417                         var iColumns = oSettings.aoColumns.length;
2418                         var aoData = _fnAjaxParameters( oSettings );
2419         
2420                         _fnBuildAjax( oSettings, aoData, function(json) {
2421                                 _fnAjaxUpdateDraw( oSettings, json );
2422                         }, oSettings );
2423         
2424                         return false;
2425                 }
2426                 return true;
2427         }
2428         
2429         
2430         /**
2431          * Build up the parameters in an object needed for a server-side processing
2432          * request. Note that this is basically done twice, is different ways - a modern
2433          * method which is used by default in DataTables 1.10 which uses objects and
2434          * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
2435          * the sAjaxSource option is used in the initialisation, or the legacyAjax
2436          * option is set.
2437          *  @param {object} oSettings dataTables settings object
2438          *  @returns {bool} block the table drawing or not
2439          *  @memberof DataTable#oApi
2440          */
2441         function _fnAjaxParameters( settings )
2442         {
2443                 var
2444                         columns = settings.aoColumns,
2445                         columnCount = columns.length,
2446                         features = settings.oFeatures,
2447                         preSearch = settings.oPreviousSearch,
2448                         preColSearch = settings.aoPreSearchCols,
2449                         i, data = [], dataProp, column, columnSearch,
2450                         sort = _fnSortFlatten( settings ),
2451                         displayStart = settings._iDisplayStart,
2452                         displayLength = features.bPaginate !== false ?
2453                                 settings._iDisplayLength :
2454                                 -1;
2455         
2456                 var param = function ( name, value ) {
2457                         data.push( { 'name': name, 'value': value } );
2458                 };
2459         
2460                 // DataTables 1.9- compatible method
2461                 param( 'sEcho',          settings.iDraw );
2462                 param( 'iColumns',       columnCount );
2463                 param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
2464                 param( 'iDisplayStart',  displayStart );
2465                 param( 'iDisplayLength', displayLength );
2466         
2467                 // DataTables 1.10+ method
2468                 var d = {
2469                         draw:    settings.iDraw,
2470                         columns: [],
2471                         order:   [],
2472                         start:   displayStart,
2473                         length:  displayLength,
2474                         search:  {
2475                                 value: preSearch.sSearch,
2476                                 regex: preSearch.bRegex
2477                         }
2478                 };
2479         
2480                 for ( i=0 ; i<columnCount ; i++ ) {
2481                         column = columns[i];
2482                         columnSearch = preColSearch[i];
2483                         dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
2484         
2485                         d.columns.push( {
2486                                 data:       dataProp,
2487                                 name:       column.sName,
2488                                 searchable: column.bSearchable,
2489                                 orderable:  column.bSortable,
2490                                 search:     {
2491                                         value: columnSearch.sSearch,
2492                                         regex: columnSearch.bRegex
2493                                 }
2494                         } );
2495         
2496                         param( "mDataProp_"+i, dataProp );
2497         
2498                         if ( features.bFilter ) {
2499                                 param( 'sSearch_'+i,     columnSearch.sSearch );
2500                                 param( 'bRegex_'+i,      columnSearch.bRegex );
2501                                 param( 'bSearchable_'+i, column.bSearchable );
2502                         }
2503         
2504                         if ( features.bSort ) {
2505                                 param( 'bSortable_'+i, column.bSortable );
2506                         }
2507                 }
2508         
2509                 if ( features.bFilter ) {
2510                         param( 'sSearch', preSearch.sSearch );
2511                         param( 'bRegex', preSearch.bRegex );
2512                 }
2513         
2514                 if ( features.bSort ) {
2515                         $.each( sort, function ( i, val ) {
2516                                 d.order.push( { column: val.col, dir: val.dir } );
2517         
2518                                 param( 'iSortCol_'+i, val.col );
2519                                 param( 'sSortDir_'+i, val.dir );
2520                         } );
2521         
2522                         param( 'iSortingCols', sort.length );
2523                 }
2524         
2525                 // If the legacy.ajax parameter is null, then we automatically decide which
2526                 // form to use, based on sAjaxSource
2527                 var legacy = DataTable.ext.legacy.ajax;
2528                 if ( legacy === null ) {
2529                         return settings.sAjaxSource ? data : d;
2530                 }
2531         
2532                 // Otherwise, if legacy has been specified then we use that to decide on the
2533                 // form
2534                 return legacy ? data : d;
2535         }
2536         
2537         
2538         /**
2539          * Data the data from the server (nuking the old) and redraw the table
2540          *  @param {object} oSettings dataTables settings object
2541          *  @param {object} json json data return from the server.
2542          *  @param {string} json.sEcho Tracking flag for DataTables to match requests
2543          *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
2544          *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
2545          *  @param {array} json.aaData The data to display on this page
2546          *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
2547          *  @memberof DataTable#oApi
2548          */
2549         function _fnAjaxUpdateDraw ( settings, json )
2550         {
2551                 // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
2552                 // Support both
2553                 var compat = function ( old, modern ) {
2554                         return json[old] !== undefined ? json[old] : json[modern];
2555                 };
2556         
2557                 var draw            = compat( 'sEcho',                'draw' );
2558                 var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
2559                 var rocordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
2560         
2561                 if ( draw ) {
2562                         // Protect against out of sequence returns
2563                         if ( draw*1 < settings.iDraw ) {
2564                                 return;
2565                         }
2566                         settings.iDraw = draw * 1;
2567                 }
2568         
2569                 _fnClearTable( settings );
2570                 settings._iRecordsTotal   = parseInt(recordsTotal, 10);
2571                 settings._iRecordsDisplay = parseInt(rocordsFiltered, 10);
2572         
2573                 var data = _fnAjaxDataSrc( settings, json );
2574                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
2575                         _fnAddData( settings, data[i] );
2576                 }
2577                 settings.aiDisplay = settings.aiDisplayMaster.slice();
2578         
2579                 settings.bAjaxDataGet = false;
2580                 _fnDraw( settings );
2581         
2582                 if ( ! settings._bInitComplete ) {
2583                         _fnInitComplete( settings, json );
2584                 }
2585         
2586                 settings.bAjaxDataGet = true;
2587                 _fnProcessingDisplay( settings, false );
2588         }
2589         
2590         
2591         /**
2592          * Get the data from the JSON data source to use for drawing a table. Using
2593          * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
2594          * source object, or from a processing function.
2595          *  @param {object} oSettings dataTables settings object
2596          *  @param  {object} json Data source object / array from the server
2597          *  @return {array} Array of data to use
2598          */
2599         function _fnAjaxDataSrc ( oSettings, json )
2600         {
2601                 var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
2602                         oSettings.ajax.dataSrc :
2603                         oSettings.sAjaxDataProp; // Compatibility with 1.9-.
2604         
2605                 // Compatibility with 1.9-. In order to read from aaData, check if the
2606                 // default has been changed, if not, check for aaData
2607                 if ( dataSrc === 'data' ) {
2608                         return json.aaData || json[dataSrc];
2609                 }
2610         
2611                 return dataSrc !== "" ?
2612                         _fnGetObjectDataFn( dataSrc )( json ) :
2613                         json;
2614         }
2615         
2616         
2617         /**
2618          * Generate the node required for filtering text
2619          *  @returns {node} Filter control element
2620          *  @param {object} oSettings dataTables settings object
2621          *  @memberof DataTable#oApi
2622          */
2623         function _fnFeatureHtmlFilter ( settings )
2624         {
2625                 var classes = settings.oClasses;
2626                 var tableId = settings.sTableId;
2627                 var previousSearch = settings.oPreviousSearch;
2628                 var features = settings.aanFeatures;
2629                 var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
2630         
2631                 var str = settings.oLanguage.sSearch;
2632                 str = str.match(/_INPUT_/) ?
2633                         str.replace('_INPUT_', input) :
2634                         str+input;
2635         
2636                 var filter = $('<div/>', {
2637                                 'id': ! features.f ? tableId+'_filter' : null,
2638                                 'class': classes.sFilter
2639                         } )
2640                         .append( $('<label/>' ).append( str ) );
2641         
2642                 var searchFn = function() {
2643                         /* Update all other filter input elements for the new display */
2644                         var n = features.f;
2645                         var val = !this.value ? "" : this.value; // mental IE8 fix :-(
2646         
2647                         /* Now do the filter */
2648                         if ( val != previousSearch.sSearch ) {
2649                                 _fnFilterComplete( settings, {
2650                                         "sSearch": val,
2651                                         "bRegex": previousSearch.bRegex,
2652                                         "bSmart": previousSearch.bSmart ,
2653                                         "bCaseInsensitive": previousSearch.bCaseInsensitive
2654                                 } );
2655         
2656                                 // Need to redraw, without resorting
2657                                 settings._iDisplayStart = 0;
2658                                 _fnDraw( settings );
2659                         }
2660                 };
2661                 var jqFilter = $('input', filter)
2662                         .val( previousSearch.sSearch.replace('"','&quot;') )
2663                         .bind(
2664                                 'keyup.DT search.DT input.DT paste.DT cut.DT',
2665                                 _fnDataSource( settings ) === 'ssp' ?
2666                                         _fnThrottle( searchFn, 400 ):
2667                                         searchFn
2668                         )
2669                         .bind( 'keypress.DT', function(e) {
2670                                 /* Prevent form submission */
2671                                 if ( e.keyCode == 13 ) {
2672                                         return false;
2673                                 }
2674                         } )
2675                         .attr('aria-controls', tableId);
2676         
2677                 // Update the input elements whenever the table is filtered
2678                 $(settings.nTable).on( 'filter.DT', function () {
2679                         // IE9 throws an 'unknown error' if document.activeElement is used
2680                         // inside an iframe or frame...
2681                         try {
2682                                 if ( jqFilter[0] !== document.activeElement ) {
2683                                         jqFilter.val( previousSearch.sSearch );
2684                                 }
2685                         }
2686                         catch ( e ) {}
2687                 } );
2688         
2689                 return filter[0];
2690         }
2691         
2692         
2693         /**
2694          * Filter the table using both the global filter and column based filtering
2695          *  @param {object} oSettings dataTables settings object
2696          *  @param {object} oSearch search information
2697          *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
2698          *  @memberof DataTable#oApi
2699          */
2700         function _fnFilterComplete ( oSettings, oInput, iForce )
2701         {
2702                 var oPrevSearch = oSettings.oPreviousSearch;
2703                 var aoPrevSearch = oSettings.aoPreSearchCols;
2704                 var fnSaveFilter = function ( oFilter ) {
2705                         /* Save the filtering values */
2706                         oPrevSearch.sSearch = oFilter.sSearch;
2707                         oPrevSearch.bRegex = oFilter.bRegex;
2708                         oPrevSearch.bSmart = oFilter.bSmart;
2709                         oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
2710                 };
2711                 var fnRegex = function ( o ) {
2712                         // Backwards compatibility with the bEscapeRegex option
2713                         return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
2714                 };
2715         
2716                 // Resolve any column types that are unknown due to addition or invalidation
2717                 // @todo As per sort - can this be moved into an event handler?
2718                 _fnColumnTypes( oSettings );
2719         
2720                 /* In server-side processing all filtering is done by the server, so no point hanging around here */
2721                 if ( _fnDataSource( oSettings ) != 'ssp' )
2722                 {
2723                         /* Global filter */
2724                         _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
2725                         fnSaveFilter( oInput );
2726         
2727                         /* Now do the individual column filter */
2728                         for ( var i=0 ; i<aoPrevSearch.length ; i++ )
2729                         {
2730                                 _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
2731                                         aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
2732                         }
2733         
2734                         /* Custom filtering */
2735                         _fnFilterCustom( oSettings );
2736                 }
2737                 else
2738                 {
2739                         fnSaveFilter( oInput );
2740                 }
2741         
2742                 /* Tell the draw function we have been filtering */
2743                 oSettings.bFiltered = true;
2744                 _fnCallbackFire( oSettings, null, 'search', [oSettings] );
2745         }
2746         
2747         
2748         /**
2749          * Apply custom filtering functions
2750          *  @param {object} oSettings dataTables settings object
2751          *  @memberof DataTable#oApi
2752          */
2753         function _fnFilterCustom( settings )
2754         {
2755                 var filters = DataTable.ext.search;
2756                 var displayRows = settings.aiDisplay;
2757                 var row, rowIdx;
2758         
2759                 for ( var i=0, iLen=filters.length ; i<iLen ; i++ ) {
2760                         for ( var j=displayRows.length-1 ; j>=0 ; j-- ) {
2761                                 rowIdx = displayRows[ j ];
2762                                 row = settings.aoData[ rowIdx ];
2763         
2764                                 if ( ! filters[i]( settings, row._aFilterData, rowIdx, row._aData ) ) {
2765                                         displayRows.splice( j, 1 );
2766                                 }
2767                         }
2768                 }
2769         }
2770         
2771         
2772         /**
2773          * Filter the table on a per-column basis
2774          *  @param {object} oSettings dataTables settings object
2775          *  @param {string} sInput string to filter on
2776          *  @param {int} iColumn column to filter
2777          *  @param {bool} bRegex treat search string as a regular expression or not
2778          *  @param {bool} bSmart use smart filtering or not
2779          *  @param {bool} bCaseInsensitive Do case insenstive matching or not
2780          *  @memberof DataTable#oApi
2781          */
2782         function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
2783         {
2784                 if ( searchStr === '' ) {
2785                         return;
2786                 }
2787         
2788                 var data;
2789                 var display = settings.aiDisplay;
2790                 var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
2791         
2792                 for ( var i=display.length-1 ; i>=0 ; i-- ) {
2793                         data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
2794         
2795                         if ( ! rpSearch.test( data ) ) {
2796                                 display.splice( i, 1 );
2797                         }
2798                 }
2799         }
2800         
2801         
2802         /**
2803          * Filter the data table based on user input and draw the table
2804          *  @param {object} settings dataTables settings object
2805          *  @param {string} input string to filter on
2806          *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
2807          *  @param {bool} regex treat as a regular expression or not
2808          *  @param {bool} smart perform smart filtering or not
2809          *  @param {bool} caseInsensitive Do case insenstive matching or not
2810          *  @memberof DataTable#oApi
2811          */
2812         function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
2813         {
2814                 var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
2815                 var prevSearch = settings.oPreviousSearch.sSearch;
2816                 var displayMaster = settings.aiDisplayMaster;
2817                 var display, invalidated, i;
2818         
2819                 // Need to take account of custom filtering functions - always filter
2820                 if ( DataTable.ext.search.length !== 0 ) {
2821                         force = true;
2822                 }
2823         
2824                 // Check if any of the rows were invalidated
2825                 invalidated = _fnFilterData( settings );
2826         
2827                 // If the input is blank - we just want the full data set
2828                 if ( input.length <= 0 ) {
2829                         settings.aiDisplay = displayMaster.slice();
2830                 }
2831                 else {
2832                         // New search - start from the master array
2833                         if ( invalidated ||
2834                                  force ||
2835                                  prevSearch.length > input.length ||
2836                                  input.indexOf(prevSearch) !== 0 ||
2837                                  settings.bSorted // On resort, the display master needs to be
2838                                                   // re-filtered since indexes will have changed
2839                         ) {
2840                                 settings.aiDisplay = displayMaster.slice();
2841                         }
2842         
2843                         // Search the display array
2844                         display = settings.aiDisplay;
2845         
2846                         for ( i=display.length-1 ; i>=0 ; i-- ) {
2847                                 if ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
2848                                         display.splice( i, 1 );
2849                                 }
2850                         }
2851                 }
2852         }
2853         
2854         
2855         /**
2856          * Build a regular expression object suitable for searching a table
2857          *  @param {string} sSearch string to search for
2858          *  @param {bool} bRegex treat as a regular expression or not
2859          *  @param {bool} bSmart perform smart filtering or not
2860          *  @param {bool} bCaseInsensitive Do case insensitive matching or not
2861          *  @returns {RegExp} constructed object
2862          *  @memberof DataTable#oApi
2863          */
2864         function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
2865         {
2866                 search = regex ?
2867                         search :
2868                         _fnEscapeRegex( search );
2869                 
2870                 if ( smart ) {
2871                         /* For smart filtering we want to allow the search to work regardless of
2872                          * word order. We also want double quoted text to be preserved, so word
2873                          * order is important - a la google. So this is what we want to
2874                          * generate:
2875                          * 
2876                          * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
2877                          */
2878                         var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || '', function ( word ) {
2879                                 return word.charAt(0) === '"' ?
2880                                         word.match( /^"(.*)"$/ )[1] :
2881                                         word;
2882                         } );
2883         
2884                         search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
2885                 }
2886         
2887                 return new RegExp( search, caseInsensitive ? 'i' : '' );
2888         }
2889         
2890         
2891         /**
2892          * scape a string such that it can be used in a regular expression
2893          *  @param {string} sVal string to escape
2894          *  @returns {string} escaped string
2895          *  @memberof DataTable#oApi
2896          */
2897         function _fnEscapeRegex ( sVal )
2898         {
2899                 return sVal.replace( _re_escape_regex, '\\$1' );
2900         }
2901         
2902         
2903         
2904         var __filter_div = $('<div>')[0];
2905         var __filter_div_textContent = __filter_div.textContent !== undefined;
2906         
2907         // Update the filtering data for each row if needed (by invalidation or first run)
2908         function _fnFilterData ( settings )
2909         {
2910                 var columns = settings.aoColumns;
2911                 var column;
2912                 var i, j, ien, jen, filterData, cellData, row;
2913                 var fomatters = DataTable.ext.type.search;
2914                 var wasInvalidated = false;
2915         
2916                 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
2917                         row = settings.aoData[i];
2918         
2919                         if ( ! row._aFilterData ) {
2920                                 filterData = [];
2921         
2922                                 for ( j=0, jen=columns.length ; j<jen ; j++ ) {
2923                                         column = columns[j];
2924         
2925                                         if ( column.bSearchable ) {
2926                                                 cellData = _fnGetCellData( settings, i, j, 'filter' );
2927         
2928                                                 cellData = fomatters[ column.sType ] ?
2929                                                         fomatters[ column.sType ]( cellData ) :
2930                                                         cellData !== null ?
2931                                                                 cellData :
2932                                                                 '';
2933                                         }
2934                                         else {
2935                                                 cellData = '';
2936                                         }
2937         
2938                                         // If it looks like there is an HTML entity in the string,
2939                                         // attempt to decode it so sorting works as expected. Note that
2940                                         // we could use a single line of jQuery to do this, but the DOM
2941                                         // method used here is much faster http://jsperf.com/html-decode
2942                                         if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
2943                                                 __filter_div.innerHTML = cellData;
2944                                                 cellData = __filter_div_textContent ?
2945                                                         __filter_div.textContent :
2946                                                         __filter_div.innerText;
2947                                         }
2948         
2949                                         if ( cellData.replace ) {
2950                                                 cellData = cellData.replace(/[\r\n]/g, '');
2951                                         }
2952         
2953                                         filterData.push( cellData );
2954                                 }
2955         
2956                                 row._aFilterData = filterData;
2957                                 row._sFilterRow = filterData.join('  ');
2958                                 wasInvalidated = true;
2959                         }
2960                 }
2961         
2962                 return wasInvalidated;
2963         }
2964         
2965         /**
2966          * Generate the node required for the info display
2967          *  @param {object} oSettings dataTables settings object
2968          *  @returns {node} Information element
2969          *  @memberof DataTable#oApi
2970          */
2971         function _fnFeatureHtmlInfo ( settings )
2972         {
2973                 var
2974                         tid = settings.sTableId,
2975                         nodes = settings.aanFeatures.i,
2976                         n = $('<div/>', {
2977                                 'class': settings.oClasses.sInfo,
2978                                 'id': ! nodes ? tid+'_info' : null
2979                         } );
2980         
2981                 if ( ! nodes ) {
2982                         // Update display on each draw
2983                         settings.aoDrawCallback.push( {
2984                                 "fn": _fnUpdateInfo,
2985                                 "sName": "information"
2986                         } );
2987         
2988                         n
2989                                 .attr( 'role', 'status' )
2990                                 .attr( 'aria-live', 'polite' );
2991         
2992                         // Table is described by our info div
2993                         $(settings.nTable).attr( 'aria-describedby', tid+'_info' );
2994                 }
2995         
2996                 return n[0];
2997         }
2998         
2999         
3000         /**
3001          * Update the information elements in the display
3002          *  @param {object} settings dataTables settings object
3003          *  @memberof DataTable#oApi
3004          */
3005         function _fnUpdateInfo ( settings )
3006         {
3007                 /* Show information about the table */
3008                 var nodes = settings.aanFeatures.i;
3009                 if ( nodes.length === 0 ) {
3010                         return;
3011                 }
3012         
3013                 var
3014                         lang  = settings.oLanguage,
3015                         start = settings._iDisplayStart+1,
3016                         end   = settings.fnDisplayEnd(),
3017                         max   = settings.fnRecordsTotal(),
3018                         total = settings.fnRecordsDisplay(),
3019                         out   = total ?
3020                                 lang.sInfo :
3021                                 lang.sInfoEmpty;
3022         
3023                 if ( total !== max ) {
3024                         /* Record set after filtering */
3025                         out += ' ' + lang.sInfoFiltered;
3026                 }
3027         
3028                 // Convert the macros
3029                 out += lang.sInfoPostFix;
3030                 out = _fnInfoMacros( settings, out );
3031         
3032                 var callback = lang.fnInfoCallback;
3033                 if ( callback !== null ) {
3034                         out = callback.call( settings.oInstance,
3035                                 settings, start, end, max, total, out
3036                         );
3037                 }
3038         
3039                 $(nodes).html( out );
3040         }
3041         
3042         
3043         function _fnInfoMacros ( settings, str )
3044         {
3045                 // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
3046                 // internally
3047                 var
3048                         formatter  = settings.fnFormatNumber,
3049                         start      = settings._iDisplayStart+1,
3050                         len        = settings._iDisplayLength,
3051                         vis        = settings.fnRecordsDisplay(),
3052                         all        = len === -1;
3053         
3054                 return str.
3055                         replace(/_START_/g, formatter.call( settings, start ) ).
3056                         replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
3057                         replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
3058                         replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
3059                         replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
3060                         replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
3061         }
3062         
3063         
3064         
3065         /**
3066          * Draw the table for the first time, adding all required features
3067          *  @param {object} settings dataTables settings object
3068          *  @memberof DataTable#oApi
3069          */
3070         function _fnInitialise ( settings )
3071         {
3072                 var i, iLen, iAjaxStart=settings.iInitDisplayStart;
3073                 var columns = settings.aoColumns, column;
3074                 var features = settings.oFeatures;
3075         
3076                 /* Ensure that the table data is fully initialised */
3077                 if ( ! settings.bInitialised ) {
3078                         setTimeout( function(){ _fnInitialise( settings ); }, 200 );
3079                         return;
3080                 }
3081         
3082                 /* Show the display HTML options */
3083                 _fnAddOptionsHtml( settings );
3084         
3085                 /* Build and draw the header / footer for the table */
3086                 _fnBuildHead( settings );
3087                 _fnDrawHead( settings, settings.aoHeader );
3088                 _fnDrawHead( settings, settings.aoFooter );
3089         
3090                 /* Okay to show that something is going on now */
3091                 _fnProcessingDisplay( settings, true );
3092         
3093                 /* Calculate sizes for columns */
3094                 if ( features.bAutoWidth ) {
3095                         _fnCalculateColumnWidths( settings );
3096                 }
3097         
3098                 for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
3099                         column = columns[i];
3100         
3101                         if ( column.sWidth ) {
3102                                 column.nTh.style.width = _fnStringToCss( column.sWidth );
3103                         }
3104                 }
3105         
3106                 // If there is default sorting required - let's do it. The sort function
3107                 // will do the drawing for us. Otherwise we draw the table regardless of the
3108                 // Ajax source - this allows the table to look initialised for Ajax sourcing
3109                 // data (show 'loading' message possibly)
3110                 _fnReDraw( settings );
3111         
3112                 // Server-side processing init complete is done by _fnAjaxUpdateDraw
3113                 var dataSrc = _fnDataSource( settings );
3114                 if ( dataSrc != 'ssp' ) {
3115                         // if there is an ajax source load the data
3116                         if ( dataSrc == 'ajax' ) {
3117                                 _fnBuildAjax( settings, [], function(json) {
3118                                         var aData = _fnAjaxDataSrc( settings, json );
3119         
3120                                         // Got the data - add it to the table
3121                                         for ( i=0 ; i<aData.length ; i++ ) {
3122                                                 _fnAddData( settings, aData[i] );
3123                                         }
3124         
3125                                         // Reset the init display for cookie saving. We've already done
3126                                         // a filter, and therefore cleared it before. So we need to make
3127                                         // it appear 'fresh'
3128                                         settings.iInitDisplayStart = iAjaxStart;
3129         
3130                                         _fnReDraw( settings );
3131         
3132                                         _fnProcessingDisplay( settings, false );
3133                                         _fnInitComplete( settings, json );
3134                                 }, settings );
3135                         }
3136                         else {
3137                                 _fnProcessingDisplay( settings, false );
3138                                 _fnInitComplete( settings );
3139                         }
3140                 }
3141         }
3142         
3143         
3144         /**
3145          * Draw the table for the first time, adding all required features
3146          *  @param {object} oSettings dataTables settings object
3147          *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
3148          *    with client-side processing (optional)
3149          *  @memberof DataTable#oApi
3150          */
3151         function _fnInitComplete ( settings, json )
3152         {
3153                 settings._bInitComplete = true;
3154         
3155                 // On an Ajax load we now have data and therefore want to apply the column
3156                 // sizing
3157                 if ( json ) {
3158                         _fnAdjustColumnSizing( settings );
3159                 }
3160         
3161                 _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
3162         }
3163         
3164         
3165         function _fnLengthChange ( settings, val )
3166         {
3167                 var len = parseInt( val, 10 );
3168                 settings._iDisplayLength = len;
3169         
3170                 _fnLengthOverflow( settings );
3171         
3172                 // Fire length change event
3173                 _fnCallbackFire( settings, null, 'length', [settings, len] );
3174         }
3175         
3176         
3177         /**
3178          * Generate the node required for user display length changing
3179          *  @param {object} settings dataTables settings object
3180          *  @returns {node} Display length feature node
3181          *  @memberof DataTable#oApi
3182          */
3183         function _fnFeatureHtmlLength ( settings )
3184         {
3185                 var
3186                         classes  = settings.oClasses,
3187                         tableId  = settings.sTableId,
3188                         menu     = settings.aLengthMenu,
3189                         d2       = $.isArray( menu[0] ),
3190                         lengths  = d2 ? menu[0] : menu,
3191                         language = d2 ? menu[1] : menu;
3192         
3193                 var select = $('<select/>', {
3194                         'name':          tableId+'_length',
3195                         'aria-controls': tableId,
3196                         'class':         classes.sLengthSelect
3197                 } );
3198         
3199                 for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
3200                         select[0][ i ] = new Option( language[i], lengths[i] );
3201                 }
3202         
3203                 var div = $('<div><label/></div>').addClass( classes.sLength );
3204                 if ( ! settings.aanFeatures.l ) {
3205                         div[0].id = tableId+'_length';
3206                 }
3207         
3208                 var a = settings.oLanguage.sLengthMenu.split(/(_MENU_)/);
3209                 div.children().append( a.length > 1 ?
3210                         [ a[0], select, a[2] ] :
3211                         a[0]
3212                 );
3213         
3214                 // Can't use `select` variable, as user might provide their own select menu
3215                 $('select', div)
3216                         .val( settings._iDisplayLength )
3217                         .bind( 'change.DT', function(e) {
3218                                 _fnLengthChange( settings, $(this).val() );
3219                                 _fnDraw( settings );
3220                         } );
3221         
3222                 // Update node value whenever anything changes the table's length
3223                 $(settings.nTable).bind( 'length.dt.DT', function (e, s, len) {
3224                         $('select', div).val( len );
3225                 } );
3226         
3227                 return div[0];
3228         }
3229         
3230         
3231         
3232         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3233          * Note that most of the paging logic is done in
3234          * DataTable.ext.pager
3235          */
3236         
3237         /**
3238          * Generate the node required for default pagination
3239          *  @param {object} oSettings dataTables settings object
3240          *  @returns {node} Pagination feature node
3241          *  @memberof DataTable#oApi
3242          */
3243         function _fnFeatureHtmlPaginate ( settings )
3244         {
3245                 var
3246                         type   = settings.sPaginationType,
3247                         plugin = DataTable.ext.pager[ type ],
3248                         modern = typeof plugin === 'function',
3249                         redraw = function( settings ) {
3250                                 _fnDraw( settings );
3251                         },
3252                         node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
3253                         features = settings.aanFeatures;
3254         
3255                 if ( ! modern ) {
3256                         plugin.fnInit( settings, node, redraw );
3257                 }
3258         
3259                 /* Add a draw callback for the pagination on first instance, to update the paging display */
3260                 if ( ! features.p )
3261                 {
3262                         node.id = settings.sTableId+'_paginate';
3263         
3264                         settings.aoDrawCallback.push( {
3265                                 "fn": function( settings ) {
3266                                         if ( modern ) {
3267                                                 var
3268                                                         start      = settings._iDisplayStart,
3269                                                         len        = settings._iDisplayLength,
3270                                                         visRecords = settings.fnRecordsDisplay(),
3271                                                         all        = len === -1,
3272                                                         page = all ? 0 : Math.ceil( start / len ),
3273                                                         pages = all ? 1 : Math.ceil( visRecords / len ),
3274                                                         buttons = plugin(page, pages),
3275                                                         i, ien;
3276         
3277                                                 for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
3278                                                         _fnRenderer( settings, 'pageButton' )(
3279                                                                 settings, features.p[i], i, buttons, page, pages
3280                                                         );
3281                                                 }
3282                                         }
3283                                         else {
3284                                                 plugin.fnUpdate( settings, redraw );
3285                                         }
3286                                 },
3287                                 "sName": "pagination"
3288                         } );
3289                 }
3290         
3291                 return node;
3292         }
3293         
3294         
3295         /**
3296          * Alter the display settings to change the page
3297          *  @param {object} settings DataTables settings object
3298          *  @param {string|int} action Paging action to take: "first", "previous",
3299          *    "next" or "last" or page number to jump to (integer)
3300          *  @param [bool] redraw Automatically draw the update or not
3301          *  @returns {bool} true page has changed, false - no change
3302          *  @memberof DataTable#oApi
3303          */
3304         function _fnPageChange ( settings, action, redraw )
3305         {
3306                 var
3307                         start     = settings._iDisplayStart,
3308                         len       = settings._iDisplayLength,
3309                         records   = settings.fnRecordsDisplay();
3310         
3311                 if ( records === 0 || len === -1 )
3312                 {
3313                         start = 0;
3314                 }
3315                 else if ( typeof action === "number" )
3316                 {
3317                         start = action * len;
3318         
3319                         if ( start > records )
3320                         {
3321                                 start = 0;
3322                         }
3323                 }
3324                 else if ( action == "first" )
3325                 {
3326                         start = 0;
3327                 }
3328                 else if ( action == "previous" )
3329                 {
3330                         start = len >= 0 ?
3331                                 start - len :
3332                                 0;
3333         
3334                         if ( start < 0 )
3335                         {
3336                           start = 0;
3337                         }
3338                 }
3339                 else if ( action == "next" )
3340                 {
3341                         if ( start + len < records )
3342                         {
3343                                 start += len;
3344                         }
3345                 }
3346                 else if ( action == "last" )
3347                 {
3348                         start = Math.floor( (records-1) / len) * len;
3349                 }
3350                 else
3351                 {
3352                         _fnLog( settings, 0, "Unknown paging action: "+action, 5 );
3353                 }
3354         
3355                 var changed = settings._iDisplayStart !== start;
3356                 settings._iDisplayStart = start;
3357         
3358                 if ( changed ) {
3359                         _fnCallbackFire( settings, null, 'page', [settings] );
3360         
3361                         if ( redraw ) {
3362                                 _fnDraw( settings );
3363                         }
3364                 }
3365         
3366                 return changed;
3367         }
3368         
3369         
3370         
3371         /**
3372          * Generate the node required for the processing node
3373          *  @param {object} settings dataTables settings object
3374          *  @returns {node} Processing element
3375          *  @memberof DataTable#oApi
3376          */
3377         function _fnFeatureHtmlProcessing ( settings )
3378         {
3379                 return $('<div/>', {
3380                                 'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
3381                                 'class': settings.oClasses.sProcessing
3382                         } )
3383                         .html( settings.oLanguage.sProcessing )
3384                         .insertBefore( settings.nTable )[0];
3385         }
3386         
3387         
3388         /**
3389          * Display or hide the processing indicator
3390          *  @param {object} settings dataTables settings object
3391          *  @param {bool} show Show the processing indicator (true) or not (false)
3392          *  @memberof DataTable#oApi
3393          */
3394         function _fnProcessingDisplay ( settings, show )
3395         {
3396                 if ( settings.oFeatures.bProcessing ) {
3397                         $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
3398                 }
3399         
3400                 _fnCallbackFire( settings, null, 'processing', [settings, show] );
3401         }
3402         
3403         /**
3404          * Add any control elements for the table - specifically scrolling
3405          *  @param {object} settings dataTables settings object
3406          *  @returns {node} Node to add to the DOM
3407          *  @memberof DataTable#oApi
3408          */
3409         function _fnFeatureHtmlTable ( settings )
3410         {
3411                 var table = $(settings.nTable);
3412         
3413                 // Add the ARIA grid role to the table
3414                 table.attr( 'role', 'grid' );
3415         
3416                 // Scrolling from here on in
3417                 var scroll = settings.oScroll;
3418         
3419                 if ( scroll.sX === '' && scroll.sY === '' ) {
3420                         return settings.nTable;
3421                 }
3422         
3423                 var scrollX = scroll.sX;
3424                 var scrollY = scroll.sY;
3425                 var classes = settings.oClasses;
3426                 var caption = table.children('caption');
3427                 var captionSide = caption.length ? caption[0]._captionSide : null;
3428                 var headerClone = $( table[0].cloneNode(false) );
3429                 var footerClone = $( table[0].cloneNode(false) );
3430                 var footer = table.children('tfoot');
3431                 var _div = '<div/>';
3432                 var size = function ( s ) {
3433                         return !s ? null : _fnStringToCss( s );
3434                 };
3435         
3436                 // This is fairly messy, but with x scrolling enabled, if the table has a
3437                 // width attribute, regardless of any width applied using the column width
3438                 // options, the browser will shrink or grow the table as needed to fit into
3439                 // that 100%. That would make the width options useless. So we remove it.
3440                 // This is okay, under the assumption that width:100% is applied to the
3441                 // table in CSS (it is in the default stylesheet) which will set the table
3442                 // width as appropriate (the attribute and css behave differently...)
3443                 if ( scroll.sX && table.attr('width') === '100%' ) {
3444                         table.removeAttr('width');
3445                 }
3446         
3447                 if ( ! footer.length ) {
3448                         footer = null;
3449                 }
3450         
3451                 /*
3452                  * The HTML structure that we want to generate in this function is:
3453                  *  div - scroller
3454                  *    div - scroll head
3455                  *      div - scroll head inner
3456                  *        table - scroll head table
3457                  *          thead - thead
3458                  *    div - scroll body
3459                  *      table - table (master table)
3460                  *        thead - thead clone for sizing
3461                  *        tbody - tbody
3462                  *    div - scroll foot
3463                  *      div - scroll foot inner
3464                  *        table - scroll foot table
3465                  *          tfoot - tfoot
3466                  */
3467                 var scroller = $( _div, { 'class': classes.sScrollWrapper } )
3468                         .append(
3469                                 $(_div, { 'class': classes.sScrollHead } )
3470                                         .css( {
3471                                                 overflow: 'hidden',
3472                                                 position: 'relative',
3473                                                 border: 0,
3474                                                 width: scrollX ? size(scrollX) : '100%'
3475                                         } )
3476                                         .append(
3477                                                 $(_div, { 'class': classes.sScrollHeadInner } )
3478                                                         .css( {
3479                                                                 'box-sizing': 'content-box',
3480                                                                 width: scroll.sXInner || '100%'
3481                                                         } )
3482                                                         .append(
3483                                                                 headerClone
3484                                                                         .removeAttr('id')
3485                                                                         .css( 'margin-left', 0 )
3486                                                                         .append(
3487                                                                                 table.children('thead')
3488                                                                         )
3489                                                         )
3490                                         )
3491                                         .append( captionSide === 'top' ? caption : null )
3492                         )
3493                         .append(
3494                                 $(_div, { 'class': classes.sScrollBody } )
3495                                         .css( {
3496                                                 overflow: 'auto',
3497                                                 height: size( scrollY ),
3498                                                 width: size( scrollX )
3499                                         } )
3500                                         .append( table )
3501                         );
3502         
3503                 if ( footer ) {
3504                         scroller.append(
3505                                 $(_div, { 'class': classes.sScrollFoot } )
3506                                         .css( {
3507                                                 overflow: 'hidden',
3508                                                 border: 0,
3509                                                 width: scrollX ? size(scrollX) : '100%'
3510                                         } )
3511                                         .append(
3512                                                 $(_div, { 'class': classes.sScrollFootInner } )
3513                                                         .append(
3514                                                                 footerClone
3515                                                                         .removeAttr('id')
3516                                                                         .css( 'margin-left', 0 )
3517                                                                         .append(
3518                                                                                 table.children('tfoot')
3519                                                                         )
3520                                                         )
3521                                         )
3522                                         .append( captionSide === 'bottom' ? caption : null )
3523                         );
3524                 }
3525         
3526                 var children = scroller.children();
3527                 var scrollHead = children[0];
3528                 var scrollBody = children[1];
3529                 var scrollFoot = footer ? children[2] : null;
3530         
3531                 // When the body is scrolled, then we also want to scroll the headers
3532                 if ( scrollX ) {
3533                         $(scrollBody).scroll( function (e) {
3534                                 var scrollLeft = this.scrollLeft;
3535         
3536                                 scrollHead.scrollLeft = scrollLeft;
3537         
3538                                 if ( footer ) {
3539                                         scrollFoot.scrollLeft = scrollLeft;
3540                                 }
3541                         } );
3542                 }
3543         
3544                 settings.nScrollHead = scrollHead;
3545                 settings.nScrollBody = scrollBody;
3546                 settings.nScrollFoot = scrollFoot;
3547         
3548                 // On redraw - align columns
3549                 settings.aoDrawCallback.push( {
3550                         "fn": _fnScrollDraw,
3551                         "sName": "scrolling"
3552                 } );
3553         
3554                 return scroller[0];
3555         }
3556         
3557         
3558         
3559         /**
3560          * Update the header, footer and body tables for resizing - i.e. column
3561          * alignment.
3562          *
3563          * Welcome to the most horrible function DataTables. The process that this
3564          * function follows is basically:
3565          *   1. Re-create the table inside the scrolling div
3566          *   2. Take live measurements from the DOM
3567          *   3. Apply the measurements to align the columns
3568          *   4. Clean up
3569          *
3570          *  @param {object} settings dataTables settings object
3571          *  @memberof DataTable#oApi
3572          */
3573         function _fnScrollDraw ( settings )
3574         {
3575                 // Given that this is such a monster function, a lot of variables are use
3576                 // to try and keep the minimised size as small as possible
3577                 var
3578                         scroll         = settings.oScroll,
3579                         scrollX        = scroll.sX,
3580                         scrollXInner   = scroll.sXInner,
3581                         scrollY        = scroll.sY,
3582                         barWidth       = scroll.iBarWidth,
3583                         divHeader      = $(settings.nScrollHead),
3584                         divHeaderStyle = divHeader[0].style,
3585                         divHeaderInner = divHeader.children('div'),
3586                         divHeaderInnerStyle = divHeaderInner[0].style,
3587                         divHeaderTable = divHeaderInner.children('table'),
3588                         divBodyEl      = settings.nScrollBody,
3589                         divBody        = $(divBodyEl),
3590                         divBodyStyle   = divBodyEl.style,
3591                         divFooter      = $(settings.nScrollFoot),
3592                         divFooterInner = divFooter.children('div'),
3593                         divFooterTable = divFooterInner.children('table'),
3594                         header         = $(settings.nTHead),
3595                         table          = $(settings.nTable),
3596                         tableEl        = table[0],
3597                         tableStyle     = tableEl.style,
3598                         footer         = settings.nTFoot ? $(settings.nTFoot) : null,
3599                         browser        = settings.oBrowser,
3600                         ie67           = browser.bScrollOversize,
3601                         headerTrgEls, footerTrgEls,
3602                         headerSrcEls, footerSrcEls,
3603                         headerCopy, footerCopy,
3604                         headerWidths=[], footerWidths=[],
3605                         headerContent=[],
3606                         idx, correction, sanityWidth,
3607                         zeroOut = function(nSizer) {
3608                                 var style = nSizer.style;
3609                                 style.paddingTop = "0";
3610                                 style.paddingBottom = "0";
3611                                 style.borderTopWidth = "0";
3612                                 style.borderBottomWidth = "0";
3613                                 style.height = 0;
3614                         };
3615         
3616                 /*
3617                  * 1. Re-create the table inside the scrolling div
3618                  */
3619         
3620                 // Remove the old minimised thead and tfoot elements in the inner table
3621                 table.children('thead, tfoot').remove();
3622         
3623                 // Clone the current header and footer elements and then place it into the inner table
3624                 headerCopy = header.clone().prependTo( table );
3625                 headerTrgEls = header.find('tr'); // original header is in its own table
3626                 headerSrcEls = headerCopy.find('tr');
3627                 headerCopy.find('th, td').removeAttr('tabindex');
3628         
3629                 if ( footer ) {
3630                         footerCopy = footer.clone().prependTo( table );
3631                         footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
3632                         footerSrcEls = footerCopy.find('tr');
3633                 }
3634         
3635         
3636                 /*
3637                  * 2. Take live measurements from the DOM - do not alter the DOM itself!
3638                  */
3639         
3640                 // Remove old sizing and apply the calculated column widths
3641                 // Get the unique column headers in the newly created (cloned) header. We want to apply the
3642                 // calculated sizes to this header
3643                 if ( ! scrollX )
3644                 {
3645                         divBodyStyle.width = '100%';
3646                         divHeader[0].style.width = '100%';
3647                 }
3648         
3649                 $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
3650                         idx = _fnVisibleToColumnIndex( settings, i );
3651                         el.style.width = settings.aoColumns[idx].sWidth;
3652                 } );
3653         
3654                 if ( footer ) {
3655                         _fnApplyToChildren( function(n) {
3656                                 n.style.width = "";
3657                         }, footerSrcEls );
3658                 }
3659         
3660                 // If scroll collapse is enabled, when we put the headers back into the body for sizing, we
3661                 // will end up forcing the scrollbar to appear, making our measurements wrong for when we
3662                 // then hide it (end of this function), so add the header height to the body scroller.
3663                 if ( scroll.bCollapse && scrollY !== "" ) {
3664                         divBodyStyle.height = (divBody[0].offsetHeight + header[0].offsetHeight)+"px";
3665                 }
3666         
3667                 // Size the table as a whole
3668                 sanityWidth = table.outerWidth();
3669                 if ( scrollX === "" ) {
3670                         // No x scrolling
3671                         tableStyle.width = "100%";
3672         
3673                         // IE7 will make the width of the table when 100% include the scrollbar
3674                         // - which is shouldn't. When there is a scrollbar we need to take this
3675                         // into account.
3676                         if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
3677                                 divBody.css('overflow-y') == "scroll")
3678                         ) {
3679                                 tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
3680                         }
3681                 }
3682                 else
3683                 {
3684                         // x scrolling
3685                         if ( scrollXInner !== "" ) {
3686                                 // x scroll inner has been given - use it
3687                                 tableStyle.width = _fnStringToCss(scrollXInner);
3688                         }
3689                         else if ( sanityWidth == divBody.width() && divBody.height() < table.height() ) {
3690                                 // There is y-scrolling - try to take account of the y scroll bar
3691                                 tableStyle.width = _fnStringToCss( sanityWidth-barWidth );
3692                                 if ( table.outerWidth() > sanityWidth-barWidth ) {
3693                                         // Not possible to take account of it
3694                                         tableStyle.width = _fnStringToCss( sanityWidth );
3695                                 }
3696                         }
3697                         else {
3698                                 // When all else fails
3699                                 tableStyle.width = _fnStringToCss( sanityWidth );
3700                         }
3701                 }
3702         
3703                 // Recalculate the sanity width - now that we've applied the required width,
3704                 // before it was a temporary variable. This is required because the column
3705                 // width calculation is done before this table DOM is created.
3706                 sanityWidth = table.outerWidth();
3707         
3708                 // Hidden header should have zero height, so remove padding and borders. Then
3709                 // set the width based on the real headers
3710         
3711                 // Apply all styles in one pass
3712                 _fnApplyToChildren( zeroOut, headerSrcEls );
3713         
3714                 // Read all widths in next pass
3715                 _fnApplyToChildren( function(nSizer) {
3716                         headerContent.push( nSizer.innerHTML );
3717                         headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
3718                 }, headerSrcEls );
3719         
3720                 // Apply all widths in final pass
3721                 _fnApplyToChildren( function(nToSize, i) {
3722                         nToSize.style.width = headerWidths[i];
3723                 }, headerTrgEls );
3724         
3725                 $(headerSrcEls).height(0);
3726         
3727                 /* Same again with the footer if we have one */
3728                 if ( footer )
3729                 {
3730                         _fnApplyToChildren( zeroOut, footerSrcEls );
3731         
3732                         _fnApplyToChildren( function(nSizer) {
3733                                 footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
3734                         }, footerSrcEls );
3735         
3736                         _fnApplyToChildren( function(nToSize, i) {
3737                                 nToSize.style.width = footerWidths[i];
3738                         }, footerTrgEls );
3739         
3740                         $(footerSrcEls).height(0);
3741                 }
3742         
3743         
3744                 /*
3745                  * 3. Apply the measurements
3746                  */
3747         
3748                 // "Hide" the header and footer that we used for the sizing. We need to keep
3749                 // the content of the cell so that the width applied to the header and body
3750                 // both match, but we want to hide it completely. We want to also fix their
3751                 // width to what they currently are
3752                 _fnApplyToChildren( function(nSizer, i) {
3753                         nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
3754                         nSizer.style.width = headerWidths[i];
3755                 }, headerSrcEls );
3756         
3757                 if ( footer )
3758                 {
3759                         _fnApplyToChildren( function(nSizer, i) {
3760                                 nSizer.innerHTML = "";
3761                                 nSizer.style.width = footerWidths[i];
3762                         }, footerSrcEls );
3763                 }
3764         
3765                 // Sanity check that the table is of a sensible width. If not then we are going to get
3766                 // misalignment - try to prevent this by not allowing the table to shrink below its min width
3767                 if ( table.outerWidth() < sanityWidth )
3768                 {
3769                         // The min width depends upon if we have a vertical scrollbar visible or not */
3770                         correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
3771                                 divBody.css('overflow-y') == "scroll")) ?
3772                                         sanityWidth+barWidth :
3773                                         sanityWidth;
3774         
3775                         // IE6/7 are a law unto themselves...
3776                         if ( ie67 && (divBodyEl.scrollHeight >
3777                                 divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
3778                         ) {
3779                                 tableStyle.width = _fnStringToCss( correction-barWidth );
3780                         }
3781         
3782                         // And give the user a warning that we've stopped the table getting too small
3783                         if ( scrollX === "" || scrollXInner !== "" ) {
3784                                 _fnLog( settings, 1, 'Possible column misalignment', 6 );
3785                         }
3786                 }
3787                 else
3788                 {
3789                         correction = '100%';
3790                 }
3791         
3792                 // Apply to the container elements
3793                 divBodyStyle.width = _fnStringToCss( correction );
3794                 divHeaderStyle.width = _fnStringToCss( correction );
3795         
3796                 if ( footer ) {
3797                         settings.nScrollFoot.style.width = _fnStringToCss( correction );
3798                 }
3799         
3800         
3801                 /*
3802                  * 4. Clean up
3803                  */
3804                 if ( ! scrollY ) {
3805                         /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
3806                          * the scrollbar height from the visible display, rather than adding it on. We need to
3807                          * set the height in order to sort this. Don't want to do it in any other browsers.
3808                          */
3809                         if ( ie67 ) {
3810                                 divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
3811                         }
3812                 }
3813         
3814                 if ( scrollY && scroll.bCollapse ) {
3815                         divBodyStyle.height = _fnStringToCss( scrollY );
3816         
3817                         var iExtra = (scrollX && tableEl.offsetWidth > divBodyEl.offsetWidth) ?
3818                                 barWidth :
3819                                 0;
3820         
3821                         if ( tableEl.offsetHeight < divBodyEl.offsetHeight ) {
3822                                 divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+iExtra );
3823                         }
3824                 }
3825         
3826                 /* Finally set the width's of the header and footer tables */
3827                 var iOuterWidth = table.outerWidth();
3828                 divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
3829                 divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
3830         
3831                 // Figure out if there are scrollbar present - if so then we need a the header and footer to
3832                 // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
3833                 var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
3834                 var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
3835                 divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
3836         
3837                 if ( footer ) {
3838                         divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
3839                         divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
3840                         divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
3841                 }
3842         
3843                 /* Adjust the position of the header in case we loose the y-scrollbar */
3844                 divBody.scroll();
3845         
3846                 /* If sorting or filtering has occurred, jump the scrolling back to the top */
3847                 if ( settings.bSorted || settings.bFiltered ) {
3848                         divBodyEl.scrollTop = 0;
3849                 }
3850         }
3851         
3852         
3853         
3854         /**
3855          * Apply a given function to the display child nodes of an element array (typically
3856          * TD children of TR rows
3857          *  @param {function} fn Method to apply to the objects
3858          *  @param array {nodes} an1 List of elements to look through for display children
3859          *  @param array {nodes} an2 Another list (identical structure to the first) - optional
3860          *  @memberof DataTable#oApi
3861          */
3862         function _fnApplyToChildren( fn, an1, an2 )
3863         {
3864                 var index=0, i=0, iLen=an1.length;
3865                 var nNode1, nNode2;
3866         
3867                 while ( i < iLen ) {
3868                         nNode1 = an1[i].firstChild;
3869                         nNode2 = an2 ? an2[i].firstChild : null;
3870         
3871                         while ( nNode1 ) {
3872                                 if ( nNode1.nodeType === 1 ) {
3873                                         if ( an2 ) {
3874                                                 fn( nNode1, nNode2, index );
3875                                         }
3876                                         else {
3877                                                 fn( nNode1, index );
3878                                         }
3879         
3880                                         index++;
3881                                 }
3882         
3883                                 nNode1 = nNode1.nextSibling;
3884                                 nNode2 = an2 ? nNode2.nextSibling : null;
3885                         }
3886         
3887                         i++;
3888                 }
3889         }
3890         
3891         
3892         
3893         var __re_html_remove = /<.*?>/g;
3894         
3895         
3896         /**
3897          * Calculate the width of columns for the table
3898          *  @param {object} oSettings dataTables settings object
3899          *  @memberof DataTable#oApi
3900          */
3901         function _fnCalculateColumnWidths ( oSettings )
3902         {
3903                 var
3904                         table = oSettings.nTable,
3905                         columns = oSettings.aoColumns,
3906                         scroll = oSettings.oScroll,
3907                         scrollY = scroll.sY,
3908                         scrollX = scroll.sX,
3909                         scrollXInner = scroll.sXInner,
3910                         columnCount = columns.length,
3911                         visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
3912                         headerCells = $('th', oSettings.nTHead),
3913                         tableWidthAttr = table.getAttribute('width'),
3914                         tableContainer = table.parentNode,
3915                         userInputs = false,
3916                         i, column, columnIdx, width, outerWidth;
3917         
3918                 /* Convert any user input sizes into pixel sizes */
3919                 for ( i=0 ; i<visibleColumns.length ; i++ ) {
3920                         column = columns[ visibleColumns[i] ];
3921         
3922                         if ( column.sWidth !== null ) {
3923                                 column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
3924         
3925                                 userInputs = true;
3926                         }
3927                 }
3928         
3929                 /* If the number of columns in the DOM equals the number that we have to
3930                  * process in DataTables, then we can use the offsets that are created by
3931                  * the web- browser. No custom sizes can be set in order for this to happen,
3932                  * nor scrolling used
3933                  */
3934                 if ( ! userInputs && ! scrollX && ! scrollY &&
3935                     columnCount == _fnVisbleColumns( oSettings ) &&
3936                         columnCount == headerCells.length
3937                 ) {
3938                         for ( i=0 ; i<columnCount ; i++ ) {
3939                                 columns[i].sWidth = _fnStringToCss( headerCells.eq(i).width() );
3940                         }
3941                 }
3942                 else
3943                 {
3944                         // Otherwise construct a single row table with the widest node in the
3945                         // data, assign any user defined widths, then insert it into the DOM and
3946                         // allow the browser to do all the hard work of calculating table widths
3947                         var tmpTable = $( table.cloneNode( false ) )
3948                                 .css( 'visibility', 'hidden' )
3949                                 .removeAttr( 'id' )
3950                                 .append( $(oSettings.nTHead).clone( false ) )
3951                                 .append( $(oSettings.nTFoot).clone( false ) )
3952                                 .append( $('<tbody><tr/></tbody>') );
3953         
3954                         // Remove any assigned widths from the footer (from scrolling)
3955                         tmpTable.find('tfoot th, tfoot td').css('width', '');
3956         
3957                         var tr = tmpTable.find( 'tbody tr' );
3958         
3959                         // Apply custom sizing to the cloned header
3960                         headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
3961         
3962                         for ( i=0 ; i<visibleColumns.length ; i++ ) {
3963                                 column = columns[ visibleColumns[i] ];
3964         
3965                                 headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
3966                                         _fnStringToCss( column.sWidthOrig ) :
3967                                         '';
3968                         }
3969         
3970                         // Find the widest cell for each column and put it into the table
3971                         if ( oSettings.aoData.length ) {
3972                                 for ( i=0 ; i<visibleColumns.length ; i++ ) {
3973                                         columnIdx = visibleColumns[i];
3974                                         column = columns[ columnIdx ];
3975         
3976                                         $( _fnGetWidestNode( oSettings, columnIdx ) )
3977                                                 .clone( false )
3978                                                 .append( column.sContentPadding )
3979                                                 .appendTo( tr );
3980                                 }
3981                         }
3982         
3983                         // Table has been built, attach to the document so we can work with it
3984                         tmpTable.appendTo( tableContainer );
3985         
3986                         // When scrolling (X or Y) we want to set the width of the table as 
3987                         // appropriate. However, when not scrolling leave the table width as it
3988                         // is. This results in slightly different, but I think correct behaviour
3989                         if ( scrollX && scrollXInner ) {
3990                                 tmpTable.width( scrollXInner );
3991                         }
3992                         else if ( scrollX ) {
3993                                 tmpTable.css( 'width', 'auto' );
3994         
3995                                 if ( tmpTable.width() < tableContainer.offsetWidth ) {
3996                                         tmpTable.width( tableContainer.offsetWidth );
3997                                 }
3998                         }
3999                         else if ( scrollY ) {
4000                                 tmpTable.width( tableContainer.offsetWidth );
4001                         }
4002                         else if ( tableWidthAttr ) {
4003                                 tmpTable.width( tableWidthAttr );
4004                         }
4005         
4006                         // Take into account the y scrollbar
4007                         _fnScrollingWidthAdjust( oSettings, tmpTable[0] );
4008         
4009                         // Browsers need a bit of a hand when a width is assigned to any columns
4010                         // when x-scrolling as they tend to collapse the table to the min-width,
4011                         // even if we sent the column widths. So we need to keep track of what
4012                         // the table width should be by summing the user given values, and the
4013                         // automatic values
4014                         if ( scrollX )
4015                         {
4016                                 var total = 0;
4017         
4018                                 for ( i=0 ; i<visibleColumns.length ; i++ ) {
4019                                         column = columns[ visibleColumns[i] ];
4020                                         outerWidth = $(headerCells[i]).outerWidth();
4021         
4022                                         total += column.sWidthOrig === null ?
4023                                                 outerWidth :
4024                                                 parseInt( column.sWidth, 10 ) + outerWidth - $(headerCells[i]).width();
4025                                 }
4026         
4027                                 tmpTable.width( _fnStringToCss( total ) );
4028                                 table.style.width = _fnStringToCss( total );
4029                         }
4030         
4031                         // Get the width of each column in the constructed table
4032                         for ( i=0 ; i<visibleColumns.length ; i++ ) {
4033                                 column = columns[ visibleColumns[i] ];
4034                                 width = $(headerCells[i]).width();
4035         
4036                                 if ( width ) {
4037                                         column.sWidth = _fnStringToCss( width );
4038                                 }
4039                         }
4040         
4041                         table.style.width = _fnStringToCss( tmpTable.css('width') );
4042         
4043                         // Finished with the table - ditch it
4044                         tmpTable.remove();
4045                 }
4046         
4047                 // If there is a width attr, we want to attach an event listener which
4048                 // allows the table sizing to automatically adjust when the window is
4049                 // resized. Use the width attr rather than CSS, since we can't know if the
4050                 // CSS is a relative value or absolute - DOM read is always px.
4051                 if ( tableWidthAttr ) {
4052                         table.style.width = _fnStringToCss( tableWidthAttr );
4053                 }
4054         
4055                 if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
4056                         $(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
4057                                 _fnAdjustColumnSizing( oSettings );
4058                         } ) );
4059         
4060                         oSettings._reszEvt = true;
4061                 }
4062         }
4063         
4064         
4065         /**
4066          * Throttle the calls to a function. Arguments and context are maintained for
4067          * the throttled function
4068          *  @param {function} fn Function to be called
4069          *  @param {int} [freq=200] call frequency in mS
4070          *  @returns {function} wrapped function
4071          *  @memberof DataTable#oApi
4072          */
4073         function _fnThrottle( fn, freq ) {
4074                 var
4075                         frequency = freq || 200,
4076                         last,
4077                         timer;
4078         
4079                 return function () {
4080                         var
4081                                 that = this,
4082                                 now  = +new Date(),
4083                                 args = arguments;
4084         
4085                         if ( last && now < last + frequency ) {
4086                                 clearTimeout( timer );
4087         
4088                                 timer = setTimeout( function () {
4089                                         last = undefined;
4090                                         fn.apply( that, args );
4091                                 }, frequency );
4092                         }
4093                         else if ( last ) {
4094                                 last = now;
4095                                 fn.apply( that, args );
4096                         }
4097                         else {
4098                                 last = now;
4099                         }
4100                 };
4101         }
4102         
4103         
4104         /**
4105          * Convert a CSS unit width to pixels (e.g. 2em)
4106          *  @param {string} width width to be converted
4107          *  @param {node} parent parent to get the with for (required for relative widths) - optional
4108          *  @returns {int} width in pixels
4109          *  @memberof DataTable#oApi
4110          */
4111         function _fnConvertToWidth ( width, parent )
4112         {
4113                 if ( ! width ) {
4114                         return 0;
4115                 }
4116         
4117                 var n = $('<div/>')
4118                         .css( 'width', _fnStringToCss( width ) )
4119                         .appendTo( parent || document.body );
4120         
4121                 var val = n[0].offsetWidth;
4122                 n.remove();
4123         
4124                 return val;
4125         }
4126         
4127         
4128         /**
4129          * Adjust a table's width to take account of vertical scroll bar
4130          *  @param {object} oSettings dataTables settings object
4131          *  @param {node} n table node
4132          *  @memberof DataTable#oApi
4133          */
4134         
4135         function _fnScrollingWidthAdjust ( settings, n )
4136         {
4137                 var scroll = settings.oScroll;
4138         
4139                 if ( scroll.sX || scroll.sY ) {
4140                         // When y-scrolling only, we want to remove the width of the scroll bar
4141                         // so the table + scroll bar will fit into the area available, otherwise
4142                         // we fix the table at its current size with no adjustment
4143                         var correction = ! scroll.sX ? scroll.iBarWidth : 0;
4144                         n.style.width = _fnStringToCss( $(n).outerWidth() - correction );
4145                 }
4146         }
4147         
4148         
4149         /**
4150          * Get the widest node
4151          *  @param {object} settings dataTables settings object
4152          *  @param {int} colIdx column of interest
4153          *  @returns {node} widest table node
4154          *  @memberof DataTable#oApi
4155          */
4156         function _fnGetWidestNode( settings, colIdx )
4157         {
4158                 var idx = _fnGetMaxLenString( settings, colIdx );
4159                 if ( idx < 0 ) {
4160                         return null;
4161                 }
4162         
4163                 var data = settings.aoData[ idx ];
4164                 return ! data.nTr ? // Might not have been created when deferred rendering
4165                         $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
4166                         data.anCells[ colIdx ];
4167         }
4168         
4169         
4170         /**
4171          * Get the maximum strlen for each data column
4172          *  @param {object} settings dataTables settings object
4173          *  @param {int} colIdx column of interest
4174          *  @returns {string} max string length for each column
4175          *  @memberof DataTable#oApi
4176          */
4177         function _fnGetMaxLenString( settings, colIdx )
4178         {
4179                 var s, max=-1, maxIdx = -1;
4180         
4181                 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4182                         s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
4183                         s = s.replace( __re_html_remove, '' );
4184         
4185                         if ( s.length > max ) {
4186                                 max = s.length;
4187                                 maxIdx = i;
4188                         }
4189                 }
4190         
4191                 return maxIdx;
4192         }
4193         
4194         
4195         /**
4196          * Append a CSS unit (only if required) to a string
4197          *  @param {string} value to css-ify
4198          *  @returns {string} value with css unit
4199          *  @memberof DataTable#oApi
4200          */
4201         function _fnStringToCss( s )
4202         {
4203                 if ( s === null ) {
4204                         return '0px';
4205                 }
4206         
4207                 if ( typeof s == 'number' ) {
4208                         return s < 0 ?
4209                                 '0px' :
4210                                 s+'px';
4211                 }
4212         
4213                 // Check it has a unit character already
4214                 return s.match(/\d$/) ?
4215                         s+'px' :
4216                         s;
4217         }
4218         
4219         
4220         /**
4221          * Get the width of a scroll bar in this browser being used
4222          *  @returns {int} width in pixels
4223          *  @memberof DataTable#oApi
4224          */
4225         function _fnScrollBarWidth ()
4226         {
4227                 // On first run a static variable is set, since this is only needed once.
4228                 // Subsequent runs will just use the previously calculated value
4229                 if ( ! DataTable.__scrollbarWidth ) {
4230                         var inner = $('<p/>').css( {
4231                                 width: '100%',
4232                                 height: 200,
4233                                 padding: 0
4234                         } )[0];
4235         
4236                         var outer = $('<div/>')
4237                                 .css( {
4238                                         position: 'absolute',
4239                                         top: 0,
4240                                         left: 0,
4241                                         width: 200,
4242                                         height: 150,
4243                                         padding: 0,
4244                                         overflow: 'hidden',
4245                                         visibility: 'hidden'
4246                                 } )
4247                                 .append( inner )
4248                                 .appendTo( 'body' );
4249         
4250                         var w1 = inner.offsetWidth;
4251                         outer.css( 'overflow', 'scroll' );
4252                         var w2 = inner.offsetWidth;
4253         
4254                         if ( w1 === w2 ) {
4255                                 w2 = outer[0].clientWidth;
4256                         }
4257         
4258                         outer.remove();
4259         
4260                         DataTable.__scrollbarWidth = w1 - w2;
4261                 }
4262         
4263                 return DataTable.__scrollbarWidth;
4264         }
4265         
4266         
4267         
4268         function _fnSortFlatten ( settings )
4269         {
4270                 var
4271                         i, iLen, k, kLen,
4272                         aSort = [],
4273                         aiOrig = [],
4274                         aoColumns = settings.aoColumns,
4275                         aDataSort, iCol, sType, srcCol,
4276                         fixed = settings.aaSortingFixed,
4277                         fixedObj = $.isPlainObject( fixed ),
4278                         nestedSort = [],
4279                         add = function ( a ) {
4280                                 if ( a.length && ! $.isArray( a[0] ) ) {
4281                                         // 1D array
4282                                         nestedSort.push( a );
4283                                 }
4284                                 else {
4285                                         // 2D array
4286                                         nestedSort.push.apply( nestedSort, a );
4287                                 }
4288                         };
4289         
4290                 // Build the sort array, with pre-fix and post-fix options if they have been
4291                 // specified
4292                 if ( $.isArray( fixed ) ) {
4293                         add( fixed );
4294                 }
4295         
4296                 if ( fixedObj && fixed.pre ) {
4297                         add( fixed.pre );
4298                 }
4299         
4300                 add( settings.aaSorting );
4301         
4302                 if (fixedObj && fixed.post ) {
4303                         add( fixed.post );
4304                 }
4305         
4306                 for ( i=0 ; i<nestedSort.length ; i++ )
4307                 {
4308                         srcCol = nestedSort[i][0];
4309                         aDataSort = aoColumns[ srcCol ].aDataSort;
4310         
4311                         for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
4312                         {
4313                                 iCol = aDataSort[k];
4314                                 sType = aoColumns[ iCol ].sType || 'string';
4315         
4316                                 aSort.push( {
4317                                         src:       srcCol,
4318                                         col:       iCol,
4319                                         dir:       nestedSort[i][1],
4320                                         index:     nestedSort[i][2],
4321                                         type:      sType,
4322                                         formatter: DataTable.ext.type.order[ sType+"-pre" ]
4323                                 } );
4324                         }
4325                 }
4326         
4327                 return aSort;
4328         }
4329         
4330         /**
4331          * Change the order of the table
4332          *  @param {object} oSettings dataTables settings object
4333          *  @memberof DataTable#oApi
4334          *  @todo This really needs split up!
4335          */
4336         function _fnSort ( oSettings )
4337         {
4338                 var
4339                         i, ien, iLen, j, jLen, k, kLen,
4340                         sDataType, nTh,
4341                         aiOrig = [],
4342                         oExtSort = DataTable.ext.type.order,
4343                         aoData = oSettings.aoData,
4344                         aoColumns = oSettings.aoColumns,
4345                         aDataSort, data, iCol, sType, oSort,
4346                         formatters = 0,
4347                         sortCol,
4348                         displayMaster = oSettings.aiDisplayMaster,
4349                         aSort;
4350         
4351                 // Resolve any column types that are unknown due to addition or invalidation
4352                 // @todo Can this be moved into a 'data-ready' handler which is called when
4353                 //   data is going to be used in the table?
4354                 _fnColumnTypes( oSettings );
4355         
4356                 aSort = _fnSortFlatten( oSettings );
4357         
4358                 for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
4359                         sortCol = aSort[i];
4360         
4361                         // Track if we can use the fast sort algorithm
4362                         if ( sortCol.formatter ) {
4363                                 formatters++;
4364                         }
4365         
4366                         // Load the data needed for the sort, for each cell
4367                         _fnSortData( oSettings, sortCol.col );
4368                 }
4369         
4370                 /* No sorting required if server-side or no sorting array */
4371                 if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
4372                 {
4373                         // Create a value - key array of the current row positions such that we can use their
4374                         // current position during the sort, if values match, in order to perform stable sorting
4375                         for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
4376                                 aiOrig[ displayMaster[i] ] = i;
4377                         }
4378         
4379                         /* Do the sort - here we want multi-column sorting based on a given data source (column)
4380                          * and sorting function (from oSort) in a certain direction. It's reasonably complex to
4381                          * follow on it's own, but this is what we want (example two column sorting):
4382                          *  fnLocalSorting = function(a,b){
4383                          *    var iTest;
4384                          *    iTest = oSort['string-asc']('data11', 'data12');
4385                          *      if (iTest !== 0)
4386                          *        return iTest;
4387                          *    iTest = oSort['numeric-desc']('data21', 'data22');
4388                          *    if (iTest !== 0)
4389                          *      return iTest;
4390                          *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
4391                          *  }
4392                          * Basically we have a test for each sorting column, if the data in that column is equal,
4393                          * test the next column. If all columns match, then we use a numeric sort on the row
4394                          * positions in the original data array to provide a stable sort.
4395                          *
4396                          * Note - I know it seems excessive to have two sorting methods, but the first is around
4397                          * 15% faster, so the second is only maintained for backwards compatibility with sorting
4398                          * methods which do not have a pre-sort formatting function.
4399                          */
4400                         if ( formatters === aSort.length ) {
4401                                 // All sort types have formatting functions
4402                                 displayMaster.sort( function ( a, b ) {
4403                                         var
4404                                                 x, y, k, test, sort,
4405                                                 len=aSort.length,
4406                                                 dataA = aoData[a]._aSortData,
4407                                                 dataB = aoData[b]._aSortData;
4408         
4409                                         for ( k=0 ; k<len ; k++ ) {
4410                                                 sort = aSort[k];
4411         
4412                                                 x = dataA[ sort.col ];
4413                                                 y = dataB[ sort.col ];
4414         
4415                                                 test = x<y ? -1 : x>y ? 1 : 0;
4416                                                 if ( test !== 0 ) {
4417                                                         return sort.dir === 'asc' ? test : -test;
4418                                                 }
4419                                         }
4420         
4421                                         x = aiOrig[a];
4422                                         y = aiOrig[b];
4423                                         return x<y ? -1 : x>y ? 1 : 0;
4424                                 } );
4425                         }
4426                         else {
4427                                 // Depreciated - remove in 1.11 (providing a plug-in option)
4428                                 // Not all sort types have formatting methods, so we have to call their sorting
4429                                 // methods.
4430                                 displayMaster.sort( function ( a, b ) {
4431                                         var
4432                                                 x, y, k, l, test, sort, fn,
4433                                                 len=aSort.length,
4434                                                 dataA = aoData[a]._aSortData,
4435                                                 dataB = aoData[b]._aSortData;
4436         
4437                                         for ( k=0 ; k<len ; k++ ) {
4438                                                 sort = aSort[k];
4439         
4440                                                 x = dataA[ sort.col ];
4441                                                 y = dataB[ sort.col ];
4442         
4443                                                 fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
4444                                                 test = fn( x, y );
4445                                                 if ( test !== 0 ) {
4446                                                         return test;
4447                                                 }
4448                                         }
4449         
4450                                         x = aiOrig[a];
4451                                         y = aiOrig[b];
4452                                         return x<y ? -1 : x>y ? 1 : 0;
4453                                 } );
4454                         }
4455                 }
4456         
4457                 /* Tell the draw function that we have sorted the data */
4458                 oSettings.bSorted = true;
4459         }
4460         
4461         
4462         function _fnSortAria ( settings )
4463         {
4464                 var label;
4465                 var nextSort;
4466                 var columns = settings.aoColumns;
4467                 var aSort = _fnSortFlatten( settings );
4468                 var oAria = settings.oLanguage.oAria;
4469         
4470                 // ARIA attributes - need to loop all columns, to update all (removing old
4471                 // attributes as needed)
4472                 for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
4473                 {
4474                         var col = columns[i];
4475                         var asSorting = col.asSorting;
4476                         var sTitle = col.sTitle.replace( /<.*?>/g, "" );
4477                         var th = col.nTh;
4478         
4479                         // IE7 is throwing an error when setting these properties with jQuery's
4480                         // attr() and removeAttr() methods...
4481                         th.removeAttribute('aria-sort');
4482         
4483                         /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
4484                         if ( col.bSortable ) {
4485                                 if ( aSort.length > 0 && aSort[0].col == i ) {
4486                                         th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
4487                                         nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
4488                                 }
4489                                 else {
4490                                         nextSort = asSorting[0];
4491                                 }
4492         
4493                                 label = sTitle + ( nextSort === "asc" ?
4494                                         oAria.sSortAscending :
4495                                         oAria.sSortDescending
4496                                 );
4497                         }
4498                         else {
4499                                 label = sTitle;
4500                         }
4501         
4502                         th.setAttribute('aria-label', label);
4503                 }
4504         }
4505         
4506         
4507         /**
4508          * Function to run on user sort request
4509          *  @param {object} settings dataTables settings object
4510          *  @param {node} attachTo node to attach the handler to
4511          *  @param {int} colIdx column sorting index
4512          *  @param {boolean} [append=false] Append the requested sort to the existing
4513          *    sort if true (i.e. multi-column sort)
4514          *  @param {function} [callback] callback function
4515          *  @memberof DataTable#oApi
4516          */
4517         function _fnSortListener ( settings, colIdx, append, callback )
4518         {
4519                 var col = settings.aoColumns[ colIdx ];
4520                 var sorting = settings.aaSorting;
4521                 var asSorting = col.asSorting;
4522                 var nextSortIdx;
4523                 var next = function ( a ) {
4524                         var idx = a._idx;
4525                         if ( idx === undefined ) {
4526                                 idx = $.inArray( a[1], asSorting );
4527                         }
4528         
4529                         return idx+1 >= asSorting.length ? 0 : idx+1;
4530                 };
4531         
4532                 // If appending the sort then we are multi-column sorting
4533                 if ( append && settings.oFeatures.bSortMulti ) {
4534                         // Are we already doing some kind of sort on this column?
4535                         var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
4536         
4537                         if ( sortIdx !== -1 ) {
4538                                 // Yes, modify the sort
4539                                 nextSortIdx = next( sorting[sortIdx] );
4540         
4541                                 sorting[sortIdx][1] = asSorting[ nextSortIdx ];
4542                                 sorting[sortIdx]._idx = nextSortIdx;
4543                         }
4544                         else {
4545                                 // No sort on this column yet
4546                                 sorting.push( [ colIdx, asSorting[0], 0 ] );
4547                                 sorting[sorting.length-1]._idx = 0;
4548                         }
4549                 }
4550                 else if ( sorting.length && sorting[0][0] == colIdx ) {
4551                         // Single column - already sorting on this column, modify the sort
4552                         nextSortIdx = next( sorting[0] );
4553         
4554                         sorting.length = 1;
4555                         sorting[0][1] = asSorting[ nextSortIdx ];
4556                         sorting[0]._idx = nextSortIdx;
4557                 }
4558                 else {
4559                         // Single column - sort only on this column
4560                         sorting.length = 0;
4561                         sorting.push( [ colIdx, asSorting[0] ] );
4562                         sorting[0]._idx = 0;
4563                 }
4564         
4565                 // Run the sort by calling a full redraw
4566                 _fnReDraw( settings );
4567         
4568                 // callback used for async user interaction
4569                 if ( typeof callback == 'function' ) {
4570                         callback( settings );
4571                 }
4572         }
4573         
4574         
4575         /**
4576          * Attach a sort handler (click) to a node
4577          *  @param {object} settings dataTables settings object
4578          *  @param {node} attachTo node to attach the handler to
4579          *  @param {int} colIdx column sorting index
4580          *  @param {function} [callback] callback function
4581          *  @memberof DataTable#oApi
4582          */
4583         function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
4584         {
4585                 var col = settings.aoColumns[ colIdx ];
4586         
4587                 _fnBindAction( attachTo, {}, function (e) {
4588                         /* If the column is not sortable - don't to anything */
4589                         if ( col.bSortable === false ) {
4590                                 return;
4591                         }
4592         
4593                         // If processing is enabled use a timeout to allow the processing
4594                         // display to be shown - otherwise to it synchronously
4595                         if ( settings.oFeatures.bProcessing ) {
4596                                 _fnProcessingDisplay( settings, true );
4597         
4598                                 setTimeout( function() {
4599                                         _fnSortListener( settings, colIdx, e.shiftKey, callback );
4600         
4601                                         // In server-side processing, the draw callback will remove the
4602                                         // processing display
4603                                         if ( _fnDataSource( settings ) !== 'ssp' ) {
4604                                                 _fnProcessingDisplay( settings, false );
4605                                         }
4606                                 }, 0 );
4607                         }
4608                         else {
4609                                 _fnSortListener( settings, colIdx, e.shiftKey, callback );
4610                         }
4611                 } );
4612         }
4613         
4614         
4615         /**
4616          * Set the sorting classes on table's body, Note: it is safe to call this function
4617          * when bSort and bSortClasses are false
4618          *  @param {object} oSettings dataTables settings object
4619          *  @memberof DataTable#oApi
4620          */
4621         function _fnSortingClasses( settings )
4622         {
4623                 var oldSort = settings.aLastSort;
4624                 var sortClass = settings.oClasses.sSortColumn;
4625                 var sort = _fnSortFlatten( settings );
4626                 var features = settings.oFeatures;
4627                 var i, ien, colIdx;
4628         
4629                 if ( features.bSort && features.bSortClasses ) {
4630                         // Remove old sorting classes
4631                         for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
4632                                 colIdx = oldSort[i].src;
4633         
4634                                 // Remove column sorting
4635                                 $( _pluck( settings.aoData, 'anCells', colIdx ) )
4636                                         .removeClass( sortClass + (i<2 ? i+1 : 3) );
4637                         }
4638         
4639                         // Add new column sorting
4640                         for ( i=0, ien=sort.length ; i<ien ; i++ ) {
4641                                 colIdx = sort[i].src;
4642         
4643                                 $( _pluck( settings.aoData, 'anCells', colIdx ) )
4644                                         .addClass( sortClass + (i<2 ? i+1 : 3) );
4645                         }
4646                 }
4647         
4648                 settings.aLastSort = sort;
4649         }
4650         
4651         
4652         // Get the data to sort a column, be it from cache, fresh (populating the
4653         // cache), or from a sort formatter
4654         function _fnSortData( settings, idx )
4655         {
4656                 // Custom sorting function - provided by the sort data type
4657                 var column = settings.aoColumns[ idx ];
4658                 var customSort = DataTable.ext.order[ column.sSortDataType ];
4659                 var customData;
4660         
4661                 if ( customSort ) {
4662                         customData = customSort.call( settings.oInstance, settings, idx,
4663                                 _fnColumnIndexToVisible( settings, idx )
4664                         );
4665                 }
4666         
4667                 // Use / populate cache
4668                 var row, cellData;
4669                 var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
4670         
4671                 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4672                         row = settings.aoData[i];
4673         
4674                         if ( ! row._aSortData ) {
4675                                 row._aSortData = [];
4676                         }
4677         
4678                         if ( ! row._aSortData[idx] || customSort ) {
4679                                 cellData = customSort ?
4680                                         customData[i] : // If there was a custom sort function, use data from there
4681                                         _fnGetCellData( settings, i, idx, 'sort' );
4682         
4683                                 row._aSortData[ idx ] = formatter ?
4684                                         formatter( cellData ) :
4685                                         cellData;
4686                         }
4687                 }
4688         }
4689         
4690         
4691         
4692         /**
4693          * Save the state of a table
4694          *  @param {object} oSettings dataTables settings object
4695          *  @memberof DataTable#oApi
4696          */
4697         function _fnSaveState ( oSettings )
4698         {
4699                 if ( !oSettings.oFeatures.bStateSave || oSettings.bDestroying )
4700                 {
4701                         return;
4702                 }
4703         
4704                 /* Store the interesting variables */
4705                 var i, iLen;
4706                 var oState = {
4707                         "iCreate":      +new Date(),
4708                         "iStart":       oSettings._iDisplayStart,
4709                         "iLength":      oSettings._iDisplayLength,
4710                         "aaSorting":    $.extend( true, [], oSettings.aaSorting ),
4711                         "oSearch":      $.extend( true, {}, oSettings.oPreviousSearch ),
4712                         "aoSearchCols": $.extend( true, [], oSettings.aoPreSearchCols ),
4713                         "abVisCols":    _pluck( oSettings.aoColumns, 'bVisible' )
4714                 };
4715         
4716                 _fnCallbackFire( oSettings, "aoStateSaveParams", 'stateSaveParams', [oSettings, oState] );
4717         
4718                 oSettings.fnStateSaveCallback.call( oSettings.oInstance, oSettings, oState );
4719         }
4720         
4721         
4722         /**
4723          * Attempt to load a saved table state
4724          *  @param {object} oSettings dataTables settings object
4725          *  @param {object} oInit DataTables init object so we can override settings
4726          *  @memberof DataTable#oApi
4727          */
4728         function _fnLoadState ( oSettings, oInit )
4729         {
4730                 var i, ien;
4731                 var columns = oSettings.aoColumns;
4732         
4733                 if ( ! oSettings.oFeatures.bStateSave ) {
4734                         return;
4735                 }
4736         
4737                 var oData = oSettings.fnStateLoadCallback.call( oSettings.oInstance, oSettings );
4738                 if ( !oData ) {
4739                         return;
4740                 }
4741         
4742                 /* Allow custom and plug-in manipulation functions to alter the saved data set and
4743                  * cancelling of loading by returning false
4744                  */
4745                 var abStateLoad = _fnCallbackFire( oSettings, 'aoStateLoadParams', 'stateLoadParams', [oSettings, oData] );
4746                 if ( $.inArray( false, abStateLoad ) !== -1 ) {
4747                         return;
4748                 }
4749         
4750                 /* Reject old data */
4751                 var duration = oSettings.iStateDuration;
4752                 if ( duration > 0 && oData.iCreate < +new Date() - (duration*1000) ) {
4753                         return;
4754                 }
4755         
4756                 // Number of columns have changed - all bets are off, no restore of settings
4757                 if ( columns.length !== oData.aoSearchCols.length ) {
4758                         return;
4759                 }
4760         
4761                 /* Store the saved state so it might be accessed at any time */
4762                 oSettings.oLoadedState = $.extend( true, {}, oData );
4763         
4764                 /* Restore key features */
4765                 oSettings._iDisplayStart    = oData.iStart;
4766                 oSettings.iInitDisplayStart = oData.iStart;
4767                 oSettings._iDisplayLength   = oData.iLength;
4768                 oSettings.aaSorting = $.map( oData.aaSorting, function ( col, i ) {
4769                         return col[0] >= columns.length ?
4770                                 [ 0, col[1] ] :
4771                                 col;
4772                 } );
4773         
4774                 /* Search filtering  */
4775                 $.extend( oSettings.oPreviousSearch, oData.oSearch );
4776                 $.extend( true, oSettings.aoPreSearchCols, oData.aoSearchCols );
4777         
4778                 /* Column visibility state */
4779                 var visColumns = oData.abVisCols;
4780                 for ( i=0, ien=visColumns.length ; i<ien ; i++ ) {
4781                         columns[i].bVisible = visColumns[i];
4782                 }
4783         
4784                 _fnCallbackFire( oSettings, 'aoStateLoaded', 'stateLoaded', [oSettings, oData] );
4785         }
4786         
4787         
4788         /**
4789          * Return the settings object for a particular table
4790          *  @param {node} table table we are using as a dataTable
4791          *  @returns {object} Settings object - or null if not found
4792          *  @memberof DataTable#oApi
4793          */
4794         function _fnSettingsFromNode ( table )
4795         {
4796                 var settings = DataTable.settings;
4797                 var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
4798         
4799                 return idx !== -1 ?
4800                         settings[ idx ] :
4801                         null;
4802         }
4803         
4804         
4805         /**
4806          * Log an error message
4807          *  @param {object} settings dataTables settings object
4808          *  @param {int} level log error messages, or display them to the user
4809          *  @param {string} msg error message
4810          *  @param {int} tn Technical note id to get more information about the error.
4811          *  @memberof DataTable#oApi
4812          */
4813         function _fnLog( settings, level, msg, tn )
4814         {
4815                 msg = 'DataTables warning: '+
4816                         (settings!==null ? 'table id='+settings.sTableId+' - ' : '')+msg;
4817         
4818                 if ( tn ) {
4819                         msg += '. For more information about this error, please see '+
4820                         'http://datatables.net/tn/'+tn;
4821                 }
4822         
4823                 if ( ! level  ) {
4824                         // Backwards compatibility pre 1.10
4825                         var ext = DataTable.ext;
4826                         var type = ext.sErrMode || ext.errMode;
4827         
4828                         if ( type == 'alert' ) {
4829                                 alert( msg );
4830                         }
4831                         else {
4832                                 throw new Error(msg);
4833                         }
4834                 }
4835                 else if ( window.console && console.log ) {
4836                         console.log( msg );
4837                 }
4838         }
4839         
4840         
4841         /**
4842          * See if a property is defined on one object, if so assign it to the other object
4843          *  @param {object} ret target object
4844          *  @param {object} src source object
4845          *  @param {string} name property
4846          *  @param {string} [mappedName] name to map too - optional, name used if not given
4847          *  @memberof DataTable#oApi
4848          */
4849         function _fnMap( ret, src, name, mappedName )
4850         {
4851                 if ( $.isArray( name ) ) {
4852                         $.each( name, function (i, val) {
4853                                 if ( $.isArray( val ) ) {
4854                                         _fnMap( ret, src, val[0], val[1] );
4855                                 }
4856                                 else {
4857                                         _fnMap( ret, src, val );
4858                                 }
4859                         } );
4860         
4861                         return;
4862                 }
4863         
4864                 if ( mappedName === undefined ) {
4865                         mappedName = name;
4866                 }
4867         
4868                 if ( src[name] !== undefined ) {
4869                         ret[mappedName] = src[name];
4870                 }
4871         }
4872         
4873         
4874         /**
4875          * Extend objects - very similar to jQuery.extend, but deep copy objects, and
4876          * shallow copy arrays. The reason we need to do this, is that we don't want to
4877          * deep copy array init values (such as aaSorting) since the dev wouldn't be
4878          * able to override them, but we do want to deep copy arrays.
4879          *  @param {object} out Object to extend
4880          *  @param {object} extender Object from which the properties will be applied to
4881          *      out
4882          *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
4883          *      independent copy with the exception of the `data` or `aaData` parameters
4884          *      if they are present. This is so you can pass in a collection to
4885          *      DataTables and have that used as your data source without breaking the
4886          *      references
4887          *  @returns {object} out Reference, just for convenience - out === the return.
4888          *  @memberof DataTable#oApi
4889          *  @todo This doesn't take account of arrays inside the deep copied objects.
4890          */
4891         function _fnExtend( out, extender, breakRefs )
4892         {
4893                 var val;
4894         
4895                 for ( var prop in extender ) {
4896                         if ( extender.hasOwnProperty(prop) ) {
4897                                 val = extender[prop];
4898         
4899                                 if ( $.isPlainObject( val ) ) {
4900                                         if ( ! $.isPlainObject( out[prop] ) ) {
4901                                                 out[prop] = {};
4902                                         }
4903                                         $.extend( true, out[prop], val );
4904                                 }
4905                                 else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
4906                                         out[prop] = val.slice();
4907                                 }
4908                                 else {
4909                                         out[prop] = val;
4910                                 }
4911                         }
4912                 }
4913         
4914                 return out;
4915         }
4916         
4917         
4918         /**
4919          * Bind an event handers to allow a click or return key to activate the callback.
4920          * This is good for accessibility since a return on the keyboard will have the
4921          * same effect as a click, if the element has focus.
4922          *  @param {element} n Element to bind the action to
4923          *  @param {object} oData Data object to pass to the triggered function
4924          *  @param {function} fn Callback function for when the event is triggered
4925          *  @memberof DataTable#oApi
4926          */
4927         function _fnBindAction( n, oData, fn )
4928         {
4929                 $(n)
4930                         .bind( 'click.DT', oData, function (e) {
4931                                         n.blur(); // Remove focus outline for mouse users
4932                                         fn(e);
4933                                 } )
4934                         .bind( 'keypress.DT', oData, function (e){
4935                                         if ( e.which === 13 ) {
4936                                                 e.preventDefault();
4937                                                 fn(e);
4938                                         }
4939                                 } )
4940                         .bind( 'selectstart.DT', function () {
4941                                         /* Take the brutal approach to cancelling text selection */
4942                                         return false;
4943                                 } );
4944         }
4945         
4946         
4947         /**
4948          * Register a callback function. Easily allows a callback function to be added to
4949          * an array store of callback functions that can then all be called together.
4950          *  @param {object} oSettings dataTables settings object
4951          *  @param {string} sStore Name of the array storage for the callbacks in oSettings
4952          *  @param {function} fn Function to be called back
4953          *  @param {string} sName Identifying name for the callback (i.e. a label)
4954          *  @memberof DataTable#oApi
4955          */
4956         function _fnCallbackReg( oSettings, sStore, fn, sName )
4957         {
4958                 if ( fn )
4959                 {
4960                         oSettings[sStore].push( {
4961                                 "fn": fn,
4962                                 "sName": sName
4963                         } );
4964                 }
4965         }
4966         
4967         
4968         /**
4969          * Fire callback functions and trigger events. Note that the loop over the
4970          * callback array store is done backwards! Further note that you do not want to
4971          * fire off triggers in time sensitive applications (for example cell creation)
4972          * as its slow.
4973          *  @param {object} settings dataTables settings object
4974          *  @param {string} callbackArr Name of the array storage for the callbacks in
4975          *      oSettings
4976          *  @param {string} event Name of the jQuery custom event to trigger. If null no
4977          *      trigger is fired
4978          *  @param {array} args Array of arguments to pass to the callback function /
4979          *      trigger
4980          *  @memberof DataTable#oApi
4981          */
4982         function _fnCallbackFire( settings, callbackArr, event, args )
4983         {
4984                 var ret = [];
4985         
4986                 if ( callbackArr ) {
4987                         ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
4988                                 return val.fn.apply( settings.oInstance, args );
4989                         } );
4990                 }
4991         
4992                 if ( event !== null ) {
4993                         $(settings.nTable).trigger( event+'.dt', args );
4994                 }
4995         
4996                 return ret;
4997         }
4998         
4999         
5000         function _fnLengthOverflow ( settings )
5001         {
5002                 var
5003                         start = settings._iDisplayStart,
5004                         end = settings.fnDisplayEnd(),
5005                         len = settings._iDisplayLength;
5006         
5007                 /* If we have space to show extra rows (backing up from the end point - then do so */
5008                 if ( end === settings.fnRecordsDisplay() )
5009                 {
5010                         start = end - len;
5011                 }
5012         
5013                 if ( len === -1 || start < 0 )
5014                 {
5015                         start = 0;
5016                 }
5017         
5018                 settings._iDisplayStart = start;
5019         }
5020         
5021         
5022         function _fnRenderer( settings, type )
5023         {
5024                 var renderer = settings.renderer;
5025                 var host = DataTable.ext.renderer[type];
5026         
5027                 if ( $.isPlainObject( renderer ) && renderer[type] ) {
5028                         // Specific renderer for this type. If available use it, otherwise use
5029                         // the default.
5030                         return host[renderer[type]] || host._;
5031                 }
5032                 else if ( typeof renderer === 'string' ) {
5033                         // Common renderer - if there is one available for this type use it,
5034                         // otherwise use the default
5035                         return host[renderer] || host._;
5036                 }
5037         
5038                 // Use the default
5039                 return host._;
5040         }
5041         
5042         
5043         /**
5044          * Detect the data source being used for the table. Used to simplify the code
5045          * a little (ajax) and to make it compress a little smaller.
5046          *
5047          *  @param {object} settings dataTables settings object
5048          *  @returns {string} Data source
5049          *  @memberof DataTable#oApi
5050          */
5051         function _fnDataSource ( settings )
5052         {
5053                 if ( settings.oFeatures.bServerSide ) {
5054                         return 'ssp';
5055                 }
5056                 else if ( settings.ajax || settings.sAjaxSource ) {
5057                         return 'ajax';
5058                 }
5059                 return 'dom';
5060         }
5061         
5062
5063         DataTable = function( options )
5064         {
5065                 /**
5066                  * Perform a jQuery selector action on the table's TR elements (from the tbody) and
5067                  * return the resulting jQuery object.
5068                  *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
5069                  *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
5070                  *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
5071                  *    criterion ("applied") or all TR elements (i.e. no filter).
5072                  *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
5073                  *    Can be either 'current', whereby the current sorting of the table is used, or
5074                  *    'original' whereby the original order the data was read into the table is used.
5075                  *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
5076                  *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
5077                  *    'current' and filter is 'applied', regardless of what they might be given as.
5078                  *  @returns {object} jQuery object, filtered by the given selector.
5079                  *  @dtopt API
5080                  *  @deprecated Since v1.10
5081                  *
5082                  *  @example
5083                  *    $(document).ready(function() {
5084                  *      var oTable = $('#example').dataTable();
5085                  *
5086                  *      // Highlight every second row
5087                  *      oTable.$('tr:odd').css('backgroundColor', 'blue');
5088                  *    } );
5089                  *
5090                  *  @example
5091                  *    $(document).ready(function() {
5092                  *      var oTable = $('#example').dataTable();
5093                  *
5094                  *      // Filter to rows with 'Webkit' in them, add a background colour and then
5095                  *      // remove the filter, thus highlighting the 'Webkit' rows only.
5096                  *      oTable.fnFilter('Webkit');
5097                  *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
5098                  *      oTable.fnFilter('');
5099                  *    } );
5100                  */
5101                 this.$ = function ( sSelector, oOpts )
5102                 {
5103                         return this.api(true).$( sSelector, oOpts );
5104                 };
5105                 
5106                 
5107                 /**
5108                  * Almost identical to $ in operation, but in this case returns the data for the matched
5109                  * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
5110                  * rather than any descendants, so the data can be obtained for the row/cell. If matching
5111                  * rows are found, the data returned is the original data array/object that was used to
5112                  * create the row (or a generated array if from a DOM source).
5113                  *
5114                  * This method is often useful in-combination with $ where both functions are given the
5115                  * same parameters and the array indexes will match identically.
5116                  *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
5117                  *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
5118                  *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
5119                  *    criterion ("applied") or all elements (i.e. no filter).
5120                  *  @param {string} [oOpts.order=current] Order of the data in the processed array.
5121                  *    Can be either 'current', whereby the current sorting of the table is used, or
5122                  *    'original' whereby the original order the data was read into the table is used.
5123                  *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
5124                  *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
5125                  *    'current' and filter is 'applied', regardless of what they might be given as.
5126                  *  @returns {array} Data for the matched elements. If any elements, as a result of the
5127                  *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
5128                  *    entry in the array.
5129                  *  @dtopt API
5130                  *  @deprecated Since v1.10
5131                  *
5132                  *  @example
5133                  *    $(document).ready(function() {
5134                  *      var oTable = $('#example').dataTable();
5135                  *
5136                  *      // Get the data from the first row in the table
5137                  *      var data = oTable._('tr:first');
5138                  *
5139                  *      // Do something useful with the data
5140                  *      alert( "First cell is: "+data[0] );
5141                  *    } );
5142                  *
5143                  *  @example
5144                  *    $(document).ready(function() {
5145                  *      var oTable = $('#example').dataTable();
5146                  *
5147                  *      // Filter to 'Webkit' and get all data for
5148                  *      oTable.fnFilter('Webkit');
5149                  *      var data = oTable._('tr', {"search": "applied"});
5150                  *
5151                  *      // Do something with the data
5152                  *      alert( data.length+" rows matched the search" );
5153                  *    } );
5154                  */
5155                 this._ = function ( sSelector, oOpts )
5156                 {
5157                         return this.api(true).rows( sSelector, oOpts ).data();
5158                 };
5159                 
5160                 
5161                 /**
5162                  * Create a DataTables Api instance, with the currently selected tables for
5163                  * the Api's context.
5164                  * @param {boolean} [traditional=false] Set the API instance's context to be
5165                  *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
5166                  *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
5167                  *   or if all tables captured in the jQuery object should be used.
5168                  * @return {DataTables.Api}
5169                  */
5170                 this.api = function ( traditional )
5171                 {
5172                         return traditional ?
5173                                 new _Api(
5174                                         _fnSettingsFromNode( this[ _ext.iApiIndex ] )
5175                                 ) :
5176                                 new _Api( this );
5177                 };
5178                 
5179                 
5180                 /**
5181                  * Add a single new row or multiple rows of data to the table. Please note
5182                  * that this is suitable for client-side processing only - if you are using
5183                  * server-side processing (i.e. "bServerSide": true), then to add data, you
5184                  * must add it to the data source, i.e. the server-side, through an Ajax call.
5185                  *  @param {array|object} data The data to be added to the table. This can be:
5186                  *    <ul>
5187                  *      <li>1D array of data - add a single row with the data provided</li>
5188                  *      <li>2D array of arrays - add multiple rows in a single call</li>
5189                  *      <li>object - data object when using <i>mData</i></li>
5190                  *      <li>array of objects - multiple data objects when using <i>mData</i></li>
5191                  *    </ul>
5192                  *  @param {bool} [redraw=true] redraw the table or not
5193                  *  @returns {array} An array of integers, representing the list of indexes in
5194                  *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
5195                  *    the table.
5196                  *  @dtopt API
5197                  *  @deprecated Since v1.10
5198                  *
5199                  *  @example
5200                  *    // Global var for counter
5201                  *    var giCount = 2;
5202                  *
5203                  *    $(document).ready(function() {
5204                  *      $('#example').dataTable();
5205                  *    } );
5206                  *
5207                  *    function fnClickAddRow() {
5208                  *      $('#example').dataTable().fnAddData( [
5209                  *        giCount+".1",
5210                  *        giCount+".2",
5211                  *        giCount+".3",
5212                  *        giCount+".4" ]
5213                  *      );
5214                  *
5215                  *      giCount++;
5216                  *    }
5217                  */
5218                 this.fnAddData = function( data, redraw )
5219                 {
5220                         var api = this.api( true );
5221                 
5222                         /* Check if we want to add multiple rows or not */
5223                         var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
5224                                 api.rows.add( data ) :
5225                                 api.row.add( data );
5226                 
5227                         if ( redraw === undefined || redraw ) {
5228                                 api.draw();
5229                         }
5230                 
5231                         return rows.flatten().toArray();
5232                 };
5233                 
5234                 
5235                 /**
5236                  * This function will make DataTables recalculate the column sizes, based on the data
5237                  * contained in the table and the sizes applied to the columns (in the DOM, CSS or
5238                  * through the sWidth parameter). This can be useful when the width of the table's
5239                  * parent element changes (for example a window resize).
5240                  *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
5241                  *  @dtopt API
5242                  *  @deprecated Since v1.10
5243                  *
5244                  *  @example
5245                  *    $(document).ready(function() {
5246                  *      var oTable = $('#example').dataTable( {
5247                  *        "sScrollY": "200px",
5248                  *        "bPaginate": false
5249                  *      } );
5250                  *
5251                  *      $(window).bind('resize', function () {
5252                  *        oTable.fnAdjustColumnSizing();
5253                  *      } );
5254                  *    } );
5255                  */
5256                 this.fnAdjustColumnSizing = function ( bRedraw )
5257                 {
5258                         var api = this.api( true ).columns.adjust();
5259                         var settings = api.settings()[0];
5260                         var scroll = settings.oScroll;
5261                 
5262                         if ( bRedraw === undefined || bRedraw ) {
5263                                 api.draw( false );
5264                         }
5265                         else if ( scroll.sX !== "" || scroll.sY !== "" ) {
5266                                 /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
5267                                 _fnScrollDraw( settings );
5268                         }
5269                 };
5270                 
5271                 
5272                 /**
5273                  * Quickly and simply clear a table
5274                  *  @param {bool} [bRedraw=true] redraw the table or not
5275                  *  @dtopt API
5276                  *  @deprecated Since v1.10
5277                  *
5278                  *  @example
5279                  *    $(document).ready(function() {
5280                  *      var oTable = $('#example').dataTable();
5281                  *
5282                  *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
5283                  *      oTable.fnClearTable();
5284                  *    } );
5285                  */
5286                 this.fnClearTable = function( bRedraw )
5287                 {
5288                         var api = this.api( true ).clear();
5289                 
5290                         if ( bRedraw === undefined || bRedraw ) {
5291                                 api.draw();
5292                         }
5293                 };
5294                 
5295                 
5296                 /**
5297                  * The exact opposite of 'opening' a row, this function will close any rows which
5298                  * are currently 'open'.
5299                  *  @param {node} nTr the table row to 'close'
5300                  *  @returns {int} 0 on success, or 1 if failed (can't find the row)
5301                  *  @dtopt API
5302                  *  @deprecated Since v1.10
5303                  *
5304                  *  @example
5305                  *    $(document).ready(function() {
5306                  *      var oTable;
5307                  *
5308                  *      // 'open' an information row when a row is clicked on
5309                  *      $('#example tbody tr').click( function () {
5310                  *        if ( oTable.fnIsOpen(this) ) {
5311                  *          oTable.fnClose( this );
5312                  *        } else {
5313                  *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5314                  *        }
5315                  *      } );
5316                  *
5317                  *      oTable = $('#example').dataTable();
5318                  *    } );
5319                  */
5320                 this.fnClose = function( nTr )
5321                 {
5322                         this.api( true ).row( nTr ).child.hide();
5323                 };
5324                 
5325                 
5326                 /**
5327                  * Remove a row for the table
5328                  *  @param {mixed} target The index of the row from aoData to be deleted, or
5329                  *    the TR element you want to delete
5330                  *  @param {function|null} [callBack] Callback function
5331                  *  @param {bool} [redraw=true] Redraw the table or not
5332                  *  @returns {array} The row that was deleted
5333                  *  @dtopt API
5334                  *  @deprecated Since v1.10
5335                  *
5336                  *  @example
5337                  *    $(document).ready(function() {
5338                  *      var oTable = $('#example').dataTable();
5339                  *
5340                  *      // Immediately remove the first row
5341                  *      oTable.fnDeleteRow( 0 );
5342                  *    } );
5343                  */
5344                 this.fnDeleteRow = function( target, callback, redraw )
5345                 {
5346                         var api = this.api( true );
5347                         var rows = api.rows( target );
5348                         var settings = rows.settings()[0];
5349                         var data = settings.aoData[ rows[0][0] ];
5350                 
5351                         rows.remove();
5352                 
5353                         if ( callback ) {
5354                                 callback.call( this, settings, data );
5355                         }
5356                 
5357                         if ( redraw === undefined || redraw ) {
5358                                 api.draw();
5359                         }
5360                 
5361                         return data;
5362                 };
5363                 
5364                 
5365                 /**
5366                  * Restore the table to it's original state in the DOM by removing all of DataTables
5367                  * enhancements, alterations to the DOM structure of the table and event listeners.
5368                  *  @param {boolean} [remove=false] Completely remove the table from the DOM
5369                  *  @dtopt API
5370                  *  @deprecated Since v1.10
5371                  *
5372                  *  @example
5373                  *    $(document).ready(function() {
5374                  *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
5375                  *      var oTable = $('#example').dataTable();
5376                  *      oTable.fnDestroy();
5377                  *    } );
5378                  */
5379                 this.fnDestroy = function ( remove )
5380                 {
5381                         this.api( true ).destroy( remove );
5382                 };
5383                 
5384                 
5385                 /**
5386                  * Redraw the table
5387                  *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
5388                  *  @dtopt API
5389                  *  @deprecated Since v1.10
5390                  *
5391                  *  @example
5392                  *    $(document).ready(function() {
5393                  *      var oTable = $('#example').dataTable();
5394                  *
5395                  *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
5396                  *      oTable.fnDraw();
5397                  *    } );
5398                  */
5399                 this.fnDraw = function( complete )
5400                 {
5401                         // Note that this isn't an exact match to the old call to _fnDraw - it takes
5402                         // into account the new data, but can old position.
5403                         this.api( true ).draw( ! complete );
5404                 };
5405                 
5406                 
5407                 /**
5408                  * Filter the input based on data
5409                  *  @param {string} sInput String to filter the table on
5410                  *  @param {int|null} [iColumn] Column to limit filtering to
5411                  *  @param {bool} [bRegex=false] Treat as regular expression or not
5412                  *  @param {bool} [bSmart=true] Perform smart filtering or not
5413                  *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
5414                  *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
5415                  *  @dtopt API
5416                  *  @deprecated Since v1.10
5417                  *
5418                  *  @example
5419                  *    $(document).ready(function() {
5420                  *      var oTable = $('#example').dataTable();
5421                  *
5422                  *      // Sometime later - filter...
5423                  *      oTable.fnFilter( 'test string' );
5424                  *    } );
5425                  */
5426                 this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
5427                 {
5428                         var api = this.api( true );
5429                 
5430                         if ( iColumn === null || iColumn === undefined ) {
5431                                 api.search( sInput, bRegex, bSmart, bCaseInsensitive );
5432                         }
5433                         else {
5434                                 api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
5435                         }
5436                 
5437                         api.draw();
5438                 };
5439                 
5440                 
5441                 /**
5442                  * Get the data for the whole table, an individual row or an individual cell based on the
5443                  * provided parameters.
5444                  *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
5445                  *    a TR node then the data source for the whole row will be returned. If given as a
5446                  *    TD/TH cell node then iCol will be automatically calculated and the data for the
5447                  *    cell returned. If given as an integer, then this is treated as the aoData internal
5448                  *    data index for the row (see fnGetPosition) and the data for that row used.
5449                  *  @param {int} [col] Optional column index that you want the data of.
5450                  *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
5451                  *    returned. If mRow is defined, just data for that row, and is iCol is
5452                  *    defined, only data for the designated cell is returned.
5453                  *  @dtopt API
5454                  *  @deprecated Since v1.10
5455                  *
5456                  *  @example
5457                  *    // Row data
5458                  *    $(document).ready(function() {
5459                  *      oTable = $('#example').dataTable();
5460                  *
5461                  *      oTable.$('tr').click( function () {
5462                  *        var data = oTable.fnGetData( this );
5463                  *        // ... do something with the array / object of data for the row
5464                  *      } );
5465                  *    } );
5466                  *
5467                  *  @example
5468                  *    // Individual cell data
5469                  *    $(document).ready(function() {
5470                  *      oTable = $('#example').dataTable();
5471                  *
5472                  *      oTable.$('td').click( function () {
5473                  *        var sData = oTable.fnGetData( this );
5474                  *        alert( 'The cell clicked on had the value of '+sData );
5475                  *      } );
5476                  *    } );
5477                  */
5478                 this.fnGetData = function( src, col )
5479                 {
5480                         var api = this.api( true );
5481                 
5482                         if ( src !== undefined ) {
5483                                 var type = src.nodeName ? src.nodeName.toLowerCase() : '';
5484                 
5485                                 return col !== undefined || type == 'td' || type == 'th' ?
5486                                         api.cell( src, col ).data() :
5487                                         api.row( src ).data() || null;
5488                         }
5489                 
5490                         return api.data().toArray();
5491                 };
5492                 
5493                 
5494                 /**
5495                  * Get an array of the TR nodes that are used in the table's body. Note that you will
5496                  * typically want to use the '$' API method in preference to this as it is more
5497                  * flexible.
5498                  *  @param {int} [iRow] Optional row index for the TR element you want
5499                  *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
5500                  *    in the table's body, or iRow is defined, just the TR element requested.
5501                  *  @dtopt API
5502                  *  @deprecated Since v1.10
5503                  *
5504                  *  @example
5505                  *    $(document).ready(function() {
5506                  *      var oTable = $('#example').dataTable();
5507                  *
5508                  *      // Get the nodes from the table
5509                  *      var nNodes = oTable.fnGetNodes( );
5510                  *    } );
5511                  */
5512                 this.fnGetNodes = function( iRow )
5513                 {
5514                         var api = this.api( true );
5515                 
5516                         return iRow !== undefined ?
5517                                 api.row( iRow ).node() :
5518                                 api.rows().nodes().flatten().toArray();
5519                 };
5520                 
5521                 
5522                 /**
5523                  * Get the array indexes of a particular cell from it's DOM element
5524                  * and column index including hidden columns
5525                  *  @param {node} node this can either be a TR, TD or TH in the table's body
5526                  *  @returns {int} If nNode is given as a TR, then a single index is returned, or
5527                  *    if given as a cell, an array of [row index, column index (visible),
5528                  *    column index (all)] is given.
5529                  *  @dtopt API
5530                  *  @deprecated Since v1.10
5531                  *
5532                  *  @example
5533                  *    $(document).ready(function() {
5534                  *      $('#example tbody td').click( function () {
5535                  *        // Get the position of the current data from the node
5536                  *        var aPos = oTable.fnGetPosition( this );
5537                  *
5538                  *        // Get the data array for this row
5539                  *        var aData = oTable.fnGetData( aPos[0] );
5540                  *
5541                  *        // Update the data array and return the value
5542                  *        aData[ aPos[1] ] = 'clicked';
5543                  *        this.innerHTML = 'clicked';
5544                  *      } );
5545                  *
5546                  *      // Init DataTables
5547                  *      oTable = $('#example').dataTable();
5548                  *    } );
5549                  */
5550                 this.fnGetPosition = function( node )
5551                 {
5552                         var api = this.api( true );
5553                         var nodeName = node.nodeName.toUpperCase();
5554                 
5555                         if ( nodeName == 'TR' ) {
5556                                 return api.row( node ).index();
5557                         }
5558                         else if ( nodeName == 'TD' || nodeName == 'TH' ) {
5559                                 var cell = api.cell( node ).index();
5560                 
5561                                 return [
5562                                         cell.row,
5563                                         cell.columnVisible,
5564                                         cell.column
5565                                 ];
5566                         }
5567                         return null;
5568                 };
5569                 
5570                 
5571                 /**
5572                  * Check to see if a row is 'open' or not.
5573                  *  @param {node} nTr the table row to check
5574                  *  @returns {boolean} true if the row is currently open, false otherwise
5575                  *  @dtopt API
5576                  *  @deprecated Since v1.10
5577                  *
5578                  *  @example
5579                  *    $(document).ready(function() {
5580                  *      var oTable;
5581                  *
5582                  *      // 'open' an information row when a row is clicked on
5583                  *      $('#example tbody tr').click( function () {
5584                  *        if ( oTable.fnIsOpen(this) ) {
5585                  *          oTable.fnClose( this );
5586                  *        } else {
5587                  *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5588                  *        }
5589                  *      } );
5590                  *
5591                  *      oTable = $('#example').dataTable();
5592                  *    } );
5593                  */
5594                 this.fnIsOpen = function( nTr )
5595                 {
5596                         return this.api( true ).row( nTr ).child.isShown();
5597                 };
5598                 
5599                 
5600                 /**
5601                  * This function will place a new row directly after a row which is currently
5602                  * on display on the page, with the HTML contents that is passed into the
5603                  * function. This can be used, for example, to ask for confirmation that a
5604                  * particular record should be deleted.
5605                  *  @param {node} nTr The table row to 'open'
5606                  *  @param {string|node|jQuery} mHtml The HTML to put into the row
5607                  *  @param {string} sClass Class to give the new TD cell
5608                  *  @returns {node} The row opened. Note that if the table row passed in as the
5609                  *    first parameter, is not found in the table, this method will silently
5610                  *    return.
5611                  *  @dtopt API
5612                  *  @deprecated Since v1.10
5613                  *
5614                  *  @example
5615                  *    $(document).ready(function() {
5616                  *      var oTable;
5617                  *
5618                  *      // 'open' an information row when a row is clicked on
5619                  *      $('#example tbody tr').click( function () {
5620                  *        if ( oTable.fnIsOpen(this) ) {
5621                  *          oTable.fnClose( this );
5622                  *        } else {
5623                  *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5624                  *        }
5625                  *      } );
5626                  *
5627                  *      oTable = $('#example').dataTable();
5628                  *    } );
5629                  */
5630                 this.fnOpen = function( nTr, mHtml, sClass )
5631                 {
5632                         return this.api( true )
5633                                 .row( nTr )
5634                                 .child( mHtml, sClass )
5635                                 .show()
5636                                 .child()[0];
5637                 };
5638                 
5639                 
5640                 /**
5641                  * Change the pagination - provides the internal logic for pagination in a simple API
5642                  * function. With this function you can have a DataTables table go to the next,
5643                  * previous, first or last pages.
5644                  *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
5645                  *    or page number to jump to (integer), note that page 0 is the first page.
5646                  *  @param {bool} [bRedraw=true] Redraw the table or not
5647                  *  @dtopt API
5648                  *  @deprecated Since v1.10
5649                  *
5650                  *  @example
5651                  *    $(document).ready(function() {
5652                  *      var oTable = $('#example').dataTable();
5653                  *      oTable.fnPageChange( 'next' );
5654                  *    } );
5655                  */
5656                 this.fnPageChange = function ( mAction, bRedraw )
5657                 {
5658                         var api = this.api( true ).page( mAction );
5659                 
5660                         if ( bRedraw === undefined || bRedraw ) {
5661                                 api.draw(false);
5662                         }
5663                 };
5664                 
5665                 
5666                 /**
5667                  * Show a particular column
5668                  *  @param {int} iCol The column whose display should be changed
5669                  *  @param {bool} bShow Show (true) or hide (false) the column
5670                  *  @param {bool} [bRedraw=true] Redraw the table or not
5671                  *  @dtopt API
5672                  *  @deprecated Since v1.10
5673                  *
5674                  *  @example
5675                  *    $(document).ready(function() {
5676                  *      var oTable = $('#example').dataTable();
5677                  *
5678                  *      // Hide the second column after initialisation
5679                  *      oTable.fnSetColumnVis( 1, false );
5680                  *    } );
5681                  */
5682                 this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
5683                 {
5684                         var api = this.api( true ).column( iCol ).visible( bShow );
5685                 
5686                         if ( bRedraw === undefined || bRedraw ) {
5687                                 api.columns.adjust().draw();
5688                         }
5689                 };
5690                 
5691                 
5692                 /**
5693                  * Get the settings for a particular table for external manipulation
5694                  *  @returns {object} DataTables settings object. See
5695                  *    {@link DataTable.models.oSettings}
5696                  *  @dtopt API
5697                  *  @deprecated Since v1.10
5698                  *
5699                  *  @example
5700                  *    $(document).ready(function() {
5701                  *      var oTable = $('#example').dataTable();
5702                  *      var oSettings = oTable.fnSettings();
5703                  *
5704                  *      // Show an example parameter from the settings
5705                  *      alert( oSettings._iDisplayStart );
5706                  *    } );
5707                  */
5708                 this.fnSettings = function()
5709                 {
5710                         return _fnSettingsFromNode( this[_ext.iApiIndex] );
5711                 };
5712                 
5713                 
5714                 /**
5715                  * Sort the table by a particular column
5716                  *  @param {int} iCol the data index to sort on. Note that this will not match the
5717                  *    'display index' if you have hidden data entries
5718                  *  @dtopt API
5719                  *  @deprecated Since v1.10
5720                  *
5721                  *  @example
5722                  *    $(document).ready(function() {
5723                  *      var oTable = $('#example').dataTable();
5724                  *
5725                  *      // Sort immediately with columns 0 and 1
5726                  *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
5727                  *    } );
5728                  */
5729                 this.fnSort = function( aaSort )
5730                 {
5731                         this.api( true ).order( aaSort ).draw();
5732                 };
5733                 
5734                 
5735                 /**
5736                  * Attach a sort listener to an element for a given column
5737                  *  @param {node} nNode the element to attach the sort listener to
5738                  *  @param {int} iColumn the column that a click on this node will sort on
5739                  *  @param {function} [fnCallback] callback function when sort is run
5740                  *  @dtopt API
5741                  *  @deprecated Since v1.10
5742                  *
5743                  *  @example
5744                  *    $(document).ready(function() {
5745                  *      var oTable = $('#example').dataTable();
5746                  *
5747                  *      // Sort on column 1, when 'sorter' is clicked on
5748                  *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
5749                  *    } );
5750                  */
5751                 this.fnSortListener = function( nNode, iColumn, fnCallback )
5752                 {
5753                         this.api( true ).order.listener( nNode, iColumn, fnCallback );
5754                 };
5755                 
5756                 
5757                 /**
5758                  * Update a table cell or row - this method will accept either a single value to
5759                  * update the cell with, an array of values with one element for each column or
5760                  * an object in the same format as the original data source. The function is
5761                  * self-referencing in order to make the multi column updates easier.
5762                  *  @param {object|array|string} mData Data to update the cell/row with
5763                  *  @param {node|int} mRow TR element you want to update or the aoData index
5764                  *  @param {int} [iColumn] The column to update, give as null or undefined to
5765                  *    update a whole row.
5766                  *  @param {bool} [bRedraw=true] Redraw the table or not
5767                  *  @param {bool} [bAction=true] Perform pre-draw actions or not
5768                  *  @returns {int} 0 on success, 1 on error
5769                  *  @dtopt API
5770                  *  @deprecated Since v1.10
5771                  *
5772                  *  @example
5773                  *    $(document).ready(function() {
5774                  *      var oTable = $('#example').dataTable();
5775                  *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
5776                  *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
5777                  *    } );
5778                  */
5779                 this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
5780                 {
5781                         var api = this.api( true );
5782                 
5783                         if ( iColumn === undefined || iColumn === null ) {
5784                                 api.row( mRow ).data( mData );
5785                         }
5786                         else {
5787                                 api.cell( mRow, iColumn ).data( mData );
5788                         }
5789                 
5790                         if ( bAction === undefined || bAction ) {
5791                                 api.columns.adjust();
5792                         }
5793                 
5794                         if ( bRedraw === undefined || bRedraw ) {
5795                                 api.draw();
5796                         }
5797                         return 0;
5798                 };
5799                 
5800                 
5801                 /**
5802                  * Provide a common method for plug-ins to check the version of DataTables being used, in order
5803                  * to ensure compatibility.
5804                  *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
5805                  *    formats "X" and "X.Y" are also acceptable.
5806                  *  @returns {boolean} true if this version of DataTables is greater or equal to the required
5807                  *    version, or false if this version of DataTales is not suitable
5808                  *  @method
5809                  *  @dtopt API
5810                  *  @deprecated Since v1.10
5811                  *
5812                  *  @example
5813                  *    $(document).ready(function() {
5814                  *      var oTable = $('#example').dataTable();
5815                  *      alert( oTable.fnVersionCheck( '1.9.0' ) );
5816                  *    } );
5817                  */
5818                 this.fnVersionCheck = _ext.fnVersionCheck;
5819                 
5820
5821                 var _that = this;
5822                 var emptyInit = options === undefined;
5823                 var len = this.length;
5824
5825                 if ( emptyInit ) {
5826                         options = {};
5827                 }
5828
5829                 this.oApi = this.internal = _ext.internal;
5830
5831                 // Extend with old style plug-in API methods
5832                 for ( var fn in DataTable.ext.internal ) {
5833                         if ( fn ) {
5834                                 this[fn] = _fnExternApiFunc(fn);
5835                         }
5836                 }
5837
5838                 this.each(function() {
5839                         // For each initialisation we want to give it a clean initialisation
5840                         // object that can be bashed around
5841                         var o = {};
5842                         var oInit = len > 1 ? // optimisation for single table case
5843                                 _fnExtend( o, options, true ) :
5844                                 options;
5845
5846                         /*global oInit,_that,emptyInit*/
5847                         var i=0, iLen, j, jLen, k, kLen;
5848                         var sId = this.getAttribute( 'id' );
5849                         var bInitHandedOff = false;
5850                         var defaults = DataTable.defaults;
5851                         
5852                         
5853                         /* Sanity check */
5854                         if ( this.nodeName.toLowerCase() != 'table' )
5855                         {
5856                                 _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
5857                                 return;
5858                         }
5859                         
5860                         /* Backwards compatibility for the defaults */
5861                         _fnCompatOpts( defaults );
5862                         _fnCompatCols( defaults.column );
5863                         
5864                         /* Convert the camel-case defaults to Hungarian */
5865                         _fnCamelToHungarian( defaults, defaults, true );
5866                         _fnCamelToHungarian( defaults.column, defaults.column, true );
5867                         
5868                         /* Setting up the initialisation object */
5869                         _fnCamelToHungarian( defaults, oInit );
5870                         
5871                         /* Check to see if we are re-initialising a table */
5872                         var allSettings = DataTable.settings;
5873                         for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
5874                         {
5875                                 /* Base check on table node */
5876                                 if ( allSettings[i].nTable == this )
5877                                 {
5878                                         var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
5879                                         var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
5880                         
5881                                         if ( emptyInit || bRetrieve )
5882                                         {
5883                                                 return allSettings[i].oInstance;
5884                                         }
5885                                         else if ( bDestroy )
5886                                         {
5887                                                 allSettings[i].oInstance.fnDestroy();
5888                                                 break;
5889                                         }
5890                                         else
5891                                         {
5892                                                 _fnLog( allSettings[i], 0, 'Cannot reinitialise DataTable', 3 );
5893                                                 return;
5894                                         }
5895                                 }
5896                         
5897                                 /* If the element we are initialising has the same ID as a table which was previously
5898                                  * initialised, but the table nodes don't match (from before) then we destroy the old
5899                                  * instance by simply deleting it. This is under the assumption that the table has been
5900                                  * destroyed by other methods. Anyone using non-id selectors will need to do this manually
5901                                  */
5902                                 if ( allSettings[i].sTableId == this.id )
5903                                 {
5904                                         allSettings.splice( i, 1 );
5905                                         break;
5906                                 }
5907                         }
5908                         
5909                         /* Ensure the table has an ID - required for accessibility */
5910                         if ( sId === null || sId === "" )
5911                         {
5912                                 sId = "DataTables_Table_"+(DataTable.ext._unique++);
5913                                 this.id = sId;
5914                         }
5915                         
5916                         /* Create the settings object for this table and set some of the default parameters */
5917                         var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
5918                                 "nTable":        this,
5919                                 "oApi":          _that.internal,
5920                                 "oInit":         oInit,
5921                                 "sDestroyWidth": $(this)[0].style.width,
5922                                 "sInstance":     sId,
5923                                 "sTableId":      sId
5924                         } );
5925                         allSettings.push( oSettings );
5926                         
5927                         // Need to add the instance after the instance after the settings object has been added
5928                         // to the settings array, so we can self reference the table instance if more than one
5929                         oSettings.oInstance = (_that.length===1) ? _that : $(this).dataTable();
5930                         
5931                         // Backwards compatibility, before we apply all the defaults
5932                         _fnCompatOpts( oInit );
5933                         
5934                         if ( oInit.oLanguage )
5935                         {
5936                                 _fnLanguageCompat( oInit.oLanguage );
5937                         }
5938                         
5939                         // If the length menu is given, but the init display length is not, use the length menu
5940                         if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
5941                         {
5942                                 oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
5943                                         oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
5944                         }
5945                         
5946                         // Apply the defaults and init options to make a single init object will all
5947                         // options defined from defaults and instance options.
5948                         oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
5949                         
5950                         
5951                         // Map the initialisation options onto the settings object
5952                         _fnMap( oSettings.oFeatures, oInit, [
5953                                 "bPaginate",
5954                                 "bLengthChange",
5955                                 "bFilter",
5956                                 "bSort",
5957                                 "bSortMulti",
5958                                 "bInfo",
5959                                 "bProcessing",
5960                                 "bAutoWidth",
5961                                 "bSortClasses",
5962                                 "bServerSide",
5963                                 "bDeferRender"
5964                         ] );
5965                         _fnMap( oSettings, oInit, [
5966                                 "asStripeClasses",
5967                                 "ajax",
5968                                 "fnServerData",
5969                                 "fnFormatNumber",
5970                                 "sServerMethod",
5971                                 "aaSorting",
5972                                 "aaSortingFixed",
5973                                 "aLengthMenu",
5974                                 "sPaginationType",
5975                                 "sAjaxSource",
5976                                 "sAjaxDataProp",
5977                                 "iStateDuration",
5978                                 "sDom",
5979                                 "bSortCellsTop",
5980                                 "iTabIndex",
5981                                 "fnStateLoadCallback",
5982                                 "fnStateSaveCallback",
5983                                 "renderer",
5984                                 [ "iCookieDuration", "iStateDuration" ], // backwards compat
5985                                 [ "oSearch", "oPreviousSearch" ],
5986                                 [ "aoSearchCols", "aoPreSearchCols" ],
5987                                 [ "iDisplayLength", "_iDisplayLength" ],
5988                                 [ "bJQueryUI", "bJUI" ]
5989                         ] );
5990                         _fnMap( oSettings.oScroll, oInit, [
5991                                 [ "sScrollX", "sX" ],
5992                                 [ "sScrollXInner", "sXInner" ],
5993                                 [ "sScrollY", "sY" ],
5994                                 [ "bScrollCollapse", "bCollapse" ]
5995                         ] );
5996                         _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
5997                         
5998                         /* Callback functions which are array driven */
5999                         _fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
6000                         _fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
6001                         _fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
6002                         _fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
6003                         _fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
6004                         _fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
6005                         _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
6006                         _fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
6007                         _fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
6008                         _fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
6009                         _fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
6010                         
6011                         var oClasses = oSettings.oClasses;
6012                         
6013                         // @todo Remove in 1.11
6014                         if ( oInit.bJQueryUI )
6015                         {
6016                                 /* Use the JUI classes object for display. You could clone the oStdClasses object if
6017                                  * you want to have multiple tables with multiple independent classes
6018                                  */
6019                                 $.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses );
6020                         
6021                                 if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" )
6022                                 {
6023                                         /* Set the DOM to use a layout suitable for jQuery UI's theming */
6024                                         oSettings.sDom = '<"H"lfr>t<"F"ip>';
6025                                 }
6026                         
6027                                 if ( ! oSettings.renderer ) {
6028                                         oSettings.renderer = 'jqueryui';
6029                                 }
6030                                 else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) {
6031                                         oSettings.renderer.header = 'jqueryui';
6032                                 }
6033                         }
6034                         else
6035                         {
6036                                 $.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
6037                         }
6038                         $(this).addClass( oClasses.sTable );
6039                         
6040                         /* Calculate the scroll bar width and cache it for use later on */
6041                         if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
6042                         {
6043                                 oSettings.oScroll.iBarWidth = _fnScrollBarWidth();
6044                         }
6045                         if ( oSettings.oScroll.sX === true ) { // Easy initialisation of x-scrolling
6046                                 oSettings.oScroll.sX = '100%';
6047                         }
6048                         
6049                         if ( oSettings.iInitDisplayStart === undefined )
6050                         {
6051                                 /* Display start point, taking into account the save saving */
6052                                 oSettings.iInitDisplayStart = oInit.iDisplayStart;
6053                                 oSettings._iDisplayStart = oInit.iDisplayStart;
6054                         }
6055                         
6056                         if ( oInit.iDeferLoading !== null )
6057                         {
6058                                 oSettings.bDeferLoading = true;
6059                                 var tmp = $.isArray( oInit.iDeferLoading );
6060                                 oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
6061                                 oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
6062                         }
6063                         
6064                         /* Language definitions */
6065                         if ( oInit.oLanguage.sUrl !== "" )
6066                         {
6067                                 /* Get the language definitions from a file - because this Ajax call makes the language
6068                                  * get async to the remainder of this function we use bInitHandedOff to indicate that
6069                                  * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
6070                                  */
6071                                 oSettings.oLanguage.sUrl = oInit.oLanguage.sUrl;
6072                                 $.getJSON( oSettings.oLanguage.sUrl, null, function( json ) {
6073                                         _fnLanguageCompat( json );
6074                                         _fnCamelToHungarian( defaults.oLanguage, json );
6075                                         $.extend( true, oSettings.oLanguage, oInit.oLanguage, json );
6076                                         _fnInitialise( oSettings );
6077                                 } );
6078                                 bInitHandedOff = true;
6079                         }
6080                         else
6081                         {
6082                                 $.extend( true, oSettings.oLanguage, oInit.oLanguage );
6083                         }
6084                         
6085                         
6086                         /*
6087                          * Stripes
6088                          */
6089                         if ( oInit.asStripeClasses === null )
6090                         {
6091                                 oSettings.asStripeClasses =[
6092                                         oClasses.sStripeOdd,
6093                                         oClasses.sStripeEven
6094                                 ];
6095                         }
6096                         
6097                         /* Remove row stripe classes if they are already on the table row */
6098                         var stripeClasses = oSettings.asStripeClasses;
6099                         var rowOne = $('tbody tr:eq(0)', this);
6100                         if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
6101                                 return rowOne.hasClass(el);
6102                         } ) ) !== -1 ) {
6103                                 $('tbody tr', this).removeClass( stripeClasses.join(' ') );
6104                                 oSettings.asDestroyStripes = stripeClasses.slice();
6105                         }
6106                         
6107                         /*
6108                          * Columns
6109                          * See if we should load columns automatically or use defined ones
6110                          */
6111                         var anThs = [];
6112                         var aoColumnsInit;
6113                         var nThead = this.getElementsByTagName('thead');
6114                         if ( nThead.length !== 0 )
6115                         {
6116                                 _fnDetectHeader( oSettings.aoHeader, nThead[0] );
6117                                 anThs = _fnGetUniqueThs( oSettings );
6118                         }
6119                         
6120                         /* If not given a column array, generate one with nulls */
6121                         if ( oInit.aoColumns === null )
6122                         {
6123                                 aoColumnsInit = [];
6124                                 for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
6125                                 {
6126                                         aoColumnsInit.push( null );
6127                                 }
6128                         }
6129                         else
6130                         {
6131                                 aoColumnsInit = oInit.aoColumns;
6132                         }
6133                         
6134                         /* Add the columns */
6135                         for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
6136                         {
6137                                 _fnAddColumn( oSettings, anThs ? anThs[i] : null );
6138                         }
6139                         
6140                         /* Apply the column definitions */
6141                         _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
6142                                 _fnColumnOptions( oSettings, iCol, oDef );
6143                         } );
6144                         
6145                         /* HTML5 attribute detection - build an mData object automatically if the
6146                          * attributes are found
6147                          */
6148                         if ( rowOne.length ) {
6149                                 var a = function ( cell, name ) {
6150                                         return cell.getAttribute( 'data-'+name ) ? name : null;
6151                                 };
6152                         
6153                                 $.each( _fnGetRowElements( oSettings, rowOne[0] ).cells, function (i, cell) {
6154                                         var col = oSettings.aoColumns[i];
6155                         
6156                                         if ( col.mData === i ) {
6157                                                 var sort = a( cell, 'sort' ) || a( cell, 'order' );
6158                                                 var filter = a( cell, 'filter' ) || a( cell, 'search' );
6159                         
6160                                                 if ( sort !== null || filter !== null ) {
6161                                                         col.mData = {
6162                                                                 _:      i+'.display',
6163                                                                 sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
6164                                                                 type:   sort !== null   ? i+'.@data-'+sort   : undefined,
6165                                                                 filter: filter !== null ? i+'.@data-'+filter : undefined
6166                                                         };
6167                         
6168                                                         _fnColumnOptions( oSettings, i );
6169                                                 }
6170                                         }
6171                                 } );
6172                         }
6173                         
6174                         var features = oSettings.oFeatures;
6175                         
6176                         /* Must be done after everything which can be overridden by the state saving! */
6177                         if ( oInit.bStateSave )
6178                         {
6179                                 features.bStateSave = true;
6180                                 _fnLoadState( oSettings, oInit );
6181                                 _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
6182                         }
6183                         
6184                         
6185                         /*
6186                          * Sorting
6187                          * @todo For modularisation (1.11) this needs to do into a sort start up handler
6188                          */
6189                         
6190                         // If aaSorting is not defined, then we use the first indicator in asSorting
6191                         // in case that has been altered, so the default sort reflects that option
6192                         if ( oInit.aaSorting === undefined )
6193                         {
6194                                 var sorting = oSettings.aaSorting;
6195                                 for ( i=0, iLen=sorting.length ; i<iLen ; i++ )
6196                                 {
6197                                         sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
6198                                 }
6199                         }
6200                         
6201                         /* Do a first pass on the sorting classes (allows any size changes to be taken into
6202                          * account, and also will apply sorting disabled classes if disabled
6203                          */
6204                         _fnSortingClasses( oSettings );
6205                         
6206                         if ( features.bSort )
6207                         {
6208                                 _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
6209                                         if ( oSettings.bSorted ) {
6210                                                 var aSort = _fnSortFlatten( oSettings );
6211                                                 var sortedColumns = {};
6212                         
6213                                                 $.each( aSort, function (i, val) {
6214                                                         sortedColumns[ val.src ] = val.dir;
6215                                                 } );
6216                         
6217                                                 _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
6218                                                 _fnSortAria( oSettings );
6219                                         }
6220                                 } );
6221                         }
6222                         
6223                         _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
6224                                 if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
6225                                         _fnSortingClasses( oSettings );
6226                                 }
6227                         }, 'sc' );
6228                         
6229                         
6230                         /*
6231                          * Final init
6232                          * Cache the header, body and footer as required, creating them if needed
6233                          */
6234                         
6235                         /* Browser support detection */
6236                         _fnBrowserDetect( oSettings );
6237                         
6238                         // Work around for Webkit bug 83867 - store the caption-side before removing from doc
6239                         var captions = $(this).children('caption').each( function () {
6240                                 this._captionSide = $(this).css('caption-side');
6241                         } );
6242                         
6243                         var thead = $(this).children('thead');
6244                         if ( thead.length === 0 )
6245                         {
6246                                 thead = $('<thead/>').appendTo(this);
6247                         }
6248                         oSettings.nTHead = thead[0];
6249                         
6250                         var tbody = $(this).children('tbody');
6251                         if ( tbody.length === 0 )
6252                         {
6253                                 tbody = $('<tbody/>').appendTo(this);
6254                         }
6255                         oSettings.nTBody = tbody[0];
6256                         
6257                         var tfoot = $(this).children('tfoot');
6258                         if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
6259                         {
6260                                 // If we are a scrolling table, and no footer has been given, then we need to create
6261                                 // a tfoot element for the caption element to be appended to
6262                                 tfoot = $('<tfoot/>').appendTo(this);
6263                         }
6264                         
6265                         if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
6266                                 $(this).addClass( oClasses.sNoFooter );
6267                         }
6268                         else if ( tfoot.length > 0 ) {
6269                                 oSettings.nTFoot = tfoot[0];
6270                                 _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
6271                         }
6272                         
6273                         /* Check if there is data passing into the constructor */
6274                         if ( oInit.aaData )
6275                         {
6276                                 for ( i=0 ; i<oInit.aaData.length ; i++ )
6277                                 {
6278                                         _fnAddData( oSettings, oInit.aaData[ i ] );
6279                                 }
6280                         }
6281                         else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' )
6282                         {
6283                                 /* Grab the data from the page - only do this when deferred loading or no Ajax
6284                                  * source since there is no point in reading the DOM data if we are then going
6285                                  * to replace it with Ajax data
6286                                  */
6287                                 _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
6288                         }
6289                         
6290                         /* Copy the data index array */
6291                         oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
6292                         
6293                         /* Initialisation complete - table can be drawn */
6294                         oSettings.bInitialised = true;
6295                         
6296                         /* Check if we need to initialise the table (it might not have been handed off to the
6297                          * language processor)
6298                          */
6299                         if ( bInitHandedOff === false )
6300                         {
6301                                 _fnInitialise( oSettings );
6302                         }
6303                 } );
6304                 _that = null;
6305                 return this;
6306         };
6307
6308         
6309         
6310         /**
6311          * Computed structure of the DataTables API, defined by the options passed to
6312          * `DataTable.Api.register()` when building the API.
6313          *
6314          * The structure is built in order to speed creation and extension of the Api
6315          * objects since the extensions are effectively pre-parsed.
6316          *
6317          * The array is an array of objects with the following structure, where this
6318          * base array represents the Api prototype base:
6319          *
6320          *     [
6321          *       {
6322          *         name:      'data'                -- string   - Property name
6323          *         val:       function () {},       -- function - Api method (or undefined if just an object
6324          *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6325          *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6326          *       },
6327          *       {
6328          *         name:     'row'
6329          *         val:       {},
6330          *         methodExt: [ ... ],
6331          *         propExt:   [
6332          *           {
6333          *             name:      'data'
6334          *             val:       function () {},
6335          *             methodExt: [ ... ],
6336          *             propExt:   [ ... ]
6337          *           },
6338          *           ...
6339          *         ]
6340          *       }
6341          *     ]
6342          *
6343          * @type {Array}
6344          * @ignore
6345          */
6346         var __apiStruct = [];
6347         
6348         
6349         /**
6350          * `Array.prototype` reference.
6351          *
6352          * @type object
6353          * @ignore
6354          */
6355         var __arrayProto = Array.prototype;
6356         
6357         
6358         /**
6359          * Abstraction for `context` parameter of the `Api` constructor to allow it to
6360          * take several different forms for ease of use.
6361          *
6362          * Each of the input parameter types will be converted to a DataTables settings
6363          * object where possible.
6364          *
6365          * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6366          *   of:
6367          *
6368          *   * `string` - jQuery selector. Any DataTables' matching the given selector
6369          *     with be found and used.
6370          *   * `node` - `TABLE` node which has already been formed into a DataTable.
6371          *   * `jQuery` - A jQuery object of `TABLE` nodes.
6372          *   * `object` - DataTables settings object
6373          *   * `DataTables.Api` - API instance
6374          * @return {array|null} Matching DataTables settings objects. `null` or
6375          *   `undefined` is returned if no matching DataTable is found.
6376          * @ignore
6377          */
6378         var _toSettings = function ( mixed )
6379         {
6380                 var idx, jq;
6381                 var settings = DataTable.settings;
6382                 var tables = $.map( settings, function (el, i) {
6383                         return el.nTable;
6384                 } );
6385         
6386                 if ( ! mixed ) {
6387                         return [];
6388                 }
6389                 else if ( mixed.nTable && mixed.oApi ) {
6390                         // DataTables settings object
6391                         return [ mixed ];
6392                 }
6393                 else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6394                         // Table node
6395                         idx = $.inArray( mixed, tables );
6396                         return idx !== -1 ? [ settings[idx] ] : null;
6397                 }
6398                 else if ( mixed && typeof mixed.settings === 'function' ) {
6399                         return mixed.settings().toArray();
6400                 }
6401                 else if ( typeof mixed === 'string' ) {
6402                         // jQuery selector
6403                         jq = $(mixed);
6404                 }
6405                 else if ( mixed instanceof $ ) {
6406                         // jQuery object (also DataTables instance)
6407                         jq = mixed;
6408                 }
6409         
6410                 if ( jq ) {
6411                         return jq.map( function(i) {
6412                                 idx = $.inArray( this, tables );
6413                                 return idx !== -1 ? settings[idx] : null;
6414                         } ).toArray();
6415                 }
6416         };
6417         
6418         
6419         /**
6420          * DataTables API class - used to control and interface with  one or more
6421          * DataTables enhanced tables.
6422          *
6423          * The API class is heavily based on jQuery, presenting a chainable interface
6424          * that you can use to interact with tables. Each instance of the API class has
6425          * a "context" - i.e. the tables that it will operate on. This could be a single
6426          * table, all tables on a page or a sub-set thereof.
6427          *
6428          * Additionally the API is designed to allow you to easily work with the data in
6429          * the tables, retrieving and manipulating it as required. This is done by
6430          * presenting the API class as an array like interface. The contents of the
6431          * array depend upon the actions requested by each method (for example
6432          * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6433          * return an array of objects or arrays depending upon your table's
6434          * configuration). The API object has a number of array like methods (`push`,
6435          * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6436          * `unique` etc) to assist your working with the data held in a table.
6437          *
6438          * Most methods (those which return an Api instance) are chainable, which means
6439          * the return from a method call also has all of the methods available that the
6440          * top level object had. For example, these two calls are equivalent:
6441          *
6442          *     // Not chained
6443          *     api.row.add( {...} );
6444          *     api.draw();
6445          *
6446          *     // Chained
6447          *     api.row.add( {...} ).draw();
6448          *
6449          * @class DataTable.Api
6450          * @param {array|object|string|jQuery} context DataTable identifier. This is
6451          *   used to define which DataTables enhanced tables this API will operate on.
6452          *   Can be one of:
6453          *
6454          *   * `string` - jQuery selector. Any DataTables' matching the given selector
6455          *     with be found and used.
6456          *   * `node` - `TABLE` node which has already been formed into a DataTable.
6457          *   * `jQuery` - A jQuery object of `TABLE` nodes.
6458          *   * `object` - DataTables settings object
6459          * @param {array} [data] Data to initialise the Api instance with.
6460          *
6461          * @example
6462          *   // Direct initialisation during DataTables construction
6463          *   var api = $('#example').DataTable();
6464          *
6465          * @example
6466          *   // Initialisation using a DataTables jQuery object
6467          *   var api = $('#example').dataTable().api();
6468          *
6469          * @example
6470          *   // Initialisation as a constructor
6471          *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6472          */
6473         DataTable.Api = _Api = function ( context, data )
6474         {
6475                 if ( ! this instanceof _Api ) {
6476                         throw 'DT API must be constructed as a new object';
6477                         // or should it do the 'new' for the caller?
6478                         // return new _Api.apply( this, arguments );
6479                 }
6480         
6481                 var settings = [];
6482                 var ctxSettings = function ( o ) {
6483                         var a = _toSettings( o );
6484                         if ( a ) {
6485                                 settings.push.apply( settings, a );
6486                         }
6487                 };
6488         
6489                 if ( $.isArray( context ) ) {
6490                         for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6491                                 ctxSettings( context[i] );
6492                         }
6493                 }
6494                 else {
6495                         ctxSettings( context );
6496                 }
6497         
6498                 // Remove duplicates
6499                 this.context = _unique( settings );
6500         
6501                 // Initial data
6502                 if ( data ) {
6503                         this.push.apply( this, data.toArray ? data.toArray() : data );
6504                 }
6505         
6506                 // selector
6507                 this.selector = {
6508                         rows: null,
6509                         cols: null,
6510                         opts: null
6511                 };
6512         
6513                 _Api.extend( this, this, __apiStruct );
6514         };
6515         
6516         
6517         _Api.prototype = /** @lends DataTables.Api */{
6518                 /**
6519                  * Return a new Api instance, comprised of the data held in the current
6520                  * instance, join with the other array(s) and/or value(s).
6521                  *
6522                  * An alias for `Array.prototype.concat`.
6523                  *
6524                  * @type method
6525                  * @param {*} value1 Arrays and/or values to concatenate.
6526                  * @param {*} [...] Additional arrays and/or values to concatenate.
6527                  * @returns {DataTables.Api} New API instance, comprising of the combined
6528                  *   array.
6529                  */
6530                 concat:  __arrayProto.concat,
6531         
6532         
6533                 context: [], // array of table settings objects
6534         
6535         
6536                 each: function ( fn )
6537                 {
6538                         if ( __arrayProto.forEach ) {
6539                                 // Where possible, use the built-in forEach
6540                                 __arrayProto.forEach.call( this, fn, this );
6541                         }
6542                         else {
6543                                 // Compatibility for browsers without EMCA-252-5 (JS 1.6)
6544                                 for ( var i=0, ien=this.length ; i<ien; i++ ) {
6545                                         // In strict mode the execution scope is the passed value
6546                                         fn.call( this, this[i], i, this );
6547                                 }
6548                         }
6549         
6550                         return this;
6551                 },
6552         
6553         
6554                 eq: function ( idx )
6555                 {
6556                         var ctx = this.context;
6557         
6558                         return ctx.length > idx ?
6559                                 new _Api( ctx[idx], this[idx] ) :
6560                                 null;
6561                 },
6562         
6563         
6564                 filter: function ( fn )
6565                 {
6566                         var a = [];
6567         
6568                         if ( __arrayProto.filter ) {
6569                                 a = __arrayProto.filter.call( this, fn, this );
6570                         }
6571                         else {
6572                                 // Compatibility for browsers without EMCA-252-5 (JS 1.6)
6573                                 for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6574                                         if ( fn.call( this, this[i], i, this ) ) {
6575                                                 a.push( this[i] );
6576                                         }
6577                                 }
6578                         }
6579         
6580                         return new _Api( this.context, a );
6581                 },
6582         
6583         
6584                 flatten: function ()
6585                 {
6586                         var a = [];
6587                         return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
6588                 },
6589         
6590         
6591                 join:    __arrayProto.join,
6592         
6593         
6594                 indexOf: __arrayProto.indexOf || function (obj, start)
6595                 {
6596                         for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
6597                                 if ( this[i] === obj ) {
6598                                         return i;
6599                                 }
6600                         }
6601                         return -1;
6602                 },
6603         
6604                 // Internal only at the moment - relax?
6605                 iterator: function ( flatten, type, fn ) {
6606                         var
6607                                 a = [], ret,
6608                                 i, ien, j, jen,
6609                                 context = this.context,
6610                                 rows, items, item,
6611                                 selector = this.selector;
6612         
6613                         // Argument shifting
6614                         if ( typeof flatten === 'string' ) {
6615                                 fn = type;
6616                                 type = flatten;
6617                                 flatten = false;
6618                         }
6619         
6620                         for ( i=0, ien=context.length ; i<ien ; i++ ) {
6621                                 if ( type === 'table' ) {
6622                                         ret = fn( context[i], i );
6623         
6624                                         if ( ret !== undefined ) {
6625                                                 a.push( ret );
6626                                         }
6627                                 }
6628                                 else if ( type === 'columns' || type === 'rows' ) {
6629                                         // this has same length as context - one entry for each table
6630                                         ret = fn( context[i], this[i], i );
6631         
6632                                         if ( ret !== undefined ) {
6633                                                 a.push( ret );
6634                                         }
6635                                 }
6636                                 else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
6637                                         // columns and rows share the same structure.
6638                                         // 'this' is an array of column indexes for each context
6639                                         items = this[i];
6640         
6641                                         if ( type === 'column-rows' ) {
6642                                                 rows = _selector_row_indexes( context[i], selector.opts );
6643                                         }
6644         
6645                                         for ( j=0, jen=items.length ; j<jen ; j++ ) {
6646                                                 item = items[j];
6647         
6648                                                 if ( type === 'cell' ) {
6649                                                         ret = fn( context[i], item.row, item.column, i, j );
6650                                                 }
6651                                                 else {
6652                                                         ret = fn( context[i], item, i, j, rows );
6653                                                 }
6654         
6655                                                 if ( ret !== undefined ) {
6656                                                         a.push( ret );
6657                                                 }
6658                                         }
6659                                 }
6660                         }
6661         
6662                         if ( a.length ) {
6663                                 var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
6664                                 var apiSelector = api.selector;
6665                                 apiSelector.rows = selector.rows;
6666                                 apiSelector.cols = selector.cols;
6667                                 apiSelector.opts = selector.opts;
6668                                 return api;
6669                         }
6670                         return this;
6671                 },
6672         
6673         
6674                 lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
6675                 {
6676                         // Bit cheeky...
6677                         return this.indexOf.apply( this.toArray.reverse(), arguments );
6678                 },
6679         
6680         
6681                 length:  0,
6682         
6683         
6684                 map: function ( fn )
6685                 {
6686                         var a = [];
6687         
6688                         if ( __arrayProto.map ) {
6689                                 a = __arrayProto.map.call( this, fn, this );
6690                         }
6691                         else {
6692                                 // Compatibility for browsers without EMCA-252-5 (JS 1.6)
6693                                 for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6694                                         a.push( fn.call( this, this[i], i ) );
6695                                 }
6696                         }
6697         
6698                         return new _Api( this.context, a );
6699                 },
6700         
6701         
6702                 pluck: function ( prop )
6703                 {
6704                         return this.map( function ( el ) {
6705                                 return el[ prop ];
6706                         } );
6707                 },
6708         
6709                 pop:     __arrayProto.pop,
6710         
6711         
6712                 push:    __arrayProto.push,
6713         
6714         
6715                 // Does not return an API instance
6716                 reduce: __arrayProto.reduce || function ( fn, init )
6717                 {
6718                         return _fnReduce( this, fn, init, 0, this.length, 1 );
6719                 },
6720         
6721         
6722                 reduceRight: __arrayProto.reduceRight || function ( fn, init )
6723                 {
6724                         return _fnReduce( this, fn, init, this.length-1, -1, -1 );
6725                 },
6726         
6727         
6728                 reverse: __arrayProto.reverse,
6729         
6730         
6731                 // Object with rows, columns and opts
6732                 selector: null,
6733         
6734         
6735                 shift:   __arrayProto.shift,
6736         
6737         
6738                 sort:    __arrayProto.sort, // ? name - order?
6739         
6740         
6741                 splice:  __arrayProto.splice,
6742         
6743         
6744                 toArray: function ()
6745                 {
6746                         return __arrayProto.slice.call( this );
6747                 },
6748         
6749         
6750                 to$: function ()
6751                 {
6752                         return $( this );
6753                 },
6754         
6755         
6756                 toJQuery: function ()
6757                 {
6758                         return $( this );
6759                 },
6760         
6761         
6762                 unique: function ()
6763                 {
6764                         return new _Api( this.context, _unique(this) );
6765                 },
6766         
6767         
6768                 unshift: __arrayProto.unshift
6769         };
6770         
6771         
6772         _Api.extend = function ( scope, obj, ext )
6773         {
6774                 // Only extend API instances and static properties of the API
6775                 if ( ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
6776                         return;
6777                 }
6778         
6779                 var
6780                         i, ien,
6781                         j, jen,
6782                         struct, inner,
6783                         methodScoping = function ( fn, struc ) {
6784                                 return function () {
6785                                         var ret = fn.apply( scope, arguments );
6786         
6787                                         // Method extension
6788                                         _Api.extend( ret, ret, struc.methodExt );
6789                                         return ret;
6790                                 };
6791                         };
6792         
6793                 for ( i=0, ien=ext.length ; i<ien ; i++ ) {
6794                         struct = ext[i];
6795         
6796                         // Value
6797                         obj[ struct.name ] = typeof struct.val === 'function' ?
6798                                 methodScoping( struct.val, struct ) :
6799                                 $.isPlainObject( struct.val ) ?
6800                                         {} :
6801                                         struct.val;
6802         
6803                         obj[ struct.name ].__dt_wrapper = true;
6804         
6805                         // Property extension
6806                         _Api.extend( scope, obj[ struct.name ], struct.propExt );
6807                 }
6808         };
6809         
6810         
6811         // @todo - Is there need for an augment function?
6812         // _Api.augment = function ( inst, name )
6813         // {
6814         //      // Find src object in the structure from the name
6815         //      var parts = name.split('.');
6816         
6817         //      _Api.extend( inst, obj );
6818         // };
6819         
6820         
6821         //     [
6822         //       {
6823         //         name:      'data'                -- string   - Property name
6824         //         val:       function () {},       -- function - Api method (or undefined if just an object
6825         //         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6826         //         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6827         //       },
6828         //       {
6829         //         name:     'row'
6830         //         val:       {},
6831         //         methodExt: [ ... ],
6832         //         propExt:   [
6833         //           {
6834         //             name:      'data'
6835         //             val:       function () {},
6836         //             methodExt: [ ... ],
6837         //             propExt:   [ ... ]
6838         //           },
6839         //           ...
6840         //         ]
6841         //       }
6842         //     ]
6843         
6844         _Api.register = _api_register = function ( name, val )
6845         {
6846                 if ( $.isArray( name ) ) {
6847                         for ( var j=0, jen=name.length ; j<jen ; j++ ) {
6848                                 _Api.register( name[j], val );
6849                         }
6850                         return;
6851                 }
6852         
6853                 var
6854                         i, ien,
6855                         heir = name.split('.'),
6856                         struct = __apiStruct,
6857                         key, method;
6858         
6859                 var find = function ( src, name ) {
6860                         for ( var i=0, ien=src.length ; i<ien ; i++ ) {
6861                                 if ( src[i].name === name ) {
6862                                         return src[i];
6863                                 }
6864                         }
6865                         return null;
6866                 };
6867         
6868                 for ( i=0, ien=heir.length ; i<ien ; i++ ) {
6869                         method = heir[i].indexOf('()') !== -1;
6870                         key = method ?
6871                                 heir[i].replace('()', '') :
6872                                 heir[i];
6873         
6874                         var src = find( struct, key );
6875                         if ( ! src ) {
6876                                 src = {
6877                                         name:      key,
6878                                         val:       {},
6879                                         methodExt: [],
6880                                         propExt:   []
6881                                 };
6882                                 struct.push( src );
6883                         }
6884         
6885                         if ( i === ien-1 ) {
6886                                 src.val = val;
6887                         }
6888                         else {
6889                                 struct = method ?
6890                                         src.methodExt :
6891                                         src.propExt;
6892                         }
6893                 }
6894         
6895                 // Rebuild the API with the new construct
6896                 if ( _Api.ready ) {
6897                         DataTable.api.build();
6898                 }
6899         };
6900         
6901         
6902         _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
6903                 _Api.register( pluralName, val );
6904         
6905                 _Api.register( singularName, function () {
6906                         var ret = val.apply( this, arguments );
6907         
6908                         if ( ret === this ) {
6909                                 // Returned item is the API instance that was passed in, return it
6910                                 return this;
6911                         }
6912                         else if ( ret instanceof _Api ) {
6913                                 // New API instance returned, want the value from the first item
6914                                 // in the returned array for the singular result.
6915                                 return ret.length ?
6916                                         $.isArray( ret[0] ) ?
6917                                                 new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
6918                                                 ret[0] :
6919                                         undefined;
6920                         }
6921         
6922                         // Non-API return - just fire it back
6923                         return ret;
6924                 } );
6925         };
6926         
6927         
6928         /**
6929          * Selector for HTML tables. Apply the given selector to the give array of
6930          * DataTables settings objects.
6931          *
6932          * @param {string|integer} [selector] jQuery selector string or integer
6933          * @param  {array} Array of DataTables settings objects to be filtered
6934          * @return {array}
6935          * @ignore
6936          */
6937         var __table_selector = function ( selector, a )
6938         {
6939                 // Integer is used to pick out a table by index
6940                 if ( typeof selector === 'number' ) {
6941                         return [ a[ selector ] ];
6942                 }
6943         
6944                 // Perform a jQuery selector on the table nodes
6945                 var nodes = $.map( a, function (el, i) {
6946                         return el.nTable;
6947                 } );
6948         
6949                 return $(nodes)
6950                         .filter( selector )
6951                         .map( function (i) {
6952                                 // Need to translate back from the table node to the settings
6953                                 var idx = $.inArray( this, nodes );
6954                                 return a[ idx ];
6955                         } )
6956                         .toArray();
6957         };
6958         
6959         
6960         
6961         /**
6962          * Context selector for the API's context (i.e. the tables the API instance
6963          * refers to.
6964          *
6965          * @name    DataTable.Api#tables
6966          * @param {string|integer} [selector] Selector to pick which tables the iterator
6967          *   should operate on. If not given, all tables in the current context are
6968          *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
6969          *   select multiple tables or as an integer to select a single table.
6970          * @returns {DataTable.Api} Returns a new API instance if a selector is given.
6971          */
6972         _api_register( 'tables()', function ( selector ) {
6973                 // A new instance is created if there was a selector specified
6974                 return selector ?
6975                         new _Api( __table_selector( selector, this.context ) ) :
6976                         this;
6977         } );
6978         
6979         
6980         _api_register( 'table()', function ( selector ) {
6981                 var tables = this.tables( selector );
6982                 var ctx = tables.context;
6983         
6984                 // Truncate to the first matched table
6985                 return ctx.length ?
6986                         new _Api( ctx[0] ) :
6987                         tables;
6988         } );
6989         
6990         
6991         _api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
6992                 return this.iterator( 'table', function ( ctx ) {
6993                         return ctx.nTable;
6994                 } );
6995         } );
6996         
6997         
6998         _api_registerPlural( 'tables().body()', 'table().body()' , function () {
6999                 return this.iterator( 'table', function ( ctx ) {
7000                         return ctx.nTBody;
7001                 } );
7002         } );
7003         
7004         
7005         _api_registerPlural( 'tables().header()', 'table().header()' , function () {
7006                 return this.iterator( 'table', function ( ctx ) {
7007                         return ctx.nTHead;
7008                 } );
7009         } );
7010         
7011         
7012         _api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7013                 return this.iterator( 'table', function ( ctx ) {
7014                         return ctx.nTFoot;
7015                 } );
7016         } );
7017         
7018         
7019         
7020         /**
7021          * Redraw the tables in the current context.
7022          *
7023          * @param {boolean} [reset=true] Reset (default) or hold the current paging
7024          *   position. A full re-sort and re-filter is performed when this method is
7025          *   called, which is why the pagination reset is the default action.
7026          * @returns {DataTables.Api} this
7027          */
7028         _api_register( 'draw()', function ( resetPaging ) {
7029                 return this.iterator( 'table', function ( settings ) {
7030                         _fnReDraw( settings, resetPaging===false );
7031                 } );
7032         } );
7033         
7034         
7035         
7036         /**
7037          * Get the current page index.
7038          *
7039          * @return {integer} Current page index (zero based)
7040          *//**
7041          * Set the current page.
7042          *
7043          * Note that if you attempt to show a page which does not exist, DataTables will
7044          * not throw an error, but rather reset the paging.
7045          *
7046          * @param {integer|string} action The paging action to take. This can be one of:
7047          *  * `integer` - The page index to jump to
7048          *  * `string` - An action to take:
7049          *    * `first` - Jump to first page.
7050          *    * `next` - Jump to the next page
7051          *    * `previous` - Jump to previous page
7052          *    * `last` - Jump to the last page.
7053          * @returns {DataTables.Api} this
7054          */
7055         _api_register( 'page()', function ( action ) {
7056                 if ( action === undefined ) {
7057                         return this.page.info().page; // not an expensive call
7058                 }
7059         
7060                 // else, have an action to take on all tables
7061                 return this.iterator( 'table', function ( settings ) {
7062                         _fnPageChange( settings, action );
7063                 } );
7064         } );
7065         
7066         
7067         /**
7068          * Paging information for the first table in the current context.
7069          *
7070          * If you require paging information for another table, use the `table()` method
7071          * with a suitable selector.
7072          *
7073          * @return {object} Object with the following properties set:
7074          *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7075          *  * `pages` - Total number of pages
7076          *  * `start` - Display index for the first record shown on the current page
7077          *  * `end` - Display index for the last record shown on the current page
7078          *  * `length` - Display length (number of records). Note that generally `start
7079          *    + length = end`, but this is not always true, for example if there are
7080          *    only 2 records to show on the final page, with a length of 10.
7081          *  * `recordsTotal` - Full data set length
7082          *  * `recordsDisplay` - Data set length once the current filtering criterion
7083          *    are applied.
7084          */
7085         _api_register( 'page.info()', function ( action ) {
7086                 if ( this.context.length === 0 ) {
7087                         return undefined;
7088                 }
7089         
7090                 var
7091                         settings   = this.context[0],
7092                         start      = settings._iDisplayStart,
7093                         len        = settings._iDisplayLength,
7094                         visRecords = settings.fnRecordsDisplay(),
7095                         all        = len === -1;
7096         
7097                 return {
7098                         "page":           all ? 0 : Math.floor( start / len ),
7099                         "pages":          all ? 1 : Math.ceil( visRecords / len ),
7100                         "start":          start,
7101                         "end":            settings.fnDisplayEnd(),
7102                         "length":         len,
7103                         "recordsTotal":   settings.fnRecordsTotal(),
7104                         "recordsDisplay": visRecords
7105                 };
7106         } );
7107         
7108         
7109         /**
7110          * Get the current page length.
7111          *
7112          * @return {integer} Current page length. Note `-1` indicates that all records
7113          *   are to be shown.
7114          *//**
7115          * Set the current page length.
7116          *
7117          * @param {integer} Page length to set. Use `-1` to show all records.
7118          * @returns {DataTables.Api} this
7119          */
7120         _api_register( 'page.len()', function ( len ) {
7121                 // Note that we can't call this function 'length()' because `length`
7122                 // is a Javascript property of functions which defines how many arguments
7123                 // the function expects.
7124                 if ( len === undefined ) {
7125                         return this.context.length !== 0 ?
7126                                 this.context[0]._iDisplayLength :
7127                                 undefined;
7128                 }
7129         
7130                 // else, set the page length
7131                 return this.iterator( 'table', function ( settings ) {
7132                         _fnLengthChange( settings, len );
7133                 } );
7134         } );
7135         
7136         
7137         
7138         var __reload = function ( settings, holdPosition, callback ) {
7139                 if ( _fnDataSource( settings ) == 'ssp' ) {
7140                         _fnReDraw( settings, holdPosition );
7141                 }
7142                 else {
7143                         // Trigger xhr
7144                         _fnProcessingDisplay( settings, true );
7145         
7146                         _fnBuildAjax( settings, [], function( json ) {
7147                                 _fnClearTable( settings );
7148         
7149                                 var data = _fnAjaxDataSrc( settings, json );
7150                                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7151                                         _fnAddData( settings, data[i] );
7152                                 }
7153         
7154                                 _fnReDraw( settings, holdPosition );
7155                                 _fnProcessingDisplay( settings, false );
7156                         } );
7157                 }
7158         
7159                 // Use the draw event to trigger a callback, regardless of if it is an async
7160                 // or sync draw
7161                 if ( callback ) {
7162                         var api = new _Api( settings );
7163         
7164                         api.one( 'draw', function () {
7165                                 callback( api.ajax.json() );
7166                         } );
7167                 }
7168         };
7169         
7170         
7171         /**
7172          * Get the JSON response from the last Ajax request that DataTables made to the
7173          * server. Note that this returns the JSON from the first table in the current
7174          * context.
7175          *
7176          * @return {object} JSON received from the server.
7177          */
7178         _api_register( 'ajax.json()', function () {
7179                 var ctx = this.context;
7180         
7181                 if ( ctx.length > 0 ) {
7182                         return ctx[0].json;
7183                 }
7184         
7185                 // else return undefined;
7186         } );
7187         
7188         
7189         /**
7190          * Get the data submitted in the last Ajax request
7191          */
7192         _api_register( 'ajax.params()', function () {
7193                 var ctx = this.context;
7194         
7195                 if ( ctx.length > 0 ) {
7196                         return ctx[0].oAjaxData;
7197                 }
7198         
7199                 // else return undefined;
7200         } );
7201         
7202         
7203         /**
7204          * Reload tables from the Ajax data source. Note that this function will
7205          * automatically re-draw the table when the remote data has been loaded.
7206          *
7207          * @param {boolean} [reset=true] Reset (default) or hold the current paging
7208          *   position. A full re-sort and re-filter is performed when this method is
7209          *   called, which is why the pagination reset is the default action.
7210          * @returns {DataTables.Api} this
7211          */
7212         _api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7213                 return this.iterator( 'table', function (settings) {
7214                         __reload( settings, resetPaging===false, callback );
7215                 } );
7216         } );
7217         
7218         
7219         /**
7220          * Get the current Ajax URL. Note that this returns the URL from the first
7221          * table in the current context.
7222          *
7223          * @return {string} Current Ajax source URL
7224          *//**
7225          * Set the Ajax URL. Note that this will set the URL for all tables in the
7226          * current context.
7227          *
7228          * @param {string} url URL to set.
7229          * @returns {DataTables.Api} this
7230          */
7231         _api_register( 'ajax.url()', function ( url ) {
7232                 var ctx = this.context;
7233         
7234                 if ( url === undefined ) {
7235                         // get
7236                         if ( ctx.length === 0 ) {
7237                                 return undefined;
7238                         }
7239                         ctx = ctx[0];
7240         
7241                         return ctx.ajax ?
7242                                 $.isPlainObject( ctx.ajax ) ?
7243                                         ctx.ajax.url :
7244                                         ctx.ajax :
7245                                 ctx.sAjaxSource;
7246                 }
7247         
7248                 // set
7249                 return this.iterator( 'table', function ( settings ) {
7250                         if ( $.isPlainObject( settings.ajax ) ) {
7251                                 settings.ajax.url = url;
7252                         }
7253                         else {
7254                                 settings.ajax = url;
7255                         }
7256                         // No need to consider sAjaxSource here since DataTables gives priority
7257                         // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7258                         // value of `sAjaxSource` redundant.
7259                 } );
7260         } );
7261         
7262         
7263         /**
7264          * Load data from the newly set Ajax URL. Note that this method is only
7265          * available when `ajax.url()` is used to set a URL. Additionally, this method
7266          * has the same effect as calling `ajax.reload()` but is provided for
7267          * convenience when setting a new URL. Like `ajax.reload()` it will
7268          * automatically redraw the table once the remote data has been loaded.
7269          *
7270          * @returns {DataTables.Api} this
7271          */
7272         _api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7273                 // Same as a reload, but makes sense to present it for easy access after a
7274                 // url change
7275                 return this.iterator( 'table', function ( ctx ) {
7276                         __reload( ctx, resetPaging===false, callback );
7277                 } );
7278         } );
7279         
7280         
7281         
7282         
7283         var _selector_run = function ( selector, select )
7284         {
7285                 var
7286                         out = [], res,
7287                         a, i, ien, j, jen;
7288         
7289                 // Can't just check for isArray here, as an API or jQuery instance might be
7290                 // given with their array like look
7291                 if ( ! selector || typeof selector === 'string' || selector.length === undefined ) {
7292                         selector = [ selector ];
7293                 }
7294         
7295                 for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7296                         a = selector[i] && selector[i].split ?
7297                                 selector[i].split(',') :
7298                                 [ selector[i] ];
7299         
7300                         for ( j=0, jen=a.length ; j<jen ; j++ ) {
7301                                 res = select( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
7302         
7303                                 if ( res && res.length ) {
7304                                         out.push.apply( out, res );
7305                                 }
7306                         }
7307                 }
7308         
7309                 return out;
7310         };
7311         
7312         
7313         var _selector_opts = function ( opts )
7314         {
7315                 if ( ! opts ) {
7316                         opts = {};
7317                 }
7318         
7319                 // Backwards compatibility for 1.9- which used the terminology filter rather
7320                 // than search
7321                 if ( opts.filter && ! opts.search ) {
7322                         opts.search = opts.filter;
7323                 }
7324         
7325                 return {
7326                         search: opts.search || 'none',
7327                         order:  opts.order  || 'current',
7328                         page:   opts.page   || 'all'
7329                 };
7330         };
7331         
7332         
7333         var _selector_first = function ( inst )
7334         {
7335                 // Reduce the API instance to the first item found
7336                 for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7337                         if ( inst[i].length > 0 ) {
7338                                 // Assign the first element to the first item in the instance
7339                                 // and truncate the instance and context
7340                                 inst[0] = inst[i];
7341                                 inst.length = 1;
7342                                 inst.context = [ inst.context[i] ];
7343         
7344                                 return inst;
7345                         }
7346                 }
7347         
7348                 // Not found - return an empty instance
7349                 inst.length = 0;
7350                 return inst;
7351         };
7352         
7353         
7354         var _selector_row_indexes = function ( settings, opts )
7355         {
7356                 var
7357                         i, ien, tmp, a=[],
7358                         displayFiltered = settings.aiDisplay,
7359                         displayMaster = settings.aiDisplayMaster;
7360         
7361                 var
7362                         search = opts.search,  // none, applied, removed
7363                         order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7364                         page   = opts.page;    // all, current
7365         
7366                 if ( _fnDataSource( settings ) == 'ssp' ) {
7367                         // In server-side processing mode, most options are irrelevant since
7368                         // rows not shown don't exist and the index order is the applied order
7369                         // Removed is a special case - for consistency just return an empty
7370                         // array
7371                         return search === 'removed' ?
7372                                 [] :
7373                                 _range( 0, displayMaster.length );
7374                 }
7375                 else if ( page == 'current' ) {
7376                         // Current page implies that order=current and fitler=applied, since it is
7377                         // fairly senseless otherwise, regardless of what order and search actually
7378                         // are
7379                         for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7380                                 a.push( displayFiltered[i] );
7381                         }
7382                 }
7383                 else if ( order == 'current' || order == 'applied' ) {
7384                         a = search == 'none' ?
7385                                 displayMaster.slice() :                      // no search
7386                                 search == 'applied' ?
7387                                         displayFiltered.slice() :                // applied search
7388                                         $.map( displayMaster, function (el, i) { // removed search
7389                                                 return $.inArray( el, displayFiltered ) === -1 ? el : null;
7390                                         } );
7391                 }
7392                 else if ( order == 'index' || order == 'original' ) {
7393                         for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7394                                 if ( search == 'none' ) {
7395                                         a.push( i );
7396                                 }
7397                                 else { // applied | removed
7398                                         tmp = $.inArray( i, displayFiltered );
7399         
7400                                         if ((tmp === -1 && search == 'removed') ||
7401                                                 (tmp === 1  && search == 'applied') )
7402                                         {
7403                                                 a.push( i );
7404                                         }
7405                                 }
7406                         }
7407                 }
7408         
7409                 return a;
7410         };
7411         
7412         
7413         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7414          * Rows
7415          *
7416          * {}          - no selector - use all available rows
7417          * {integer}   - row aoData index
7418          * {node}      - TR node
7419          * {string}    - jQuery selector to apply to the TR elements
7420          * {array}     - jQuery array of nodes, or simply an array of TR nodes
7421          *
7422          */
7423         
7424         
7425         var __row_selector = function ( settings, selector, opts )
7426         {
7427                 return _selector_run( selector, function ( sel ) {
7428                         var selInt = _intVal( sel );
7429         
7430                         // Short cut - selector is a number and no options provided (default is
7431                         // all records, so no need to check if the index is in there, since it
7432                         // must be - dev error if the index doesn't exist).
7433                         if ( selInt !== null && ! opts ) {
7434                                 return [ selInt ];
7435                         }
7436         
7437                         var rows = _selector_row_indexes( settings, opts );
7438         
7439                         if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7440                                 // Selector - integer
7441                                 return [ selInt ];
7442                         }
7443                         else if ( ! sel ) {
7444                                 // Selector - none
7445                                 return rows;
7446                         }
7447         
7448                         // Get nodes in the order from the `rows` array (can't use `pluck`) @todo - use pluck_order
7449                         var nodes = [];
7450                         for ( var i=0, ien=rows.length ; i<ien ; i++ ) {
7451                                 nodes.push( settings.aoData[ rows[i] ].nTr );
7452                         }
7453         
7454                         if ( sel.nodeName ) {
7455                                 // Selector - node
7456                                 if ( $.inArray( sel, nodes ) !== -1 ) {
7457                                         return [ sel._DT_RowIndex ];// sel is a TR node that is in the table
7458                                                                                         // and DataTables adds a prop for fast lookup
7459                                 }
7460                         }
7461         
7462                         // Selector - jQuery selector string, array of nodes or jQuery object/
7463                         // As jQuery's .filter() allows jQuery objects to be passed in filter,
7464                         // it also allows arrays, so this will cope with all three options
7465                         return $(nodes)
7466                                 .filter( sel )
7467                                 .map( function () {
7468                                         return this._DT_RowIndex;
7469                                 } )
7470                                 .toArray();
7471                 } );
7472         };
7473         
7474         
7475         /**
7476          *
7477          */
7478         _api_register( 'rows()', function ( selector, opts ) {
7479                 // argument shifting
7480                 if ( selector === undefined ) {
7481                         selector = '';
7482                 }
7483                 else if ( $.isPlainObject( selector ) ) {
7484                         opts = selector;
7485                         selector = '';
7486                 }
7487         
7488                 opts = _selector_opts( opts );
7489         
7490                 var inst = this.iterator( 'table', function ( settings ) {
7491                         return __row_selector( settings, selector, opts );
7492                 } );
7493         
7494                 // Want argument shifting here and in __row_selector?
7495                 inst.selector.rows = selector;
7496                 inst.selector.opts = opts;
7497         
7498                 return inst;
7499         } );
7500         
7501         
7502         _api_register( 'rows().nodes()', function () {
7503                 return this.iterator( 'row', function ( settings, row ) {
7504                         return settings.aoData[ row ].nTr || undefined;
7505                 } );
7506         } );
7507         
7508         _api_register( 'rows().data()', function () {
7509                 return this.iterator( true, 'rows', function ( settings, rows ) {
7510                         return _pluck_order( settings.aoData, rows, '_aData' );
7511                 } );
7512         } );
7513         
7514         _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
7515                 return this.iterator( 'row', function ( settings, row ) {
7516                         var r = settings.aoData[ row ];
7517                         return type === 'search' ? r._aFilterData : r._aSortData;
7518                 } );
7519         } );
7520         
7521         _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
7522                 return this.iterator( 'row', function ( settings, row ) {
7523                         _fnInvalidateRow( settings, row, src );
7524                 } );
7525         } );
7526         
7527         _api_registerPlural( 'rows().indexes()', 'row().index()', function () {
7528                 return this.iterator( 'row', function ( settings, row ) {
7529                         return row;
7530                 } );
7531         } );
7532         
7533         _api_registerPlural( 'rows().remove()', 'row().remove()', function () {
7534                 var that = this;
7535         
7536                 return this.iterator( 'row', function ( settings, row, thatIdx ) {
7537                         var data = settings.aoData;
7538         
7539                         data.splice( row, 1 );
7540         
7541                         // Update the _DT_RowIndex parameter on all rows in the table
7542                         for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7543                                 if ( data[i].nTr !== null ) {
7544                                         data[i].nTr._DT_RowIndex = i;
7545                                 }
7546                         }
7547         
7548                         // Remove the target row from the search array
7549                         var displayIndex = $.inArray( row, settings.aiDisplay );
7550         
7551                         // Delete from the display arrays
7552                         _fnDeleteIndex( settings.aiDisplayMaster, row );
7553                         _fnDeleteIndex( settings.aiDisplay, row );
7554                         _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
7555         
7556                         // Check for an 'overflow' they case for displaying the table
7557                         _fnLengthOverflow( settings );
7558                 } );
7559         } );
7560         
7561         
7562         _api_register( 'rows.add()', function ( rows ) {
7563                 var newRows = this.iterator( 'table', function ( settings ) {
7564                                 var row, i, ien;
7565                                 var out = [];
7566         
7567                                 for ( i=0, ien=rows.length ; i<ien ; i++ ) {
7568                                         row = rows[i];
7569         
7570                                         if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
7571                                                 out.push( _fnAddTr( settings, row )[0] );
7572                                         }
7573                                         else {
7574                                                 out.push( _fnAddData( settings, row ) );
7575                                         }
7576                                 }
7577         
7578                                 return out;
7579                         } );
7580         
7581                 // Return an Api.rows() extended instance, so rows().nodes() etc can be used
7582                 var modRows = this.rows( -1 );
7583                 modRows.pop();
7584                 modRows.push.apply( modRows, newRows.toArray() );
7585         
7586                 return modRows;
7587         } );
7588         
7589         
7590         
7591         
7592         
7593         /**
7594          *
7595          */
7596         _api_register( 'row()', function ( selector, opts ) {
7597                 return _selector_first( this.rows( selector, opts ) );
7598         } );
7599         
7600         
7601         _api_register( 'row().data()', function ( data ) {
7602                 var ctx = this.context;
7603         
7604                 if ( data === undefined ) {
7605                         // Get
7606                         return ctx.length && this.length ?
7607                                 ctx[0].aoData[ this[0] ]._aData :
7608                                 undefined;
7609                 }
7610         
7611                 // Set
7612                 ctx[0].aoData[ this[0] ]._aData = data;
7613         
7614                 // Automatically invalidate
7615                 _fnInvalidateRow( ctx[0], this[0], 'data' );
7616         
7617                 return this;
7618         } );
7619         
7620         
7621         _api_register( 'row().node()', function () {
7622                 var ctx = this.context;
7623         
7624                 return ctx.length && this.length ?
7625                         ctx[0].aoData[ this[0] ].nTr || null :
7626                         null;
7627         } );
7628         
7629         
7630         _api_register( 'row.add()', function ( row ) {
7631                 // Allow a jQuery object to be passed in - only a single row is added from
7632                 // it though - the first element in the set
7633                 if ( row instanceof $ && row.length ) {
7634                         row = row[0];
7635                 }
7636         
7637                 var rows = this.iterator( 'table', function ( settings ) {
7638                         if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
7639                                 return _fnAddTr( settings, row )[0];
7640                         }
7641                         return _fnAddData( settings, row );
7642                 } );
7643         
7644                 // Return an Api.rows() extended instance, with the newly added row selected
7645                 return this.row( rows[0] );
7646         } );
7647         
7648         
7649         
7650         var __details_add = function ( ctx, row, data, klass )
7651         {
7652                 // Convert to array of TR elements
7653                 var rows = [];
7654                 var addRow = function ( r, k ) {
7655                         // If we get a TR element, then just add it directly - up to the dev
7656                         // to add the correct number of columns etc
7657                         if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
7658                                 rows.push( r );
7659                         }
7660                         else {
7661                                 // Otherwise create a row with a wrapper
7662                                 var created = $('<tr><td/></tr>');
7663                                 $('td', created)
7664                                         .addClass( k )
7665                                         .html( r )
7666                                         [0].colSpan = _fnVisbleColumns( ctx );
7667         
7668                                 rows.push( created[0] );
7669                         }
7670                 };
7671         
7672                 if ( $.isArray( data ) || data instanceof $ ) {
7673                         for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7674                                 addRow( data[i], klass );
7675                         }
7676                 }
7677                 else {
7678                         addRow( data, klass );
7679                 }
7680         
7681                 if ( row._details ) {
7682                         row._details.remove();
7683                 }
7684         
7685                 row._details = $(rows);
7686         
7687                 // If the children were already shown, that state should be retained
7688                 if ( row._detailsShow ) {
7689                         row._details.insertAfter( row.nTr );
7690                 }
7691         };
7692         
7693         
7694         var __details_display = function ( show ) {
7695                 var ctx = this.context;
7696         
7697                 if ( ctx.length && this.length ) {
7698                         var row = ctx[0].aoData[ this[0] ];
7699         
7700                         if ( row._details ) {
7701                                 row._detailsShow = show;
7702                                 if ( show ) {
7703                                         row._details.insertAfter( row.nTr );
7704                                 }
7705                                 else {
7706                                         row._details.remove();
7707                                 }
7708         
7709                                 __details_events( ctx[0] );
7710                         }
7711                 }
7712         
7713                 return this;
7714         };
7715         
7716         
7717         var __details_events = function ( settings )
7718         {
7719                 var api = new _Api( settings );
7720                 var namespace = '.dt.DT_details';
7721                 var drawEvent = 'draw'+namespace;
7722                 var colvisEvent = 'column-visibility'+namespace;
7723         
7724                 api.off( drawEvent +' '+ colvisEvent );
7725         
7726                 if ( _pluck( settings.aoData, '_details' ).length > 0 ) {
7727                         // On each draw, insert the required elements into the document
7728                         api.on( drawEvent, function () {
7729                                 api.rows( {page:'current'} ).eq(0).each( function (idx) {
7730                                         // Internal data grab
7731                                         var row = settings.aoData[ idx ];
7732         
7733                                         if ( row._detailsShow ) {
7734                                                 row._details.insertAfter( row.nTr );
7735                                         }
7736                                 } );
7737                         } );
7738         
7739                         // Column visibility change - update the colspan
7740                         api.on( colvisEvent, function ( e, settings, idx, vis ) {
7741                                 // Update the colspan for the details rows (note, only if it already has
7742                                 // a colspan)
7743                                 var row, visible = _fnVisbleColumns( settings );
7744         
7745                                 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7746                                         row = settings.aoData[i];
7747         
7748                                         if ( row._details ) {
7749                                                 row._details.children('td[colspan]').attr('colspan', visible );
7750                                         }
7751                                 }
7752                         } );
7753                 }
7754         };
7755         
7756         // data can be:
7757         //  tr
7758         //  string
7759         //  jQuery or array of any of the above
7760         _api_register( 'row().child()', function ( data, klass ) {
7761                 var ctx = this.context;
7762         
7763                 if ( data === undefined ) {
7764                         // get
7765                         return ctx.length && this.length ?
7766                                 ctx[0].aoData[ this[0] ]._details :
7767                                 undefined;
7768                 }
7769                 else if ( ctx.length && this.length ) {
7770                         // set
7771                         __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
7772                 }
7773         
7774                 return this;
7775         } );
7776         
7777         _api_register( [
7778                 'row().child.show()',
7779                 'row().child().show()'
7780         ], function () {
7781                 __details_display.call( this, true );
7782                 return this;
7783         } );
7784         
7785         _api_register( [
7786                 'row().child.hide()',
7787                 'row().child().hide()'
7788         ], function () {
7789                 __details_display.call( this, false );
7790                 return this;
7791         } );
7792         
7793         _api_register( 'row().child.isShown()', function () {
7794                 var ctx = this.context;
7795         
7796                 if ( ctx.length && this.length ) {
7797                         // _detailsShown as false or undefined will fall through to return false
7798                         return ctx[0].aoData[ this[0] ]._detailsShow || false;
7799                 }
7800                 return false;
7801         } );
7802         
7803         
7804         
7805         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7806          * Columns
7807          *
7808          * {integer}           - column index (>=0 count from left, <0 count from right)
7809          * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
7810          * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
7811          * "{string}:name"     - column name
7812          * "{string}"          - jQuery selector on column header nodes
7813          *
7814          */
7815         
7816         // can be an array of these items, comma separated list, or an array of comma
7817         // separated lists
7818         
7819         var __re_column_selector = /^(.*):(name|visIdx|visible)$/;
7820         
7821         var __column_selector = function ( settings, selector, opts )
7822         {
7823                 var
7824                         columns = settings.aoColumns,
7825                         names = _pluck( columns, 'sName' ),
7826                         nodes = _pluck( columns, 'nTh' );
7827         
7828                 return _selector_run( selector, function ( s ) {
7829                         var selInt = _intVal( s );
7830         
7831                         if ( s === '' ) {
7832                                 // All columns
7833                                 return _range( columns.length );
7834                         }
7835                         else if ( selInt !== null ) {
7836                                 // Integer selector
7837                                 return [ selInt >= 0 ?
7838                                         selInt : // Count from left
7839                                         columns.length + selInt // Count from right (+ because its a negative value)
7840                                 ];
7841                         }
7842                         else {
7843                                 var match = typeof s === 'string' ?
7844                                         s.match( __re_column_selector ) :
7845                                         '';
7846         
7847                                 if ( match ) {
7848                                         switch( match[2] ) {
7849                                                 case 'visIdx':
7850                                                 case 'visible':
7851                                                         var idx = parseInt( match[1], 10 );
7852                                                         // Visible index given, convert to column index
7853                                                         if ( idx < 0 ) {
7854                                                                 // Counting from the right
7855                                                                 var visColumns = $.map( columns, function (col,i) {
7856                                                                         return col.bVisible ? i : null;
7857                                                                 } );
7858                                                                 return [ visColumns[ visColumns.length + idx ] ];
7859                                                         }
7860                                                         // Counting from the left
7861                                                         return [ _fnVisibleToColumnIndex( settings, idx ) ];
7862         
7863                                                 case 'name':
7864                                                         // match by name. `names` is column index complete and in order
7865                                                         return $.map( names, function (name, i) {
7866                                                                 return name === match[1] ? i : null;
7867                                                         } );
7868                                         }
7869                                 }
7870                                 else {
7871                                         // jQuery selector on the TH elements for the columns
7872                                         return $( nodes )
7873                                                 .filter( s )
7874                                                 .map( function () {
7875                                                         return $.inArray( this, nodes ); // `nodes` is column index complete and in order
7876                                                 } )
7877                                                 .toArray();
7878                                 }
7879                         }
7880                 } );
7881         };
7882         
7883         
7884         
7885         
7886         
7887         var __setColumnVis = function ( settings, column, vis ) {
7888                 var
7889                         cols = settings.aoColumns,
7890                         col  = cols[ column ],
7891                         data = settings.aoData,
7892                         row, cells, i, ien, tr;
7893         
7894                 // Get
7895                 if ( vis === undefined ) {
7896                         return col.bVisible;
7897                 }
7898         
7899                 // Set
7900                 // No change
7901                 if ( col.bVisible === vis ) {
7902                         return;
7903                 }
7904         
7905                 if ( vis ) {
7906                         // Insert column
7907                         // Need to decide if we should use appendChild or insertBefore
7908                         var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
7909         
7910                         for ( i=0, ien=data.length ; i<ien ; i++ ) {
7911                                 tr = data[i].nTr;
7912                                 cells = data[i].anCells;
7913         
7914                                 if ( tr ) {
7915                                         // insertBefore can act like appendChild if 2nd arg is null
7916                                         tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
7917                                 }
7918                         }
7919                 }
7920                 else {
7921                         // Remove column
7922                         $( _pluck( settings.aoData, 'anCells', column ) ).detach();
7923         
7924                         col.bVisible = false;
7925                         _fnDrawHead( settings, settings.aoHeader );
7926                         _fnDrawHead( settings, settings.aoFooter );
7927         
7928                         _fnSaveState( settings );
7929                 }
7930         
7931                 // Common actions
7932                 col.bVisible = vis;
7933                 _fnDrawHead( settings, settings.aoHeader );
7934                 _fnDrawHead( settings, settings.aoFooter );
7935         
7936                 // Automatically adjust column sizing
7937                 _fnAdjustColumnSizing( settings );
7938         
7939                 // Realign columns for scrolling
7940                 if ( settings.oScroll.sX || settings.oScroll.sY ) {
7941                         _fnScrollDraw( settings );
7942                 }
7943         
7944                 _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis] );
7945         
7946                 _fnSaveState( settings );
7947         };
7948         
7949         
7950         /**
7951          *
7952          */
7953         _api_register( 'columns()', function ( selector, opts ) {
7954                 // argument shifting
7955                 if ( selector === undefined ) {
7956                         selector = '';
7957                 }
7958                 else if ( $.isPlainObject( selector ) ) {
7959                         opts = selector;
7960                         selector = '';
7961                 }
7962         
7963                 opts = _selector_opts( opts );
7964         
7965                 var inst = this.iterator( 'table', function ( settings ) {
7966                         return __column_selector( settings, selector, opts );
7967                 } );
7968         
7969                 // Want argument shifting here and in _row_selector?
7970                 inst.selector.cols = selector;
7971                 inst.selector.opts = opts;
7972         
7973                 return inst;
7974         } );
7975         
7976         
7977         /**
7978          *
7979          */
7980         _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
7981                 return this.iterator( 'column', function ( settings, column ) {
7982                         return settings.aoColumns[column].nTh;
7983                 } );
7984         } );
7985         
7986         
7987         /**
7988          *
7989          */
7990         _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
7991                 return this.iterator( 'column', function ( settings, column ) {
7992                         return settings.aoColumns[column].nTf;
7993                 } );
7994         } );
7995         
7996         
7997         /**
7998          *
7999          */
8000         _api_registerPlural( 'columns().data()', 'column().data()', function () {
8001                 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8002                         var a = [];
8003                         for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8004                                 a.push( _fnGetCellData( settings, rows[row], column, '' ) );
8005                         }
8006                         return a;
8007                 } );
8008         } );
8009         
8010         
8011         _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8012                 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8013                         return _pluck_order( settings.aoData, rows,
8014                                 type === 'search' ? '_aFilterData' : '_aSortData', column
8015                         );
8016                 } );
8017         } );
8018         
8019         
8020         _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8021                 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8022                         return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8023                 } );
8024         } );
8025         
8026         
8027         
8028         _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis ) {
8029                 return this.iterator( 'column', function ( settings, column ) {
8030                         return vis === undefined ?
8031                                 settings.aoColumns[ column ].bVisible :
8032                                 __setColumnVis( settings, column, vis );
8033                 } );
8034         } );
8035         
8036         
8037         
8038         _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8039                 return this.iterator( 'column', function ( settings, column ) {
8040                         return type === 'visible' ?
8041                                 _fnColumnIndexToVisible( settings, column ) :
8042                                 column;
8043                 } );
8044         } );
8045         
8046         
8047         // _api_register( 'columns().show()', function () {
8048         //      var selector = this.selector;
8049         //      return this.columns( selector.cols, selector.opts ).visible( true );
8050         // } );
8051         
8052         
8053         // _api_register( 'columns().hide()', function () {
8054         //      var selector = this.selector;
8055         //      return this.columns( selector.cols, selector.opts ).visible( false );
8056         // } );
8057         
8058         
8059         
8060         _api_register( 'columns.adjust()', function () {
8061                 return this.iterator( 'table', function ( settings ) {
8062                         _fnAdjustColumnSizing( settings );
8063                 } );
8064         } );
8065         
8066         
8067         // Convert from one column index type, to another type
8068         _api_register( 'column.index()', function ( type, idx ) {
8069                 if ( this.context.length !== 0 ) {
8070                         var ctx = this.context[0];
8071         
8072                         if ( type === 'fromVisible' || type === 'toData' ) {
8073                                 return _fnVisibleToColumnIndex( ctx, idx );
8074                         }
8075                         else if ( type === 'fromData' || type === 'toVisible' ) {
8076                                 return _fnColumnIndexToVisible( ctx, idx );
8077                         }
8078                 }
8079         } );
8080         
8081         
8082         _api_register( 'column()', function ( selector, opts ) {
8083                 return _selector_first( this.columns( selector, opts ) );
8084         } );
8085         
8086         
8087         
8088         
8089         var __cell_selector = function ( settings, selector, opts )
8090         {
8091                 var data = settings.aoData;
8092                 var rows = _selector_row_indexes( settings, opts );
8093                 var cells = _pluck_order( data, rows, 'anCells' );
8094                 var allCells = $( [].concat.apply([], cells) );
8095                 var row;
8096                 var columns = settings.aoColumns.length;
8097                 var a, i, ien, j;
8098         
8099                 return _selector_run( selector, function ( s ) {
8100                         if ( ! s ) {
8101                                 // All cells
8102                                 a = [];
8103         
8104                                 for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8105                                         row = rows[i];
8106         
8107                                         for ( j=0 ; j<columns ; j++ ) {
8108                                                 a.push( {
8109                                                         row: row,
8110                                                         column: j
8111                                                 } );
8112                                         }
8113                                 }
8114         
8115                                 return a;
8116                         }
8117                         else if ( $.isPlainObject( s ) ) {
8118                                 return [s];
8119                         }
8120         
8121                         // jQuery filtered cells
8122                         return allCells
8123                                 .filter( s )
8124                                 .map( function (i, el) {
8125                                         row = el.parentNode._DT_RowIndex;
8126         
8127                                         return {
8128                                                 row: row,
8129                                                 column: $.inArray( el, data[ row ].anCells )
8130                                         };
8131                                 } )
8132                                 .toArray();
8133                 } );
8134         };
8135         
8136         
8137         
8138         
8139         _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8140                 // Argument shifting
8141                 if ( $.isPlainObject( rowSelector ) ) {
8142                         // If passing in a cell index
8143                         if ( rowSelector.row ) {
8144                                 opts = columnSelector;
8145                                 columnSelector = null;
8146                         }
8147                         else {
8148                                 opts = rowSelector;
8149                                 rowSelector = null;
8150                         }
8151                 }
8152                 if ( $.isPlainObject( columnSelector ) ) {
8153                         opts = columnSelector;
8154                         columnSelector = null;
8155                 }
8156         
8157                 // Cell selector
8158                 if ( columnSelector === null || columnSelector === undefined ) {
8159                         return this.iterator( 'table', function ( settings ) {
8160                                 return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8161                         } );
8162                 }
8163         
8164                 // Row + column selector
8165                 var columns = this.columns( columnSelector, opts );
8166                 var rows = this.rows( rowSelector, opts );
8167                 var a, i, ien, j, jen;
8168         
8169                 var cells = this.iterator( 'table', function ( settings, idx ) {
8170                         a = [];
8171         
8172                         for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
8173                                 for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
8174                                         a.push( {
8175                                                 row:    rows[idx][i],
8176                                                 column: columns[idx][j]
8177                                         } );
8178                                 }
8179                         }
8180         
8181                         return a;
8182                 } );
8183         
8184                 $.extend( cells.selector, {
8185                         cols: columnSelector,
8186                         rows: rowSelector,
8187                         opts: opts
8188                 } );
8189         
8190                 return cells;
8191         } );
8192         
8193         
8194         _api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8195                 return this.iterator( 'cell', function ( settings, row, column ) {
8196                         return settings.aoData[ row ].anCells[ column ];
8197                 } );
8198         } );
8199         
8200         
8201         _api_register( 'cells().data()', function () {
8202                 return this.iterator( 'cell', function ( settings, row, column ) {
8203                         return _fnGetCellData( settings, row, column );
8204                 } );
8205         } );
8206         
8207         
8208         _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8209                 type = type === 'search' ? '_aFilterData' : '_aSortData';
8210         
8211                 return this.iterator( 'cell', function ( settings, row, column ) {
8212                         return settings.aoData[ row ][ type ][ column ];
8213                 } );
8214         } );
8215         
8216         
8217         _api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8218                 return this.iterator( 'cell', function ( settings, row, column ) {
8219                         return {
8220                                 row: row,
8221                                 column: column,
8222                                 columnVisible: _fnColumnIndexToVisible( settings, column )
8223                         };
8224                 } );
8225         } );
8226         
8227         
8228         _api_register( [
8229                 'cells().invalidate()',
8230                 'cell().invalidate()'
8231         ], function ( src ) {
8232                 var selector = this.selector;
8233         
8234                 // Use the rows method of the instance to perform the invalidation, rather
8235                 // than doing it here. This avoids needing to handle duplicate rows from
8236                 // the cells.
8237                 this.rows( selector.rows, selector.opts ).invalidate( src );
8238         
8239                 return this;
8240         } );
8241         
8242         
8243         
8244         
8245         _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8246                 return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8247         } );
8248         
8249         
8250         
8251         _api_register( 'cell().data()', function ( data ) {
8252                 var ctx = this.context;
8253                 var cell = this[0];
8254         
8255                 if ( data === undefined ) {
8256                         // Get
8257                         return ctx.length && cell.length ?
8258                                 _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8259                                 undefined;
8260                 }
8261         
8262                 // Set
8263                 _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8264                 _fnInvalidateRow( ctx[0], cell[0].row, 'data', cell[0].column );
8265         
8266                 return this;
8267         } );
8268         
8269         
8270         
8271         /**
8272          * Get current ordering (sorting) that has been applied to the table.
8273          *
8274          * @returns {array} 2D array containing the sorting information for the first
8275          *   table in the current context. Each element in the parent array represents
8276          *   a column being sorted upon (i.e. multi-sorting with two columns would have
8277          *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8278          *   the column index that the sorting condition applies to, the second is the
8279          *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8280          *   index of the sorting order from the `column.sorting` initialisation array.
8281          *//**
8282          * Set the ordering for the table.
8283          *
8284          * @param {integer} order Column index to sort upon.
8285          * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8286          * @returns {DataTables.Api} this
8287          *//**
8288          * Set the ordering for the table.
8289          *
8290          * @param {array} order 1D array of sorting information to be applied.
8291          * @param {array} [...] Optional additional sorting conditions
8292          * @returns {DataTables.Api} this
8293          *//**
8294          * Set the ordering for the table.
8295          *
8296          * @param {array} order 2D array of sorting information to be applied.
8297          * @returns {DataTables.Api} this
8298          */
8299         _api_register( 'order()', function ( order, dir ) {
8300                 var ctx = this.context;
8301         
8302                 if ( order === undefined ) {
8303                         // get
8304                         return ctx.length !== 0 ?
8305                                 ctx[0].aaSorting :
8306                                 undefined;
8307                 }
8308         
8309                 // set
8310                 if ( typeof order === 'number' ) {
8311                         // Simple column / direction passed in
8312                         order = [ [ order, dir ] ];
8313                 }
8314                 else if ( ! $.isArray( order[0] ) ) {
8315                         // Arguments passed in (list of 1D arrays)
8316                         order = Array.prototype.slice.call( arguments );
8317                 }
8318                 // otherwise a 2D array was passed in
8319         
8320                 return this.iterator( 'table', function ( settings ) {
8321                         settings.aaSorting = order.slice();
8322                 } );
8323         } );
8324         
8325         
8326         /**
8327          * Attach a sort listener to an element for a given column
8328          *
8329          * @param {node|jQuery|string} node Identifier for the element(s) to attach the
8330          *   listener to. This can take the form of a single DOM node, a jQuery
8331          *   collection of nodes or a jQuery selector which will identify the node(s).
8332          * @param {integer} column the column that a click on this node will sort on
8333          * @param {function} [callback] callback function when sort is run
8334          * @returns {DataTables.Api} this
8335          */
8336         _api_register( 'order.listener()', function ( node, column, callback ) {
8337                 return this.iterator( 'table', function ( settings ) {
8338                         _fnSortAttachListener( settings, node, column, callback );
8339                 } );
8340         } );
8341         
8342         
8343         // Order by the selected column(s)
8344         _api_register( [
8345                 'columns().order()',
8346                 'column().order()'
8347         ], function ( dir ) {
8348                 var that = this;
8349         
8350                 return this.iterator( 'table', function ( settings, i ) {
8351                         var sort = [];
8352         
8353                         $.each( that[i], function (j, col) {
8354                                 sort.push( [ col, dir ] );
8355                         } );
8356         
8357                         settings.aaSorting = sort;
8358                 } );
8359         } );
8360         
8361         
8362         
8363         _api_register( 'search()', function ( input, regex, smart, caseInsen ) {
8364                 var ctx = this.context;
8365         
8366                 if ( input === undefined ) {
8367                         // get
8368                         return ctx.length !== 0 ?
8369                                 ctx[0].oPreviousSearch.sSearch :
8370                                 undefined;
8371                 }
8372         
8373                 // set
8374                 return this.iterator( 'table', function ( settings ) {
8375                         if ( ! settings.oFeatures.bFilter ) {
8376                                 return;
8377                         }
8378         
8379                         _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
8380                                 "sSearch": input+"",
8381                                 "bRegex":  regex === null ? false : regex,
8382                                 "bSmart":  smart === null ? true  : smart,
8383                                 "bCaseInsensitive": caseInsen === null ? true : caseInsen
8384                         } ), 1 );
8385                 } );
8386         } );
8387         
8388         
8389         _api_register( [
8390                 'columns().search()',
8391                 'column().search()'
8392         ], function ( input, regex, smart, caseInsen ) {
8393                 return this.iterator( 'column', function ( settings, column ) {
8394                         var preSearch = settings.aoPreSearchCols;
8395         
8396                         if ( input === undefined ) {
8397                                 // get
8398                                 return preSearch[ column ].sSearch;
8399                         }
8400         
8401                         // set
8402                         if ( ! settings.oFeatures.bFilter ) {
8403                                 return;
8404                         }
8405         
8406                         $.extend( preSearch[ column ], {
8407                                 "sSearch": input+"",
8408                                 "bRegex":  regex === null ? false : regex,
8409                                 "bSmart":  smart === null ? true  : smart,
8410                                 "bCaseInsensitive": caseInsen === null ? true : caseInsen
8411                         } );
8412         
8413                         _fnFilterComplete( settings, settings.oPreviousSearch, 1 );
8414                 } );
8415         } );
8416         
8417         
8418         
8419         /**
8420          * Provide a common method for plug-ins to check the version of DataTables being
8421          * used, in order to ensure compatibility.
8422          *
8423          *  @param {string} version Version string to check for, in the format "X.Y.Z".
8424          *    Note that the formats "X" and "X.Y" are also acceptable.
8425          *  @returns {boolean} true if this version of DataTables is greater or equal to
8426          *    the required version, or false if this version of DataTales is not
8427          *    suitable
8428          *  @static
8429          *  @dtopt API-Static
8430          *
8431          *  @example
8432          *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
8433          */
8434         DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
8435         {
8436                 var aThis = DataTable.version.split('.');
8437                 var aThat = version.split('.');
8438                 var iThis, iThat;
8439         
8440                 for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
8441                         iThis = parseInt( aThis[i], 10 ) || 0;
8442                         iThat = parseInt( aThat[i], 10 ) || 0;
8443         
8444                         // Parts are the same, keep comparing
8445                         if (iThis === iThat) {
8446                                 continue;
8447                         }
8448         
8449                         // Parts are different, return immediately
8450                         return iThis > iThat;
8451                 }
8452         
8453                 return true;
8454         };
8455         
8456         
8457         /**
8458          * Check if a `<table>` node is a DataTable table already or not.
8459          *
8460          *  @param {node|jquery|string} table Table node, jQuery object or jQuery
8461          *      selector for the table to test. Note that if more than more than one
8462          *      table is passed on, only the first will be checked
8463          *  @returns {boolean} true the table given is a DataTable, or false otherwise
8464          *  @static
8465          *  @dtopt API-Static
8466          *
8467          *  @example
8468          *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
8469          *      $('#example').dataTable();
8470          *    }
8471          */
8472         DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
8473         {
8474                 var t = $(table).get(0);
8475                 var is = false;
8476         
8477                 $.each( DataTable.settings, function (i, o) {
8478                         if ( o.nTable === t || o.nScrollHead === t || o.nScrollFoot === t ) {
8479                                 is = true;
8480                         }
8481                 } );
8482         
8483                 return is;
8484         };
8485         
8486         
8487         /**
8488          * Get all DataTable tables that have been initialised - optionally you can
8489          * select to get only currently visible tables.
8490          *
8491          *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
8492          *    or visible tables only.
8493          *  @returns {array} Array of `table` nodes (not DataTable instances) which are
8494          *    DataTables
8495          *  @static
8496          *  @dtopt API-Static
8497          *
8498          *  @example
8499          *    $.each( $.fn.dataTable.tables(true), function () {
8500          *      $(table).DataTable().columns.adjust();
8501          *    } );
8502          */
8503         DataTable.tables = DataTable.fnTables = function ( visible )
8504         {
8505                 return jQuery.map( DataTable.settings, function (o) {
8506                         if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
8507                                 return o.nTable;
8508                         }
8509                 } );
8510         };
8511         
8512         
8513         /**
8514          * Convert from camel case parameters to Hungarian notation. This is made public
8515          * for the extensions to provide the same ability as DataTables core to accept
8516          * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
8517          * parameters.
8518          *
8519          *  @param {object} src The model object which holds all parameters that can be
8520          *    mapped.
8521          *  @param {object} user The object to convert from camel case to Hungarian.
8522          *  @param {boolean} force When set to `true`, properties which already have a
8523          *    Hungarian value in the `user` object will be overwritten. Otherwise they
8524          *    won't be.
8525          */
8526         DataTable.camelToHungarian = _fnCamelToHungarian;
8527         
8528         
8529         
8530         /**
8531          *
8532          */
8533         _api_register( '$()', function ( selector, opts ) {
8534                 var
8535                         rows   = this.rows( opts ).nodes(), // Get all rows
8536                         jqRows = $(rows);
8537         
8538                 return $( [].concat(
8539                         jqRows.filter( selector ).toArray(),
8540                         jqRows.find( selector ).toArray()
8541                 ) );
8542         } );
8543         
8544         
8545         // jQuery functions to operate on the tables
8546         $.each( [ 'on', 'one', 'off' ], function (i, key) {
8547                 _api_register( key+'()', function ( /* event, handler */ ) {
8548                         var args = Array.prototype.slice.call(arguments);
8549         
8550                         // Add the `dt` namespace automatically if it isn't already present
8551                         if ( args[0].indexOf( '.dt' ) === -1 ) {
8552                                 args[0] += '.dt';
8553                         }
8554         
8555                         var inst = $( this.tables().nodes() );
8556                         inst[key].apply( inst, args );
8557                         return this;
8558                 } );
8559         } );
8560         
8561         
8562         _api_register( 'clear()', function () {
8563                 return this.iterator( 'table', function ( settings ) {
8564                         _fnClearTable( settings );
8565                 } );
8566         } );
8567         
8568         
8569         _api_register( 'settings()', function () {
8570                 return new _Api( this.context, this.context );
8571         } );
8572         
8573         
8574         _api_register( 'data()', function () {
8575                 return this.iterator( 'table', function ( settings ) {
8576                         return _pluck( settings.aoData, '_aData' );
8577                 } ).flatten();
8578         } );
8579         
8580         
8581         _api_register( 'destroy()', function ( remove ) {
8582                 remove = remove || false;
8583         
8584                 return this.iterator( 'table', function ( settings ) {
8585                         var orig      = settings.nTableWrapper.parentNode;
8586                         var classes   = settings.oClasses;
8587                         var table     = settings.nTable;
8588                         var tbody     = settings.nTBody;
8589                         var thead     = settings.nTHead;
8590                         var tfoot     = settings.nTFoot;
8591                         var jqTable   = $(table);
8592                         var jqTbody   = $(tbody);
8593                         var jqWrapper = $(settings.nTableWrapper);
8594                         var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
8595                         var i, ien;
8596         
8597                         // Flag to note that the table is currently being destroyed - no action
8598                         // should be taken
8599                         settings.bDestroying = true;
8600         
8601                         // Fire off the destroy callbacks for plug-ins etc
8602                         _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
8603         
8604                         // If not being removed from the document, make all columns visible
8605                         if ( ! remove ) {
8606                                 new _Api( settings ).columns().visible( true );
8607                         }
8608         
8609                         // Blitz all `DT` namespaced events (these are internal events, the
8610                         // lowercase, `dt` events are user subscribed and they are responsible
8611                         // for removing them
8612                         jqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT');
8613                         $(window).unbind('.DT-'+settings.sInstance);
8614         
8615                         // When scrolling we had to break the table up - restore it
8616                         if ( table != thead.parentNode ) {
8617                                 jqTable.children('thead').detach();
8618                                 jqTable.append( thead );
8619                         }
8620         
8621                         if ( tfoot && table != tfoot.parentNode ) {
8622                                 jqTable.children('tfoot').detach();
8623                                 jqTable.append( tfoot );
8624                         }
8625         
8626                         // Remove the DataTables generated nodes, events and classes
8627                         jqTable.detach();
8628                         jqWrapper.detach();
8629         
8630                         settings.aaSorting = [];
8631                         settings.aaSortingFixed = [];
8632                         _fnSortingClasses( settings );
8633         
8634                         $( rows ).removeClass( settings.asStripeClasses.join(' ') );
8635         
8636                         $('th, td', thead).removeClass( classes.sSortable+' '+
8637                                 classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
8638                         );
8639         
8640                         if ( settings.bJUI ) {
8641                                 $('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach();
8642                                 $('th, td', thead).each( function () {
8643                                         var wrapper = $('div.'+classes.sSortJUIWrapper, this);
8644                                         $(this).append( wrapper.contents() );
8645                                         wrapper.detach();
8646                                 } );
8647                         }
8648         
8649                         if ( ! remove && orig ) {
8650                                 // insertBefore acts like appendChild if !arg[1]
8651                                 orig.insertBefore( table, settings.nTableReinsertBefore );
8652                         }
8653         
8654                         // Add the TR elements back into the table in their original order
8655                         jqTbody.children().detach();
8656                         jqTbody.append( rows );
8657         
8658                         // Restore the width of the original table - was read from the style property,
8659                         // so we can restore directly to that
8660                         jqTable
8661                                 .css( 'width', settings.sDestroyWidth )
8662                                 .removeClass( classes.sTable );
8663         
8664                         // If the were originally stripe classes - then we add them back here.
8665                         // Note this is not fool proof (for example if not all rows had stripe
8666                         // classes - but it's a good effort without getting carried away
8667                         ien = settings.asDestroyStripes.length;
8668         
8669                         if ( ien ) {
8670                                 jqTbody.children().each( function (i) {
8671                                         $(this).addClass( settings.asDestroyStripes[i % ien] );
8672                                 } );
8673                         }
8674         
8675                         /* Remove the settings object from the settings array */
8676                         var idx = $.inArray( settings, DataTable.settings );
8677                         if ( idx !== -1 ) {
8678                                 DataTable.settings.splice( idx, 1 );
8679                         }
8680                 } );
8681         } );
8682         
8683
8684         /**
8685          * Version string for plug-ins to check compatibility. Allowed format is
8686          * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
8687          * only for non-release builds. See http://semver.org/ for more information.
8688          *  @member
8689          *  @type string
8690          *  @default Version number
8691          */
8692         DataTable.version = "1.10.0";
8693
8694         /**
8695          * Private data store, containing all of the settings objects that are
8696          * created for the tables on a given page.
8697          *
8698          * Note that the `DataTable.settings` object is aliased to
8699          * `jQuery.fn.dataTableExt` through which it may be accessed and
8700          * manipulated, or `jQuery.fn.dataTable.settings`.
8701          *  @member
8702          *  @type array
8703          *  @default []
8704          *  @private
8705          */
8706         DataTable.settings = [];
8707
8708         /**
8709          * Object models container, for the various models that DataTables has
8710          * available to it. These models define the objects that are used to hold
8711          * the active state and configuration of the table.
8712          *  @namespace
8713          */
8714         DataTable.models = {};
8715         
8716         
8717         
8718         /**
8719          * Template object for the way in which DataTables holds information about
8720          * search information for the global filter and individual column filters.
8721          *  @namespace
8722          */
8723         DataTable.models.oSearch = {
8724                 /**
8725                  * Flag to indicate if the filtering should be case insensitive or not
8726                  *  @type boolean
8727                  *  @default true
8728                  */
8729                 "bCaseInsensitive": true,
8730         
8731                 /**
8732                  * Applied search term
8733                  *  @type string
8734                  *  @default <i>Empty string</i>
8735                  */
8736                 "sSearch": "",
8737         
8738                 /**
8739                  * Flag to indicate if the search term should be interpreted as a
8740                  * regular expression (true) or not (false) and therefore and special
8741                  * regex characters escaped.
8742                  *  @type boolean
8743                  *  @default false
8744                  */
8745                 "bRegex": false,
8746         
8747                 /**
8748                  * Flag to indicate if DataTables is to use its smart filtering or not.
8749                  *  @type boolean
8750                  *  @default true
8751                  */
8752                 "bSmart": true
8753         };
8754         
8755         
8756         
8757         
8758         /**
8759          * Template object for the way in which DataTables holds information about
8760          * each individual row. This is the object format used for the settings
8761          * aoData array.
8762          *  @namespace
8763          */
8764         DataTable.models.oRow = {
8765                 /**
8766                  * TR element for the row
8767                  *  @type node
8768                  *  @default null
8769                  */
8770                 "nTr": null,
8771         
8772                 /**
8773                  * Array of TD elements for each row. This is null until the row has been
8774                  * created.
8775                  *  @type array nodes
8776                  *  @default []
8777                  */
8778                 "anCells": null,
8779         
8780                 /**
8781                  * Data object from the original data source for the row. This is either
8782                  * an array if using the traditional form of DataTables, or an object if
8783                  * using mData options. The exact type will depend on the passed in
8784                  * data from the data source, or will be an array if using DOM a data
8785                  * source.
8786                  *  @type array|object
8787                  *  @default []
8788                  */
8789                 "_aData": [],
8790         
8791                 /**
8792                  * Sorting data cache - this array is ostensibly the same length as the
8793                  * number of columns (although each index is generated only as it is
8794                  * needed), and holds the data that is used for sorting each column in the
8795                  * row. We do this cache generation at the start of the sort in order that
8796                  * the formatting of the sort data need be done only once for each cell
8797                  * per sort. This array should not be read from or written to by anything
8798                  * other than the master sorting methods.
8799                  *  @type array
8800                  *  @default null
8801                  *  @private
8802                  */
8803                 "_aSortData": null,
8804         
8805                 /**
8806                  * Per cell filtering data cache. As per the sort data cache, used to
8807                  * increase the performance of the filtering in DataTables
8808                  *  @type array
8809                  *  @default null
8810                  *  @private
8811                  */
8812                 "_aFilterData": null,
8813         
8814                 /**
8815                  * Filtering data cache. This is the same as the cell filtering cache, but
8816                  * in this case a string rather than an array. This is easily computed with
8817                  * a join on `_aFilterData`, but is provided as a cache so the join isn't
8818                  * needed on every search (memory traded for performance)
8819                  *  @type array
8820                  *  @default null
8821                  *  @private
8822                  */
8823                 "_sFilterRow": null,
8824         
8825                 /**
8826                  * Cache of the class name that DataTables has applied to the row, so we
8827                  * can quickly look at this variable rather than needing to do a DOM check
8828                  * on className for the nTr property.
8829                  *  @type string
8830                  *  @default <i>Empty string</i>
8831                  *  @private
8832                  */
8833                 "_sRowStripe": "",
8834         
8835                 /**
8836                  * Denote if the original data source was from the DOM, or the data source
8837                  * object. This is used for invalidating data, so DataTables can
8838                  * automatically read data from the original source, unless uninstructed
8839                  * otherwise.
8840                  *  @type string
8841                  *  @default null
8842                  *  @private
8843                  */
8844                 "src": null
8845         };
8846         
8847         
8848         /**
8849          * Template object for the column information object in DataTables. This object
8850          * is held in the settings aoColumns array and contains all the information that
8851          * DataTables needs about each individual column.
8852          *
8853          * Note that this object is related to {@link DataTable.defaults.column}
8854          * but this one is the internal data store for DataTables's cache of columns.
8855          * It should NOT be manipulated outside of DataTables. Any configuration should
8856          * be done through the initialisation options.
8857          *  @namespace
8858          */
8859         DataTable.models.oColumn = {
8860                 /**
8861                  * Column index. This could be worked out on-the-fly with $.inArray, but it
8862                  * is faster to just hold it as a variable
8863                  *  @type integer
8864                  *  @default null
8865                  */
8866                 "idx": null,
8867         
8868                 /**
8869                  * A list of the columns that sorting should occur on when this column
8870                  * is sorted. That this property is an array allows multi-column sorting
8871                  * to be defined for a column (for example first name / last name columns
8872                  * would benefit from this). The values are integers pointing to the
8873                  * columns to be sorted on (typically it will be a single integer pointing
8874                  * at itself, but that doesn't need to be the case).
8875                  *  @type array
8876                  */
8877                 "aDataSort": null,
8878         
8879                 /**
8880                  * Define the sorting directions that are applied to the column, in sequence
8881                  * as the column is repeatedly sorted upon - i.e. the first value is used
8882                  * as the sorting direction when the column if first sorted (clicked on).
8883                  * Sort it again (click again) and it will move on to the next index.
8884                  * Repeat until loop.
8885                  *  @type array
8886                  */
8887                 "asSorting": null,
8888         
8889                 /**
8890                  * Flag to indicate if the column is searchable, and thus should be included
8891                  * in the filtering or not.
8892                  *  @type boolean
8893                  */
8894                 "bSearchable": null,
8895         
8896                 /**
8897                  * Flag to indicate if the column is sortable or not.
8898                  *  @type boolean
8899                  */
8900                 "bSortable": null,
8901         
8902                 /**
8903                  * Flag to indicate if the column is currently visible in the table or not
8904                  *  @type boolean
8905                  */
8906                 "bVisible": null,
8907         
8908                 /**
8909                  * Store for manual type assignment using the `column.type` option. This
8910                  * is held in store so we can manipulate the column's `sType` property.
8911                  *  @type string
8912                  *  @default null
8913                  *  @private
8914                  */
8915                 "_sManualType": null,
8916         
8917                 /**
8918                  * Flag to indicate if HTML5 data attributes should be used as the data
8919                  * source for filtering or sorting. True is either are.
8920                  *  @type boolean
8921                  *  @default false
8922                  *  @private
8923                  */
8924                 "_bAttrSrc": false,
8925         
8926                 /**
8927                  * Developer definable function that is called whenever a cell is created (Ajax source,
8928                  * etc) or processed for input (DOM source). This can be used as a compliment to mRender
8929                  * allowing you to modify the DOM element (add background colour for example) when the
8930                  * element is available.
8931                  *  @type function
8932                  *  @param {element} nTd The TD node that has been created
8933                  *  @param {*} sData The Data for the cell
8934                  *  @param {array|object} oData The data for the whole row
8935                  *  @param {int} iRow The row index for the aoData data store
8936                  *  @default null
8937                  */
8938                 "fnCreatedCell": null,
8939         
8940                 /**
8941                  * Function to get data from a cell in a column. You should <b>never</b>
8942                  * access data directly through _aData internally in DataTables - always use
8943                  * the method attached to this property. It allows mData to function as
8944                  * required. This function is automatically assigned by the column
8945                  * initialisation method
8946                  *  @type function
8947                  *  @param {array|object} oData The data array/object for the array
8948                  *    (i.e. aoData[]._aData)
8949                  *  @param {string} sSpecific The specific data type you want to get -
8950                  *    'display', 'type' 'filter' 'sort'
8951                  *  @returns {*} The data for the cell from the given row's data
8952                  *  @default null
8953                  */
8954                 "fnGetData": null,
8955         
8956                 /**
8957                  * Function to set data for a cell in the column. You should <b>never</b>
8958                  * set the data directly to _aData internally in DataTables - always use
8959                  * this method. It allows mData to function as required. This function
8960                  * is automatically assigned by the column initialisation method
8961                  *  @type function
8962                  *  @param {array|object} oData The data array/object for the array
8963                  *    (i.e. aoData[]._aData)
8964                  *  @param {*} sValue Value to set
8965                  *  @default null
8966                  */
8967                 "fnSetData": null,
8968         
8969                 /**
8970                  * Property to read the value for the cells in the column from the data
8971                  * source array / object. If null, then the default content is used, if a
8972                  * function is given then the return from the function is used.
8973                  *  @type function|int|string|null
8974                  *  @default null
8975                  */
8976                 "mData": null,
8977         
8978                 /**
8979                  * Partner property to mData which is used (only when defined) to get
8980                  * the data - i.e. it is basically the same as mData, but without the
8981                  * 'set' option, and also the data fed to it is the result from mData.
8982                  * This is the rendering method to match the data method of mData.
8983                  *  @type function|int|string|null
8984                  *  @default null
8985                  */
8986                 "mRender": null,
8987         
8988                 /**
8989                  * Unique header TH/TD element for this column - this is what the sorting
8990                  * listener is attached to (if sorting is enabled.)
8991                  *  @type node
8992                  *  @default null
8993                  */
8994                 "nTh": null,
8995         
8996                 /**
8997                  * Unique footer TH/TD element for this column (if there is one). Not used
8998                  * in DataTables as such, but can be used for plug-ins to reference the
8999                  * footer for each column.
9000                  *  @type node
9001                  *  @default null
9002                  */
9003                 "nTf": null,
9004         
9005                 /**
9006                  * The class to apply to all TD elements in the table's TBODY for the column
9007                  *  @type string
9008                  *  @default null
9009                  */
9010                 "sClass": null,
9011         
9012                 /**
9013                  * When DataTables calculates the column widths to assign to each column,
9014                  * it finds the longest string in each column and then constructs a
9015                  * temporary table and reads the widths from that. The problem with this
9016                  * is that "mmm" is much wider then "iiii", but the latter is a longer
9017                  * string - thus the calculation can go wrong (doing it properly and putting
9018                  * it into an DOM object and measuring that is horribly(!) slow). Thus as
9019                  * a "work around" we provide this option. It will append its value to the
9020                  * text that is found to be the longest string for the column - i.e. padding.
9021                  *  @type string
9022                  */
9023                 "sContentPadding": null,
9024         
9025                 /**
9026                  * Allows a default value to be given for a column's data, and will be used
9027                  * whenever a null data source is encountered (this can be because mData
9028                  * is set to null, or because the data source itself is null).
9029                  *  @type string
9030                  *  @default null
9031                  */
9032                 "sDefaultContent": null,
9033         
9034                 /**
9035                  * Name for the column, allowing reference to the column by name as well as
9036                  * by index (needs a lookup to work by name).
9037                  *  @type string
9038                  */
9039                 "sName": null,
9040         
9041                 /**
9042                  * Custom sorting data type - defines which of the available plug-ins in
9043                  * afnSortData the custom sorting will use - if any is defined.
9044                  *  @type string
9045                  *  @default std
9046                  */
9047                 "sSortDataType": 'std',
9048         
9049                 /**
9050                  * Class to be applied to the header element when sorting on this column
9051                  *  @type string
9052                  *  @default null
9053                  */
9054                 "sSortingClass": null,
9055         
9056                 /**
9057                  * Class to be applied to the header element when sorting on this column -
9058                  * when jQuery UI theming is used.
9059                  *  @type string
9060                  *  @default null
9061                  */
9062                 "sSortingClassJUI": null,
9063         
9064                 /**
9065                  * Title of the column - what is seen in the TH element (nTh).
9066                  *  @type string
9067                  */
9068                 "sTitle": null,
9069         
9070                 /**
9071                  * Column sorting and filtering type
9072                  *  @type string
9073                  *  @default null
9074                  */
9075                 "sType": null,
9076         
9077                 /**
9078                  * Width of the column
9079                  *  @type string
9080                  *  @default null
9081                  */
9082                 "sWidth": null,
9083         
9084                 /**
9085                  * Width of the column when it was first "encountered"
9086                  *  @type string
9087                  *  @default null
9088                  */
9089                 "sWidthOrig": null
9090         };
9091         
9092         
9093         /*
9094          * Developer note: The properties of the object below are given in Hungarian
9095          * notation, that was used as the interface for DataTables prior to v1.10, however
9096          * from v1.10 onwards the primary interface is camel case. In order to avoid
9097          * breaking backwards compatibility utterly with this change, the Hungarian
9098          * version is still, internally the primary interface, but is is not documented
9099          * - hence the @name tags in each doc comment. This allows a Javascript function
9100          * to create a map from Hungarian notation to camel case (going the other direction
9101          * would require each property to be listed, which would at around 3K to the size
9102          * of DataTables, while this method is about a 0.5K hit.
9103          *
9104          * Ultimately this does pave the way for Hungarian notation to be dropped
9105          * completely, but that is a massive amount of work and will break current
9106          * installs (therefore is on-hold until v2).
9107          */
9108         
9109         /**
9110          * Initialisation options that can be given to DataTables at initialisation
9111          * time.
9112          *  @namespace
9113          */
9114         DataTable.defaults = {
9115                 /**
9116                  * An array of data to use for the table, passed in at initialisation which
9117                  * will be used in preference to any data which is already in the DOM. This is
9118                  * particularly useful for constructing tables purely in Javascript, for
9119                  * example with a custom Ajax call.
9120                  *  @type array
9121                  *  @default null
9122                  *
9123                  *  @dtopt Option
9124                  *  @name DataTable.defaults.data
9125                  *
9126                  *  @example
9127                  *    // Using a 2D array data source
9128                  *    $(document).ready( function () {
9129                  *      $('#example').dataTable( {
9130                  *        "data": [
9131                  *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9132                  *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9133                  *        ],
9134                  *        "columns": [
9135                  *          { "title": "Engine" },
9136                  *          { "title": "Browser" },
9137                  *          { "title": "Platform" },
9138                  *          { "title": "Version" },
9139                  *          { "title": "Grade" }
9140                  *        ]
9141                  *      } );
9142                  *    } );
9143                  *
9144                  *  @example
9145                  *    // Using an array of objects as a data source (`data`)
9146                  *    $(document).ready( function () {
9147                  *      $('#example').dataTable( {
9148                  *        "data": [
9149                  *          {
9150                  *            "engine":   "Trident",
9151                  *            "browser":  "Internet Explorer 4.0",
9152                  *            "platform": "Win 95+",
9153                  *            "version":  4,
9154                  *            "grade":    "X"
9155                  *          },
9156                  *          {
9157                  *            "engine":   "Trident",
9158                  *            "browser":  "Internet Explorer 5.0",
9159                  *            "platform": "Win 95+",
9160                  *            "version":  5,
9161                  *            "grade":    "C"
9162                  *          }
9163                  *        ],
9164                  *        "columns": [
9165                  *          { "title": "Engine",   "data": "engine" },
9166                  *          { "title": "Browser",  "data": "browser" },
9167                  *          { "title": "Platform", "data": "platform" },
9168                  *          { "title": "Version",  "data": "version" },
9169                  *          { "title": "Grade",    "data": "grade" }
9170                  *        ]
9171                  *      } );
9172                  *    } );
9173                  */
9174                 "aaData": null,
9175         
9176         
9177                 /**
9178                  * If ordering is enabled, then DataTables will perform a first pass sort on
9179                  * initialisation. You can define which column(s) the sort is performed
9180                  * upon, and the sorting direction, with this variable. The `sorting` array
9181                  * should contain an array for each column to be sorted initially containing
9182                  * the column's index and a direction string ('asc' or 'desc').
9183                  *  @type array
9184                  *  @default [[0,'asc']]
9185                  *
9186                  *  @dtopt Option
9187                  *  @name DataTable.defaults.order
9188                  *
9189                  *  @example
9190                  *    // Sort by 3rd column first, and then 4th column
9191                  *    $(document).ready( function() {
9192                  *      $('#example').dataTable( {
9193                  *        "order": [[2,'asc'], [3,'desc']]
9194                  *      } );
9195                  *    } );
9196                  *
9197                  *    // No initial sorting
9198                  *    $(document).ready( function() {
9199                  *      $('#example').dataTable( {
9200                  *        "order": []
9201                  *      } );
9202                  *    } );
9203                  */
9204                 "aaSorting": [[0,'asc']],
9205         
9206         
9207                 /**
9208                  * This parameter is basically identical to the `sorting` parameter, but
9209                  * cannot be overridden by user interaction with the table. What this means
9210                  * is that you could have a column (visible or hidden) which the sorting
9211                  * will always be forced on first - any sorting after that (from the user)
9212                  * will then be performed as required. This can be useful for grouping rows
9213                  * together.
9214                  *  @type array
9215                  *  @default null
9216                  *
9217                  *  @dtopt Option
9218                  *  @name DataTable.defaults.orderFixed
9219                  *
9220                  *  @example
9221                  *    $(document).ready( function() {
9222                  *      $('#example').dataTable( {
9223                  *        "orderFixed": [[0,'asc']]
9224                  *      } );
9225                  *    } )
9226                  */
9227                 "aaSortingFixed": [],
9228         
9229         
9230                 /**
9231                  * DataTables can be instructed to load data to display in the table from a
9232                  * Ajax source. This option defines how that Ajax call is made and where to.
9233                  *
9234                  * The `ajax` property has three different modes of operation, depending on
9235                  * how it is defined. These are:
9236                  *
9237                  * * `string` - Set the URL from where the data should be loaded from.
9238                  * * `object` - Define properties for `jQuery.ajax`.
9239                  * * `function` - Custom data get function
9240                  *
9241                  * `string`
9242                  * --------
9243                  *
9244                  * As a string, the `ajax` property simply defines the URL from which
9245                  * DataTables will load data.
9246                  *
9247                  * `object`
9248                  * --------
9249                  *
9250                  * As an object, the parameters in the object are passed to
9251                  * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
9252                  * of the Ajax request. DataTables has a number of default parameters which
9253                  * you can override using this option. Please refer to the jQuery
9254                  * documentation for a full description of the options available, although
9255                  * the following parameters provide additional options in DataTables or
9256                  * require special consideration:
9257                  *
9258                  * * `data` - As with jQuery, `data` can be provided as an object, but it
9259                  *   can also be used as a function to manipulate the data DataTables sends
9260                  *   to the server. The function takes a single parameter, an object of
9261                  *   parameters with the values that DataTables has readied for sending. An
9262                  *   object may be returned which will be merged into the DataTables
9263                  *   defaults, or you can add the items to the object that was passed in and
9264                  *   not return anything from the function. This supersedes `fnServerParams`
9265                  *   from DataTables 1.9-.
9266                  *
9267                  * * `dataSrc` - By default DataTables will look for the property `data` (or
9268                  *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
9269                  *   from an Ajax source or for server-side processing - this parameter
9270                  *   allows that property to be changed. You can use Javascript dotted
9271                  *   object notation to get a data source for multiple levels of nesting, or
9272                  *   it my be used as a function. As a function it takes a single parameter,
9273                  *   the JSON returned from the server, which can be manipulated as
9274                  *   required, with the returned value being that used by DataTables as the
9275                  *   data source for the table. This supersedes `sAjaxDataProp` from
9276                  *   DataTables 1.9-.
9277                  *
9278                  * * `success` - Should not be overridden it is used internally in
9279                  *   DataTables. To manipulate / transform the data returned by the server
9280                  *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
9281                  *
9282                  * `function`
9283                  * ----------
9284                  *
9285                  * As a function, making the Ajax call is left up to yourself allowing
9286                  * complete control of the Ajax request. Indeed, if desired, a method other
9287                  * than Ajax could be used to obtain the required data, such as Web storage
9288                  * or an AIR database.
9289                  *
9290                  * The function is given four parameters and no return is required. The
9291                  * parameters are:
9292                  *
9293                  * 1. _object_ - Data to send to the server
9294                  * 2. _function_ - Callback function that must be executed when the required
9295                  *    data has been obtained. That data should be passed into the callback
9296                  *    as the only parameter
9297                  * 3. _object_ - DataTables settings object for the table
9298                  *
9299                  * Note that this supersedes `fnServerData` from DataTables 1.9-.
9300                  *
9301                  *  @type string|object|function
9302                  *  @default null
9303                  *
9304                  *  @dtopt Option
9305                  *  @name DataTable.defaults.ajax
9306                  *  @since 1.10.0
9307                  *
9308                  * @example
9309                  *   // Get JSON data from a file via Ajax.
9310                  *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
9311                  *   $('#example').dataTable( {
9312                  *     "ajax": "data.json"
9313                  *   } );
9314                  *
9315                  * @example
9316                  *   // Get JSON data from a file via Ajax, using `dataSrc` to change
9317                  *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
9318                  *   $('#example').dataTable( {
9319                  *     "ajax": {
9320                  *       "url": "data.json",
9321                  *       "dataSrc": "tableData"
9322                  *     }
9323                  *   } );
9324                  *
9325                  * @example
9326                  *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
9327                  *   // from a plain array rather than an array in an object
9328                  *   $('#example').dataTable( {
9329                  *     "ajax": {
9330                  *       "url": "data.json",
9331                  *       "dataSrc": ""
9332                  *     }
9333                  *   } );
9334                  *
9335                  * @example
9336                  *   // Manipulate the data returned from the server - add a link to data
9337                  *   // (note this can, should, be done using `render` for the column - this
9338                  *   // is just a simple example of how the data can be manipulated).
9339                  *   $('#example').dataTable( {
9340                  *     "ajax": {
9341                  *       "url": "data.json",
9342                  *       "dataSrc": function ( json ) {
9343                  *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
9344                  *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
9345                  *         }
9346                  *         return json;
9347                  *       }
9348                  *     }
9349                  *   } );
9350                  *
9351                  * @example
9352                  *   // Add data to the request
9353                  *   $('#example').dataTable( {
9354                  *     "ajax": {
9355                  *       "url": "data.json",
9356                  *       "data": function ( d ) {
9357                  *         return {
9358                  *           "extra_search": $('#extra').val()
9359                  *         };
9360                  *       }
9361                  *     }
9362                  *   } );
9363                  *
9364                  * @example
9365                  *   // Send request as POST
9366                  *   $('#example').dataTable( {
9367                  *     "ajax": {
9368                  *       "url": "data.json",
9369                  *       "type": "POST"
9370                  *     }
9371                  *   } );
9372                  *
9373                  * @example
9374                  *   // Get the data from localStorage (could interface with a form for
9375                  *   // adding, editing and removing rows).
9376                  *   $('#example').dataTable( {
9377                  *     "ajax": function (data, callback, settings) {
9378                  *       callback(
9379                  *         JSON.parse( localStorage.getItem('dataTablesData') )
9380                  *       );
9381                  *     }
9382                  *   } );
9383                  */
9384                 "ajax": null,
9385         
9386         
9387                 /**
9388                  * This parameter allows you to readily specify the entries in the length drop
9389                  * down menu that DataTables shows when pagination is enabled. It can be
9390                  * either a 1D array of options which will be used for both the displayed
9391                  * option and the value, or a 2D array which will use the array in the first
9392                  * position as the value, and the array in the second position as the
9393                  * displayed options (useful for language strings such as 'All').
9394                  *
9395                  * Note that the `pageLength` property will be automatically set to the
9396                  * first value given in this array, unless `pageLength` is also provided.
9397                  *  @type array
9398                  *  @default [ 10, 25, 50, 100 ]
9399                  *
9400                  *  @dtopt Option
9401                  *  @name DataTable.defaults.lengthMenu
9402                  *
9403                  *  @example
9404                  *    $(document).ready( function() {
9405                  *      $('#example').dataTable( {
9406                  *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
9407                  *      } );
9408                  *    } );
9409                  */
9410                 "aLengthMenu": [ 10, 25, 50, 100 ],
9411         
9412         
9413                 /**
9414                  * The `columns` option in the initialisation parameter allows you to define
9415                  * details about the way individual columns behave. For a full list of
9416                  * column options that can be set, please see
9417                  * {@link DataTable.defaults.column}. Note that if you use `columns` to
9418                  * define your columns, you must have an entry in the array for every single
9419                  * column that you have in your table (these can be null if you don't which
9420                  * to specify any options).
9421                  *  @member
9422                  *
9423                  *  @name DataTable.defaults.column
9424                  */
9425                 "aoColumns": null,
9426         
9427                 /**
9428                  * Very similar to `columns`, `columnDefs` allows you to target a specific
9429                  * column, multiple columns, or all columns, using the `targets` property of
9430                  * each object in the array. This allows great flexibility when creating
9431                  * tables, as the `columnDefs` arrays can be of any length, targeting the
9432                  * columns you specifically want. `columnDefs` may use any of the column
9433                  * options available: {@link DataTable.defaults.column}, but it _must_
9434                  * have `targets` defined in each object in the array. Values in the `targets`
9435                  * array may be:
9436                  *   <ul>
9437                  *     <li>a string - class name will be matched on the TH for the column</li>
9438                  *     <li>0 or a positive integer - column index counting from the left</li>
9439                  *     <li>a negative integer - column index counting from the right</li>
9440                  *     <li>the string "_all" - all columns (i.e. assign a default)</li>
9441                  *   </ul>
9442                  *  @member
9443                  *
9444                  *  @name DataTable.defaults.columnDefs
9445                  */
9446                 "aoColumnDefs": null,
9447         
9448         
9449                 /**
9450                  * Basically the same as `search`, this parameter defines the individual column
9451                  * filtering state at initialisation time. The array must be of the same size
9452                  * as the number of columns, and each element be an object with the parameters
9453                  * `search` and `escapeRegex` (the latter is optional). 'null' is also
9454                  * accepted and the default will be used.
9455                  *  @type array
9456                  *  @default []
9457                  *
9458                  *  @dtopt Option
9459                  *  @name DataTable.defaults.searchCols
9460                  *
9461                  *  @example
9462                  *    $(document).ready( function() {
9463                  *      $('#example').dataTable( {
9464                  *        "searchCols": [
9465                  *          null,
9466                  *          { "search": "My filter" },
9467                  *          null,
9468                  *          { "search": "^[0-9]", "escapeRegex": false }
9469                  *        ]
9470                  *      } );
9471                  *    } )
9472                  */
9473                 "aoSearchCols": [],
9474         
9475         
9476                 /**
9477                  * An array of CSS classes that should be applied to displayed rows. This
9478                  * array may be of any length, and DataTables will apply each class
9479                  * sequentially, looping when required.
9480                  *  @type array
9481                  *  @default null <i>Will take the values determined by the `oClasses.stripe*`
9482                  *    options</i>
9483                  *
9484                  *  @dtopt Option
9485                  *  @name DataTable.defaults.stripeClasses
9486                  *
9487                  *  @example
9488                  *    $(document).ready( function() {
9489                  *      $('#example').dataTable( {
9490                  *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
9491                  *      } );
9492                  *    } )
9493                  */
9494                 "asStripeClasses": null,
9495         
9496         
9497                 /**
9498                  * Enable or disable automatic column width calculation. This can be disabled
9499                  * as an optimisation (it takes some time to calculate the widths) if the
9500                  * tables widths are passed in using `columns`.
9501                  *  @type boolean
9502                  *  @default true
9503                  *
9504                  *  @dtopt Features
9505                  *  @name DataTable.defaults.autoWidth
9506                  *
9507                  *  @example
9508                  *    $(document).ready( function () {
9509                  *      $('#example').dataTable( {
9510                  *        "autoWidth": false
9511                  *      } );
9512                  *    } );
9513                  */
9514                 "bAutoWidth": true,
9515         
9516         
9517                 /**
9518                  * Deferred rendering can provide DataTables with a huge speed boost when you
9519                  * are using an Ajax or JS data source for the table. This option, when set to
9520                  * true, will cause DataTables to defer the creation of the table elements for
9521                  * each row until they are needed for a draw - saving a significant amount of
9522                  * time.
9523                  *  @type boolean
9524                  *  @default false
9525                  *
9526                  *  @dtopt Features
9527                  *  @name DataTable.defaults.deferRender
9528                  *
9529                  *  @example
9530                  *    $(document).ready( function() {
9531                  *      $('#example').dataTable( {
9532                  *        "ajax": "sources/arrays.txt",
9533                  *        "deferRender": true
9534                  *      } );
9535                  *    } );
9536                  */
9537                 "bDeferRender": false,
9538         
9539         
9540                 /**
9541                  * Replace a DataTable which matches the given selector and replace it with
9542                  * one which has the properties of the new initialisation object passed. If no
9543                  * table matches the selector, then the new DataTable will be constructed as
9544                  * per normal.
9545                  *  @type boolean
9546                  *  @default false
9547                  *
9548                  *  @dtopt Options
9549                  *  @name DataTable.defaults.destroy
9550                  *
9551                  *  @example
9552                  *    $(document).ready( function() {
9553                  *      $('#example').dataTable( {
9554                  *        "srollY": "200px",
9555                  *        "paginate": false
9556                  *      } );
9557                  *
9558                  *      // Some time later....
9559                  *      $('#example').dataTable( {
9560                  *        "filter": false,
9561                  *        "destroy": true
9562                  *      } );
9563                  *    } );
9564                  */
9565                 "bDestroy": false,
9566         
9567         
9568                 /**
9569                  * Enable or disable filtering of data. Filtering in DataTables is "smart" in
9570                  * that it allows the end user to input multiple words (space separated) and
9571                  * will match a row containing those words, even if not in the order that was
9572                  * specified (this allow matching across multiple columns). Note that if you
9573                  * wish to use filtering in DataTables this must remain 'true' - to remove the
9574                  * default filtering input box and retain filtering abilities, please use
9575                  * {@link DataTable.defaults.dom}.
9576                  *  @type boolean
9577                  *  @default true
9578                  *
9579                  *  @dtopt Features
9580                  *  @name DataTable.defaults.searching
9581                  *
9582                  *  @example
9583                  *    $(document).ready( function () {
9584                  *      $('#example').dataTable( {
9585                  *        "searching": false
9586                  *      } );
9587                  *    } );
9588                  */
9589                 "bFilter": true,
9590         
9591         
9592                 /**
9593                  * Enable or disable the table information display. This shows information
9594                  * about the data that is currently visible on the page, including information
9595                  * about filtered data if that action is being performed.
9596                  *  @type boolean
9597                  *  @default true
9598                  *
9599                  *  @dtopt Features
9600                  *  @name DataTable.defaults.info
9601                  *
9602                  *  @example
9603                  *    $(document).ready( function () {
9604                  *      $('#example').dataTable( {
9605                  *        "info": false
9606                  *      } );
9607                  *    } );
9608                  */
9609                 "bInfo": true,
9610         
9611         
9612                 /**
9613                  * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
9614                  * slightly different and additional mark-up from what DataTables has
9615                  * traditionally used).
9616                  *  @type boolean
9617                  *  @default false
9618                  *
9619                  *  @dtopt Features
9620                  *  @name DataTable.defaults.jQueryUI
9621                  *
9622                  *  @example
9623                  *    $(document).ready( function() {
9624                  *      $('#example').dataTable( {
9625                  *        "jQueryUI": true
9626                  *      } );
9627                  *    } );
9628                  */
9629                 "bJQueryUI": false,
9630         
9631         
9632                 /**
9633                  * Allows the end user to select the size of a formatted page from a select
9634                  * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
9635                  *  @type boolean
9636                  *  @default true
9637                  *
9638                  *  @dtopt Features
9639                  *  @name DataTable.defaults.lengthChange
9640                  *
9641                  *  @example
9642                  *    $(document).ready( function () {
9643                  *      $('#example').dataTable( {
9644                  *        "lengthChange": false
9645                  *      } );
9646                  *    } );
9647                  */
9648                 "bLengthChange": true,
9649         
9650         
9651                 /**
9652                  * Enable or disable pagination.
9653                  *  @type boolean
9654                  *  @default true
9655                  *
9656                  *  @dtopt Features
9657                  *  @name DataTable.defaults.paging
9658                  *
9659                  *  @example
9660                  *    $(document).ready( function () {
9661                  *      $('#example').dataTable( {
9662                  *        "paging": false
9663                  *      } );
9664                  *    } );
9665                  */
9666                 "bPaginate": true,
9667         
9668         
9669                 /**
9670                  * Enable or disable the display of a 'processing' indicator when the table is
9671                  * being processed (e.g. a sort). This is particularly useful for tables with
9672                  * large amounts of data where it can take a noticeable amount of time to sort
9673                  * the entries.
9674                  *  @type boolean
9675                  *  @default false
9676                  *
9677                  *  @dtopt Features
9678                  *  @name DataTable.defaults.processing
9679                  *
9680                  *  @example
9681                  *    $(document).ready( function () {
9682                  *      $('#example').dataTable( {
9683                  *        "processing": true
9684                  *      } );
9685                  *    } );
9686                  */
9687                 "bProcessing": false,
9688         
9689         
9690                 /**
9691                  * Retrieve the DataTables object for the given selector. Note that if the
9692                  * table has already been initialised, this parameter will cause DataTables
9693                  * to simply return the object that has already been set up - it will not take
9694                  * account of any changes you might have made to the initialisation object
9695                  * passed to DataTables (setting this parameter to true is an acknowledgement
9696                  * that you understand this). `destroy` can be used to reinitialise a table if
9697                  * you need.
9698                  *  @type boolean
9699                  *  @default false
9700                  *
9701                  *  @dtopt Options
9702                  *  @name DataTable.defaults.retrieve
9703                  *
9704                  *  @example
9705                  *    $(document).ready( function() {
9706                  *      initTable();
9707                  *      tableActions();
9708                  *    } );
9709                  *
9710                  *    function initTable ()
9711                  *    {
9712                  *      return $('#example').dataTable( {
9713                  *        "scrollY": "200px",
9714                  *        "paginate": false,
9715                  *        "retrieve": true
9716                  *      } );
9717                  *    }
9718                  *
9719                  *    function tableActions ()
9720                  *    {
9721                  *      var table = initTable();
9722                  *      // perform API operations with oTable
9723                  *    }
9724                  */
9725                 "bRetrieve": false,
9726         
9727         
9728                 /**
9729                  * When vertical (y) scrolling is enabled, DataTables will force the height of
9730                  * the table's viewport to the given height at all times (useful for layout).
9731                  * However, this can look odd when filtering data down to a small data set,
9732                  * and the footer is left "floating" further down. This parameter (when
9733                  * enabled) will cause DataTables to collapse the table's viewport down when
9734                  * the result set will fit within the given Y height.
9735                  *  @type boolean
9736                  *  @default false
9737                  *
9738                  *  @dtopt Options
9739                  *  @name DataTable.defaults.scrollCollapse
9740                  *
9741                  *  @example
9742                  *    $(document).ready( function() {
9743                  *      $('#example').dataTable( {
9744                  *        "scrollY": "200",
9745                  *        "scrollCollapse": true
9746                  *      } );
9747                  *    } );
9748                  */
9749                 "bScrollCollapse": false,
9750         
9751         
9752                 /**
9753                  * Configure DataTables to use server-side processing. Note that the
9754                  * `ajax` parameter must also be given in order to give DataTables a
9755                  * source to obtain the required data for each draw.
9756                  *  @type boolean
9757                  *  @default false
9758                  *
9759                  *  @dtopt Features
9760                  *  @dtopt Server-side
9761                  *  @name DataTable.defaults.serverSide
9762                  *
9763                  *  @example
9764                  *    $(document).ready( function () {
9765                  *      $('#example').dataTable( {
9766                  *        "serverSide": true,
9767                  *        "ajax": "xhr.php"
9768                  *      } );
9769                  *    } );
9770                  */
9771                 "bServerSide": false,
9772         
9773         
9774                 /**
9775                  * Enable or disable sorting of columns. Sorting of individual columns can be
9776                  * disabled by the `sortable` option for each column.
9777                  *  @type boolean
9778                  *  @default true
9779                  *
9780                  *  @dtopt Features
9781                  *  @name DataTable.defaults.ordering
9782                  *
9783                  *  @example
9784                  *    $(document).ready( function () {
9785                  *      $('#example').dataTable( {
9786                  *        "ordering": false
9787                  *      } );
9788                  *    } );
9789                  */
9790                 "bSort": true,
9791         
9792         
9793                 /**
9794                  * Enable or display DataTables' ability to sort multiple columns at the
9795                  * same time (activated by shift-click by the user).
9796                  *  @type boolean
9797                  *  @default true
9798                  *
9799                  *  @dtopt Options
9800                  *  @name DataTable.defaults.orderMulti
9801                  *
9802                  *  @example
9803                  *    // Disable multiple column sorting ability
9804                  *    $(document).ready( function () {
9805                  *      $('#example').dataTable( {
9806                  *        "orderMulti": false
9807                  *      } );
9808                  *    } );
9809                  */
9810                 "bSortMulti": true,
9811         
9812         
9813                 /**
9814                  * Allows control over whether DataTables should use the top (true) unique
9815                  * cell that is found for a single column, or the bottom (false - default).
9816                  * This is useful when using complex headers.
9817                  *  @type boolean
9818                  *  @default false
9819                  *
9820                  *  @dtopt Options
9821                  *  @name DataTable.defaults.orderCellsTop
9822                  *
9823                  *  @example
9824                  *    $(document).ready( function() {
9825                  *      $('#example').dataTable( {
9826                  *        "orderCellsTop": true
9827                  *      } );
9828                  *    } );
9829                  */
9830                 "bSortCellsTop": false,
9831         
9832         
9833                 /**
9834                  * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
9835                  * `sorting\_3` to the columns which are currently being sorted on. This is
9836                  * presented as a feature switch as it can increase processing time (while
9837                  * classes are removed and added) so for large data sets you might want to
9838                  * turn this off.
9839                  *  @type boolean
9840                  *  @default true
9841                  *
9842                  *  @dtopt Features
9843                  *  @name DataTable.defaults.orderClasses
9844                  *
9845                  *  @example
9846                  *    $(document).ready( function () {
9847                  *      $('#example').dataTable( {
9848                  *        "orderClasses": false
9849                  *      } );
9850                  *    } );
9851                  */
9852                 "bSortClasses": true,
9853         
9854         
9855                 /**
9856                  * Enable or disable state saving. When enabled HTML5 `localStorage` will be
9857                  * used to save table display information such as pagination information,
9858                  * display length, filtering and sorting. As such when the end user reloads
9859                  * the page the display display will match what thy had previously set up.
9860                  *
9861                  * Due to the use of `localStorage` the default state saving is not supported
9862                  * in IE6 or 7. If state saving is required in those browsers, use
9863                  * `stateSaveCallback` to provide a storage solution such as cookies.
9864                  *  @type boolean
9865                  *  @default false
9866                  *
9867                  *  @dtopt Features
9868                  *  @name DataTable.defaults.stateSave
9869                  *
9870                  *  @example
9871                  *    $(document).ready( function () {
9872                  *      $('#example').dataTable( {
9873                  *        "stateSave": true
9874                  *      } );
9875                  *    } );
9876                  */
9877                 "bStateSave": false,
9878         
9879         
9880                 /**
9881                  * This function is called when a TR element is created (and all TD child
9882                  * elements have been inserted), or registered if using a DOM source, allowing
9883                  * manipulation of the TR element (adding classes etc).
9884                  *  @type function
9885                  *  @param {node} row "TR" element for the current row
9886                  *  @param {array} data Raw data array for this row
9887                  *  @param {int} dataIndex The index of this row in the internal aoData array
9888                  *
9889                  *  @dtopt Callbacks
9890                  *  @name DataTable.defaults.createdRow
9891                  *
9892                  *  @example
9893                  *    $(document).ready( function() {
9894                  *      $('#example').dataTable( {
9895                  *        "createdRow": function( row, data, dataIndex ) {
9896                  *          // Bold the grade for all 'A' grade browsers
9897                  *          if ( data[4] == "A" )
9898                  *          {
9899                  *            $('td:eq(4)', row).html( '<b>A</b>' );
9900                  *          }
9901                  *        }
9902                  *      } );
9903                  *    } );
9904                  */
9905                 "fnCreatedRow": null,
9906         
9907         
9908                 /**
9909                  * This function is called on every 'draw' event, and allows you to
9910                  * dynamically modify any aspect you want about the created DOM.
9911                  *  @type function
9912                  *  @param {object} settings DataTables settings object
9913                  *
9914                  *  @dtopt Callbacks
9915                  *  @name DataTable.defaults.drawCallback
9916                  *
9917                  *  @example
9918                  *    $(document).ready( function() {
9919                  *      $('#example').dataTable( {
9920                  *        "drawCallback": function( settings ) {
9921                  *          alert( 'DataTables has redrawn the table' );
9922                  *        }
9923                  *      } );
9924                  *    } );
9925                  */
9926                 "fnDrawCallback": null,
9927         
9928         
9929                 /**
9930                  * Identical to fnHeaderCallback() but for the table footer this function
9931                  * allows you to modify the table footer on every 'draw' event.
9932                  *  @type function
9933                  *  @param {node} foot "TR" element for the footer
9934                  *  @param {array} data Full table data (as derived from the original HTML)
9935                  *  @param {int} start Index for the current display starting point in the
9936                  *    display array
9937                  *  @param {int} end Index for the current display ending point in the
9938                  *    display array
9939                  *  @param {array int} display Index array to translate the visual position
9940                  *    to the full data array
9941                  *
9942                  *  @dtopt Callbacks
9943                  *  @name DataTable.defaults.footerCallback
9944                  *
9945                  *  @example
9946                  *    $(document).ready( function() {
9947                  *      $('#example').dataTable( {
9948                  *        "footerCallback": function( tfoot, data, start, end, display ) {
9949                  *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
9950                  *        }
9951                  *      } );
9952                  *    } )
9953                  */
9954                 "fnFooterCallback": null,
9955         
9956         
9957                 /**
9958                  * When rendering large numbers in the information element for the table
9959                  * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
9960                  * to have a comma separator for the 'thousands' units (e.g. 1 million is
9961                  * rendered as "1,000,000") to help readability for the end user. This
9962                  * function will override the default method DataTables uses.
9963                  *  @type function
9964                  *  @member
9965                  *  @param {int} toFormat number to be formatted
9966                  *  @returns {string} formatted string for DataTables to show the number
9967                  *
9968                  *  @dtopt Callbacks
9969                  *  @name DataTable.defaults.formatNumber
9970                  *
9971                  *  @example
9972                  *    // Format a number using a single quote for the separator (note that
9973                  *    // this can also be done with the language.thousands option)
9974                  *    $(document).ready( function() {
9975                  *      $('#example').dataTable( {
9976                  *        "formatNumber": function ( toFormat ) {
9977                  *          return toFormat.toString().replace(
9978                  *            /\B(?=(\d{3})+(?!\d))/g, "'"
9979                  *          );
9980                  *        };
9981                  *      } );
9982                  *    } );
9983                  */
9984                 "fnFormatNumber": function ( toFormat ) {
9985                         return toFormat.toString().replace(
9986                                 /\B(?=(\d{3})+(?!\d))/g,
9987                                 this.oLanguage.sThousands
9988                         );
9989                 },
9990         
9991         
9992                 /**
9993                  * This function is called on every 'draw' event, and allows you to
9994                  * dynamically modify the header row. This can be used to calculate and
9995                  * display useful information about the table.
9996                  *  @type function
9997                  *  @param {node} head "TR" element for the header
9998                  *  @param {array} data Full table data (as derived from the original HTML)
9999                  *  @param {int} start Index for the current display starting point in the
10000                  *    display array
10001                  *  @param {int} end Index for the current display ending point in the
10002                  *    display array
10003                  *  @param {array int} display Index array to translate the visual position
10004                  *    to the full data array
10005                  *
10006                  *  @dtopt Callbacks
10007                  *  @name DataTable.defaults.headerCallback
10008                  *
10009                  *  @example
10010                  *    $(document).ready( function() {
10011                  *      $('#example').dataTable( {
10012                  *        "fheaderCallback": function( head, data, start, end, display ) {
10013                  *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10014                  *        }
10015                  *      } );
10016                  *    } )
10017                  */
10018                 "fnHeaderCallback": null,
10019         
10020         
10021                 /**
10022                  * The information element can be used to convey information about the current
10023                  * state of the table. Although the internationalisation options presented by
10024                  * DataTables are quite capable of dealing with most customisations, there may
10025                  * be times where you wish to customise the string further. This callback
10026                  * allows you to do exactly that.
10027                  *  @type function
10028                  *  @param {object} oSettings DataTables settings object
10029                  *  @param {int} start Starting position in data for the draw
10030                  *  @param {int} end End position in data for the draw
10031                  *  @param {int} max Total number of rows in the table (regardless of
10032                  *    filtering)
10033                  *  @param {int} total Total number of rows in the data set, after filtering
10034                  *  @param {string} pre The string that DataTables has formatted using it's
10035                  *    own rules
10036                  *  @returns {string} The string to be displayed in the information element.
10037                  *
10038                  *  @dtopt Callbacks
10039                  *  @name DataTable.defaults.infoCallback
10040                  *
10041                  *  @example
10042                  *    $('#example').dataTable( {
10043                  *      "infoCallback": function( settings, start, end, max, total, pre ) {
10044                  *        return start +" to "+ end;
10045                  *      }
10046                  *    } );
10047                  */
10048                 "fnInfoCallback": null,
10049         
10050         
10051                 /**
10052                  * Called when the table has been initialised. Normally DataTables will
10053                  * initialise sequentially and there will be no need for this function,
10054                  * however, this does not hold true when using external language information
10055                  * since that is obtained using an async XHR call.
10056                  *  @type function
10057                  *  @param {object} settings DataTables settings object
10058                  *  @param {object} json The JSON object request from the server - only
10059                  *    present if client-side Ajax sourced data is used
10060                  *
10061                  *  @dtopt Callbacks
10062                  *  @name DataTable.defaults.initComplete
10063                  *
10064                  *  @example
10065                  *    $(document).ready( function() {
10066                  *      $('#example').dataTable( {
10067                  *        "initComplete": function(settings, json) {
10068                  *          alert( 'DataTables has finished its initialisation.' );
10069                  *        }
10070                  *      } );
10071                  *    } )
10072                  */
10073                 "fnInitComplete": null,
10074         
10075         
10076                 /**
10077                  * Called at the very start of each table draw and can be used to cancel the
10078                  * draw by returning false, any other return (including undefined) results in
10079                  * the full draw occurring).
10080                  *  @type function
10081                  *  @param {object} settings DataTables settings object
10082                  *  @returns {boolean} False will cancel the draw, anything else (including no
10083                  *    return) will allow it to complete.
10084                  *
10085                  *  @dtopt Callbacks
10086                  *  @name DataTable.defaults.preDrawCallback
10087                  *
10088                  *  @example
10089                  *    $(document).ready( function() {
10090                  *      $('#example').dataTable( {
10091                  *        "preDrawCallback": function( settings ) {
10092                  *          if ( $('#test').val() == 1 ) {
10093                  *            return false;
10094                  *          }
10095                  *        }
10096                  *      } );
10097                  *    } );
10098                  */
10099                 "fnPreDrawCallback": null,
10100         
10101         
10102                 /**
10103                  * This function allows you to 'post process' each row after it have been
10104                  * generated for each table draw, but before it is rendered on screen. This
10105                  * function might be used for setting the row class name etc.
10106                  *  @type function
10107                  *  @param {node} row "TR" element for the current row
10108                  *  @param {array} data Raw data array for this row
10109                  *  @param {int} displayIndex The display index for the current table draw
10110                  *  @param {int} displayIndexFull The index of the data in the full list of
10111                  *    rows (after filtering)
10112                  *
10113                  *  @dtopt Callbacks
10114                  *  @name DataTable.defaults.rowCallback
10115                  *
10116                  *  @example
10117                  *    $(document).ready( function() {
10118                  *      $('#example').dataTable( {
10119                  *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10120                  *          // Bold the grade for all 'A' grade browsers
10121                  *          if ( data[4] == "A" ) {
10122                  *            $('td:eq(4)', row).html( '<b>A</b>' );
10123                  *          }
10124                  *        }
10125                  *      } );
10126                  *    } );
10127                  */
10128                 "fnRowCallback": null,
10129         
10130         
10131                 /**
10132                  * __Deprecated__ The functionality provided by this parameter has now been
10133                  * superseded by that provided through `ajax`, which should be used instead.
10134                  *
10135                  * This parameter allows you to override the default function which obtains
10136                  * the data from the server so something more suitable for your application.
10137                  * For example you could use POST data, or pull information from a Gears or
10138                  * AIR database.
10139                  *  @type function
10140                  *  @member
10141                  *  @param {string} source HTTP source to obtain the data from (`ajax`)
10142                  *  @param {array} data A key/value pair object containing the data to send
10143                  *    to the server
10144                  *  @param {function} callback to be called on completion of the data get
10145                  *    process that will draw the data on the page.
10146                  *  @param {object} settings DataTables settings object
10147                  *
10148                  *  @dtopt Callbacks
10149                  *  @dtopt Server-side
10150                  *  @name DataTable.defaults.serverData
10151                  *
10152                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
10153                  */
10154                 "fnServerData": null,
10155         
10156         
10157                 /**
10158                  * __Deprecated__ The functionality provided by this parameter has now been
10159                  * superseded by that provided through `ajax`, which should be used instead.
10160                  *
10161                  *  It is often useful to send extra data to the server when making an Ajax
10162                  * request - for example custom filtering information, and this callback
10163                  * function makes it trivial to send extra information to the server. The
10164                  * passed in parameter is the data set that has been constructed by
10165                  * DataTables, and you can add to this or modify it as you require.
10166                  *  @type function
10167                  *  @param {array} data Data array (array of objects which are name/value
10168                  *    pairs) that has been constructed by DataTables and will be sent to the
10169                  *    server. In the case of Ajax sourced data with server-side processing
10170                  *    this will be an empty array, for server-side processing there will be a
10171                  *    significant number of parameters!
10172                  *  @returns {undefined} Ensure that you modify the data array passed in,
10173                  *    as this is passed by reference.
10174                  *
10175                  *  @dtopt Callbacks
10176                  *  @dtopt Server-side
10177                  *  @name DataTable.defaults.serverParams
10178                  *
10179                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
10180                  */
10181                 "fnServerParams": null,
10182         
10183         
10184                 /**
10185                  * Load the table state. With this function you can define from where, and how, the
10186                  * state of a table is loaded. By default DataTables will load from `localStorage`
10187                  * but you might wish to use a server-side database or cookies.
10188                  *  @type function
10189                  *  @member
10190                  *  @param {object} settings DataTables settings object
10191                  *  @return {object} The DataTables state object to be loaded
10192                  *
10193                  *  @dtopt Callbacks
10194                  *  @name DataTable.defaults.stateLoadCallback
10195                  *
10196                  *  @example
10197                  *    $(document).ready( function() {
10198                  *      $('#example').dataTable( {
10199                  *        "stateSave": true,
10200                  *        "stateLoadCallback": function (settings) {
10201                  *          var o;
10202                  *
10203                  *          // Send an Ajax request to the server to get the data. Note that
10204                  *          // this is a synchronous request.
10205                  *          $.ajax( {
10206                  *            "url": "/state_load",
10207                  *            "async": false,
10208                  *            "dataType": "json",
10209                  *            "success": function (json) {
10210                  *              o = json;
10211                  *            }
10212                  *          } );
10213                  *
10214                  *          return o;
10215                  *        }
10216                  *      } );
10217                  *    } );
10218                  */
10219                 "fnStateLoadCallback": function ( settings ) {
10220                         try {
10221                                 return JSON.parse(
10222                                         (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
10223                                                 'DataTables_'+settings.sInstance+'_'+location.pathname
10224                                         )
10225                                 );
10226                         } catch (e) {}
10227                 },
10228         
10229         
10230                 /**
10231                  * Callback which allows modification of the saved state prior to loading that state.
10232                  * This callback is called when the table is loading state from the stored data, but
10233                  * prior to the settings object being modified by the saved state. Note that for
10234                  * plug-in authors, you should use the `stateLoadParams` event to load parameters for
10235                  * a plug-in.
10236                  *  @type function
10237                  *  @param {object} settings DataTables settings object
10238                  *  @param {object} data The state object that is to be loaded
10239                  *
10240                  *  @dtopt Callbacks
10241                  *  @name DataTable.defaults.stateLoadParams
10242                  *
10243                  *  @example
10244                  *    // Remove a saved filter, so filtering is never loaded
10245                  *    $(document).ready( function() {
10246                  *      $('#example').dataTable( {
10247                  *        "stateSave": true,
10248                  *        "stateLoadParams": function (settings, data) {
10249                  *          data.oSearch.sSearch = "";
10250                  *        }
10251                  *      } );
10252                  *    } );
10253                  *
10254                  *  @example
10255                  *    // Disallow state loading by returning false
10256                  *    $(document).ready( function() {
10257                  *      $('#example').dataTable( {
10258                  *        "stateSave": true,
10259                  *        "stateLoadParams": function (settings, data) {
10260                  *          return false;
10261                  *        }
10262                  *      } );
10263                  *    } );
10264                  */
10265                 "fnStateLoadParams": null,
10266         
10267         
10268                 /**
10269                  * Callback that is called when the state has been loaded from the state saving method
10270                  * and the DataTables settings object has been modified as a result of the loaded state.
10271                  *  @type function
10272                  *  @param {object} settings DataTables settings object
10273                  *  @param {object} data The state object that was loaded
10274                  *
10275                  *  @dtopt Callbacks
10276                  *  @name DataTable.defaults.stateLoaded
10277                  *
10278                  *  @example
10279                  *    // Show an alert with the filtering value that was saved
10280                  *    $(document).ready( function() {
10281                  *      $('#example').dataTable( {
10282                  *        "stateSave": true,
10283                  *        "stateLoaded": function (settings, data) {
10284                  *          alert( 'Saved filter was: '+data.oSearch.sSearch );
10285                  *        }
10286                  *      } );
10287                  *    } );
10288                  */
10289                 "fnStateLoaded": null,
10290         
10291         
10292                 /**
10293                  * Save the table state. This function allows you to define where and how the state
10294                  * information for the table is stored By default DataTables will use `localStorage`
10295                  * but you might wish to use a server-side database or cookies.
10296                  *  @type function
10297                  *  @member
10298                  *  @param {object} settings DataTables settings object
10299                  *  @param {object} data The state object to be saved
10300                  *
10301                  *  @dtopt Callbacks
10302                  *  @name DataTable.defaults.stateSaveCallback
10303                  *
10304                  *  @example
10305                  *    $(document).ready( function() {
10306                  *      $('#example').dataTable( {
10307                  *        "stateSave": true,
10308                  *        "stateSaveCallback": function (settings, data) {
10309                  *          // Send an Ajax request to the server with the state object
10310                  *          $.ajax( {
10311                  *            "url": "/state_save",
10312                  *            "data": data,
10313                  *            "dataType": "json",
10314                  *            "method": "POST"
10315                  *            "success": function () {}
10316                  *          } );
10317                  *        }
10318                  *      } );
10319                  *    } );
10320                  */
10321                 "fnStateSaveCallback": function ( settings, data ) {
10322                         try {
10323                                 (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
10324                                         'DataTables_'+settings.sInstance+'_'+location.pathname,
10325                                         JSON.stringify( data )
10326                                 );
10327                         } catch (e) {}
10328                 },
10329         
10330         
10331                 /**
10332                  * Callback which allows modification of the state to be saved. Called when the table
10333                  * has changed state a new state save is required. This method allows modification of
10334                  * the state saving object prior to actually doing the save, including addition or
10335                  * other state properties or modification. Note that for plug-in authors, you should
10336                  * use the `stateSaveParams` event to save parameters for a plug-in.
10337                  *  @type function
10338                  *  @param {object} settings DataTables settings object
10339                  *  @param {object} data The state object to be saved
10340                  *
10341                  *  @dtopt Callbacks
10342                  *  @name DataTable.defaults.stateSaveParams
10343                  *
10344                  *  @example
10345                  *    // Remove a saved filter, so filtering is never saved
10346                  *    $(document).ready( function() {
10347                  *      $('#example').dataTable( {
10348                  *        "stateSave": true,
10349                  *        "stateSaveParams": function (settings, data) {
10350                  *          data.oSearch.sSearch = "";
10351                  *        }
10352                  *      } );
10353                  *    } );
10354                  */
10355                 "fnStateSaveParams": null,
10356         
10357         
10358                 /**
10359                  * Duration for which the saved state information is considered valid. After this period
10360                  * has elapsed the state will be returned to the default.
10361                  * Value is given in seconds.
10362                  *  @type int
10363                  *  @default 7200 <i>(2 hours)</i>
10364                  *
10365                  *  @dtopt Options
10366                  *  @name DataTable.defaults.stateDuration
10367                  *
10368                  *  @example
10369                  *    $(document).ready( function() {
10370                  *      $('#example').dataTable( {
10371                  *        "stateDuration": 60*60*24; // 1 day
10372                  *      } );
10373                  *    } )
10374                  */
10375                 "iStateDuration": 7200,
10376         
10377         
10378                 /**
10379                  * When enabled DataTables will not make a request to the server for the first
10380                  * page draw - rather it will use the data already on the page (no sorting etc
10381                  * will be applied to it), thus saving on an XHR at load time. `deferLoading`
10382                  * is used to indicate that deferred loading is required, but it is also used
10383                  * to tell DataTables how many records there are in the full table (allowing
10384                  * the information element and pagination to be displayed correctly). In the case
10385                  * where a filtering is applied to the table on initial load, this can be
10386                  * indicated by giving the parameter as an array, where the first element is
10387                  * the number of records available after filtering and the second element is the
10388                  * number of records without filtering (allowing the table information element
10389                  * to be shown correctly).
10390                  *  @type int | array
10391                  *  @default null
10392                  *
10393                  *  @dtopt Options
10394                  *  @name DataTable.defaults.deferLoading
10395                  *
10396                  *  @example
10397                  *    // 57 records available in the table, no filtering applied
10398                  *    $(document).ready( function() {
10399                  *      $('#example').dataTable( {
10400                  *        "serverSide": true,
10401                  *        "ajax": "scripts/server_processing.php",
10402                  *        "deferLoading": 57
10403                  *      } );
10404                  *    } );
10405                  *
10406                  *  @example
10407                  *    // 57 records after filtering, 100 without filtering (an initial filter applied)
10408                  *    $(document).ready( function() {
10409                  *      $('#example').dataTable( {
10410                  *        "serverSide": true,
10411                  *        "ajax": "scripts/server_processing.php",
10412                  *        "deferLoading": [ 57, 100 ],
10413                  *        "search": {
10414                  *          "search": "my_filter"
10415                  *        }
10416                  *      } );
10417                  *    } );
10418                  */
10419                 "iDeferLoading": null,
10420         
10421         
10422                 /**
10423                  * Number of rows to display on a single page when using pagination. If
10424                  * feature enabled (`lengthChange`) then the end user will be able to override
10425                  * this to a custom setting using a pop-up menu.
10426                  *  @type int
10427                  *  @default 10
10428                  *
10429                  *  @dtopt Options
10430                  *  @name DataTable.defaults.pageLength
10431                  *
10432                  *  @example
10433                  *    $(document).ready( function() {
10434                  *      $('#example').dataTable( {
10435                  *        "pageLength": 50
10436                  *      } );
10437                  *    } )
10438                  */
10439                 "iDisplayLength": 10,
10440         
10441         
10442                 /**
10443                  * Define the starting point for data display when using DataTables with
10444                  * pagination. Note that this parameter is the number of records, rather than
10445                  * the page number, so if you have 10 records per page and want to start on
10446                  * the third page, it should be "20".
10447                  *  @type int
10448                  *  @default 0
10449                  *
10450                  *  @dtopt Options
10451                  *  @name DataTable.defaults.displayStart
10452                  *
10453                  *  @example
10454                  *    $(document).ready( function() {
10455                  *      $('#example').dataTable( {
10456                  *        "displayStart": 20
10457                  *      } );
10458                  *    } )
10459                  */
10460                 "iDisplayStart": 0,
10461         
10462         
10463                 /**
10464                  * By default DataTables allows keyboard navigation of the table (sorting, paging,
10465                  * and filtering) by adding a `tabindex` attribute to the required elements. This
10466                  * allows you to tab through the controls and press the enter key to activate them.
10467                  * The tabindex is default 0, meaning that the tab follows the flow of the document.
10468                  * You can overrule this using this parameter if you wish. Use a value of -1 to
10469                  * disable built-in keyboard navigation.
10470                  *  @type int
10471                  *  @default 0
10472                  *
10473                  *  @dtopt Options
10474                  *  @name DataTable.defaults.tabIndex
10475                  *
10476                  *  @example
10477                  *    $(document).ready( function() {
10478                  *      $('#example').dataTable( {
10479                  *        "tabIndex": 1
10480                  *      } );
10481                  *    } );
10482                  */
10483                 "iTabIndex": 0,
10484         
10485         
10486                 /**
10487                  * Classes that DataTables assigns to the various components and features
10488                  * that it adds to the HTML table. This allows classes to be configured
10489                  * during initialisation in addition to through the static
10490                  * {@link DataTable.ext.oStdClasses} object).
10491                  *  @namespace
10492                  *  @name DataTable.defaults.classes
10493                  */
10494                 "oClasses": {},
10495         
10496         
10497                 /**
10498                  * All strings that DataTables uses in the user interface that it creates
10499                  * are defined in this object, allowing you to modified them individually or
10500                  * completely replace them all as required.
10501                  *  @namespace
10502                  *  @name DataTable.defaults.language
10503                  */
10504                 "oLanguage": {
10505                         /**
10506                          * Strings that are used for WAI-ARIA labels and controls only (these are not
10507                          * actually visible on the page, but will be read by screenreaders, and thus
10508                          * must be internationalised as well).
10509                          *  @namespace
10510                          *  @name DataTable.defaults.language.aria
10511                          */
10512                         "oAria": {
10513                                 /**
10514                                  * ARIA label that is added to the table headers when the column may be
10515                                  * sorted ascending by activing the column (click or return when focused).
10516                                  * Note that the column header is prefixed to this string.
10517                                  *  @type string
10518                                  *  @default : activate to sort column ascending
10519                                  *
10520                                  *  @dtopt Language
10521                                  *  @name DataTable.defaults.language.aria.sortAscending
10522                                  *
10523                                  *  @example
10524                                  *    $(document).ready( function() {
10525                                  *      $('#example').dataTable( {
10526                                  *        "language": {
10527                                  *          "aria": {
10528                                  *            "sortAscending": " - click/return to sort ascending"
10529                                  *          }
10530                                  *        }
10531                                  *      } );
10532                                  *    } );
10533                                  */
10534                                 "sSortAscending": ": activate to sort column ascending",
10535         
10536                                 /**
10537                                  * ARIA label that is added to the table headers when the column may be
10538                                  * sorted descending by activing the column (click or return when focused).
10539                                  * Note that the column header is prefixed to this string.
10540                                  *  @type string
10541                                  *  @default : activate to sort column ascending
10542                                  *
10543                                  *  @dtopt Language
10544                                  *  @name DataTable.defaults.language.aria.sortDescending
10545                                  *
10546                                  *  @example
10547                                  *    $(document).ready( function() {
10548                                  *      $('#example').dataTable( {
10549                                  *        "language": {
10550                                  *          "aria": {
10551                                  *            "sortDescending": " - click/return to sort descending"
10552                                  *          }
10553                                  *        }
10554                                  *      } );
10555                                  *    } );
10556                                  */
10557                                 "sSortDescending": ": activate to sort column descending"
10558                         },
10559         
10560                         /**
10561                          * Pagination string used by DataTables for the built-in pagination
10562                          * control types.
10563                          *  @namespace
10564                          *  @name DataTable.defaults.language.paginate
10565                          */
10566                         "oPaginate": {
10567                                 /**
10568                                  * Text to use when using the 'full_numbers' type of pagination for the
10569                                  * button to take the user to the first page.
10570                                  *  @type string
10571                                  *  @default First
10572                                  *
10573                                  *  @dtopt Language
10574                                  *  @name DataTable.defaults.language.paginate.first
10575                                  *
10576                                  *  @example
10577                                  *    $(document).ready( function() {
10578                                  *      $('#example').dataTable( {
10579                                  *        "language": {
10580                                  *          "paginate": {
10581                                  *            "first": "First page"
10582                                  *          }
10583                                  *        }
10584                                  *      } );
10585                                  *    } );
10586                                  */
10587                                 "sFirst": "First",
10588         
10589         
10590                                 /**
10591                                  * Text to use when using the 'full_numbers' type of pagination for the
10592                                  * button to take the user to the last page.
10593                                  *  @type string
10594                                  *  @default Last
10595                                  *
10596                                  *  @dtopt Language
10597                                  *  @name DataTable.defaults.language.paginate.last
10598                                  *
10599                                  *  @example
10600                                  *    $(document).ready( function() {
10601                                  *      $('#example').dataTable( {
10602                                  *        "language": {
10603                                  *          "paginate": {
10604                                  *            "last": "Last page"
10605                                  *          }
10606                                  *        }
10607                                  *      } );
10608                                  *    } );
10609                                  */
10610                                 "sLast": "Last",
10611         
10612         
10613                                 /**
10614                                  * Text to use for the 'next' pagination button (to take the user to the
10615                                  * next page).
10616                                  *  @type string
10617                                  *  @default Next
10618                                  *
10619                                  *  @dtopt Language
10620                                  *  @name DataTable.defaults.language.paginate.next
10621                                  *
10622                                  *  @example
10623                                  *    $(document).ready( function() {
10624                                  *      $('#example').dataTable( {
10625                                  *        "language": {
10626                                  *          "paginate": {
10627                                  *            "next": "Next page"
10628                                  *          }
10629                                  *        }
10630                                  *      } );
10631                                  *    } );
10632                                  */
10633                                 "sNext": "Next",
10634         
10635         
10636                                 /**
10637                                  * Text to use for the 'previous' pagination button (to take the user to
10638                                  * the previous page).
10639                                  *  @type string
10640                                  *  @default Previous
10641                                  *
10642                                  *  @dtopt Language
10643                                  *  @name DataTable.defaults.language.paginate.previous
10644                                  *
10645                                  *  @example
10646                                  *    $(document).ready( function() {
10647                                  *      $('#example').dataTable( {
10648                                  *        "language": {
10649                                  *          "paginate": {
10650                                  *            "previous": "Previous page"
10651                                  *          }
10652                                  *        }
10653                                  *      } );
10654                                  *    } );
10655                                  */
10656                                 "sPrevious": "Previous"
10657                         },
10658         
10659                         /**
10660                          * This string is shown in preference to `zeroRecords` when the table is
10661                          * empty of data (regardless of filtering). Note that this is an optional
10662                          * parameter - if it is not given, the value of `zeroRecords` will be used
10663                          * instead (either the default or given value).
10664                          *  @type string
10665                          *  @default No data available in table
10666                          *
10667                          *  @dtopt Language
10668                          *  @name DataTable.defaults.language.emptyTable
10669                          *
10670                          *  @example
10671                          *    $(document).ready( function() {
10672                          *      $('#example').dataTable( {
10673                          *        "language": {
10674                          *          "emptyTable": "No data available in table"
10675                          *        }
10676                          *      } );
10677                          *    } );
10678                          */
10679                         "sEmptyTable": "No data available in table",
10680         
10681         
10682                         /**
10683                          * This string gives information to the end user about the information
10684                          * that is current on display on the page. The following tokens can be
10685                          * used in the string and will be dynamically replaced as the table
10686                          * display updates. This tokens can be placed anywhere in the string, or
10687                          * removed as needed by the language requires:
10688                          *
10689                          * * `\_START\_` - Display index of the first record on the current page
10690                          * * `\_END\_` - Display index of the last record on the current page
10691                          * * `\_TOTAL\_` - Number of records in the table after filtering
10692                          * * `\_MAX\_` - Number of records in the table without filtering
10693                          * * `\_PAGE\_` - Current page number
10694                          * * `\_PAGES\_` - Total number of pages of data in the table
10695                          *
10696                          *  @type string
10697                          *  @default Showing _START_ to _END_ of _TOTAL_ entries
10698                          *
10699                          *  @dtopt Language
10700                          *  @name DataTable.defaults.language.info
10701                          *
10702                          *  @example
10703                          *    $(document).ready( function() {
10704                          *      $('#example').dataTable( {
10705                          *        "language": {
10706                          *          "info": "Showing page _PAGE_ of _PAGES_"
10707                          *        }
10708                          *      } );
10709                          *    } );
10710                          */
10711                         "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
10712         
10713         
10714                         /**
10715                          * Display information string for when the table is empty. Typically the
10716                          * format of this string should match `info`.
10717                          *  @type string
10718                          *  @default Showing 0 to 0 of 0 entries
10719                          *
10720                          *  @dtopt Language
10721                          *  @name DataTable.defaults.language.infoEmpty
10722                          *
10723                          *  @example
10724                          *    $(document).ready( function() {
10725                          *      $('#example').dataTable( {
10726                          *        "language": {
10727                          *          "infoEmpty": "No entries to show"
10728                          *        }
10729                          *      } );
10730                          *    } );
10731                          */
10732                         "sInfoEmpty": "Showing 0 to 0 of 0 entries",
10733         
10734         
10735                         /**
10736                          * When a user filters the information in a table, this string is appended
10737                          * to the information (`info`) to give an idea of how strong the filtering
10738                          * is. The variable _MAX_ is dynamically updated.
10739                          *  @type string
10740                          *  @default (filtered from _MAX_ total entries)
10741                          *
10742                          *  @dtopt Language
10743                          *  @name DataTable.defaults.language.infoFiltered
10744                          *
10745                          *  @example
10746                          *    $(document).ready( function() {
10747                          *      $('#example').dataTable( {
10748                          *        "language": {
10749                          *          "infoFiltered": " - filtering from _MAX_ records"
10750                          *        }
10751                          *      } );
10752                          *    } );
10753                          */
10754                         "sInfoFiltered": "(filtered from _MAX_ total entries)",
10755         
10756         
10757                         /**
10758                          * If can be useful to append extra information to the info string at times,
10759                          * and this variable does exactly that. This information will be appended to
10760                          * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
10761                          * being used) at all times.
10762                          *  @type string
10763                          *  @default <i>Empty string</i>
10764                          *
10765                          *  @dtopt Language
10766                          *  @name DataTable.defaults.language.infoPostFix
10767                          *
10768                          *  @example
10769                          *    $(document).ready( function() {
10770                          *      $('#example').dataTable( {
10771                          *        "language": {
10772                          *          "infoPostFix": "All records shown are derived from real information."
10773                          *        }
10774                          *      } );
10775                          *    } );
10776                          */
10777                         "sInfoPostFix": "",
10778         
10779         
10780                         /**
10781                          * This decimal place operator is a little different from the other
10782                          * language options since DataTables doesn't output floating point
10783                          * numbers, so it won't ever use this for display of a number. Rather,
10784                          * what this parameter does is modify the sort methods of the table so
10785                          * that numbers which are in a format which has a character other than
10786                          * a period (`.`) as a decimal place will be sorted numerically.
10787                          *
10788                          * Note that numbers with different decimal places cannot be shown in
10789                          * the same table and still be sortable, the table must be consistent.
10790                          * However, multiple different tables on the page can use different
10791                          * decimal place characters.
10792                          *  @type string
10793                          *  @default 
10794                          *
10795                          *  @dtopt Language
10796                          *  @name DataTable.defaults.language.decimal
10797                          *
10798                          *  @example
10799                          *    $(document).ready( function() {
10800                          *      $('#example').dataTable( {
10801                          *        "language": {
10802                          *          "decimal": ","
10803                          *          "thousands": "."
10804                          *        }
10805                          *      } );
10806                          *    } );
10807                          */
10808                         "sDecimal": "",
10809         
10810         
10811                         /**
10812                          * DataTables has a build in number formatter (`formatNumber`) which is
10813                          * used to format large numbers that are used in the table information.
10814                          * By default a comma is used, but this can be trivially changed to any
10815                          * character you wish with this parameter.
10816                          *  @type string
10817                          *  @default ,
10818                          *
10819                          *  @dtopt Language
10820                          *  @name DataTable.defaults.language.thousands
10821                          *
10822                          *  @example
10823                          *    $(document).ready( function() {
10824                          *      $('#example').dataTable( {
10825                          *        "language": {
10826                          *          "thousands": "'"
10827                          *        }
10828                          *      } );
10829                          *    } );
10830                          */
10831                         "sThousands": ",",
10832         
10833         
10834                         /**
10835                          * Detail the action that will be taken when the drop down menu for the
10836                          * pagination length option is changed. The '_MENU_' variable is replaced
10837                          * with a default select list of 10, 25, 50 and 100, and can be replaced
10838                          * with a custom select box if required.
10839                          *  @type string
10840                          *  @default Show _MENU_ entries
10841                          *
10842                          *  @dtopt Language
10843                          *  @name DataTable.defaults.language.lengthMenu
10844                          *
10845                          *  @example
10846                          *    // Language change only
10847                          *    $(document).ready( function() {
10848                          *      $('#example').dataTable( {
10849                          *        "language": {
10850                          *          "lengthMenu": "Display _MENU_ records"
10851                          *        }
10852                          *      } );
10853                          *    } );
10854                          *
10855                          *  @example
10856                          *    // Language and options change
10857                          *    $(document).ready( function() {
10858                          *      $('#example').dataTable( {
10859                          *        "language": {
10860                          *          "lengthMenu": 'Display <select>'+
10861                          *            '<option value="10">10</option>'+
10862                          *            '<option value="20">20</option>'+
10863                          *            '<option value="30">30</option>'+
10864                          *            '<option value="40">40</option>'+
10865                          *            '<option value="50">50</option>'+
10866                          *            '<option value="-1">All</option>'+
10867                          *            '</select> records'
10868                          *        }
10869                          *      } );
10870                          *    } );
10871                          */
10872                         "sLengthMenu": "Show _MENU_ entries",
10873         
10874         
10875                         /**
10876                          * When using Ajax sourced data and during the first draw when DataTables is
10877                          * gathering the data, this message is shown in an empty row in the table to
10878                          * indicate to the end user the the data is being loaded. Note that this
10879                          * parameter is not used when loading data by server-side processing, just
10880                          * Ajax sourced data with client-side processing.
10881                          *  @type string
10882                          *  @default Loading...
10883                          *
10884                          *  @dtopt Language
10885                          *  @name DataTable.defaults.language.loadingRecords
10886                          *
10887                          *  @example
10888                          *    $(document).ready( function() {
10889                          *      $('#example').dataTable( {
10890                          *        "language": {
10891                          *          "loadingRecords": "Please wait - loading..."
10892                          *        }
10893                          *      } );
10894                          *    } );
10895                          */
10896                         "sLoadingRecords": "Loading...",
10897         
10898         
10899                         /**
10900                          * Text which is displayed when the table is processing a user action
10901                          * (usually a sort command or similar).
10902                          *  @type string
10903                          *  @default Processing...
10904                          *
10905                          *  @dtopt Language
10906                          *  @name DataTable.defaults.language.processing
10907                          *
10908                          *  @example
10909                          *    $(document).ready( function() {
10910                          *      $('#example').dataTable( {
10911                          *        "language": {
10912                          *          "processing": "DataTables is currently busy"
10913                          *        }
10914                          *      } );
10915                          *    } );
10916                          */
10917                         "sProcessing": "Processing...",
10918         
10919         
10920                         /**
10921                          * Details the actions that will be taken when the user types into the
10922                          * filtering input text box. The variable "_INPUT_", if used in the string,
10923                          * is replaced with the HTML text box for the filtering input allowing
10924                          * control over where it appears in the string. If "_INPUT_" is not given
10925                          * then the input box is appended to the string automatically.
10926                          *  @type string
10927                          *  @default Search:
10928                          *
10929                          *  @dtopt Language
10930                          *  @name DataTable.defaults.language.search
10931                          *
10932                          *  @example
10933                          *    // Input text box will be appended at the end automatically
10934                          *    $(document).ready( function() {
10935                          *      $('#example').dataTable( {
10936                          *        "language": {
10937                          *          "search": "Filter records:"
10938                          *        }
10939                          *      } );
10940                          *    } );
10941                          *
10942                          *  @example
10943                          *    // Specify where the filter should appear
10944                          *    $(document).ready( function() {
10945                          *      $('#example').dataTable( {
10946                          *        "language": {
10947                          *          "search": "Apply filter _INPUT_ to table"
10948                          *        }
10949                          *      } );
10950                          *    } );
10951                          */
10952                         "sSearch": "Search:",
10953         
10954         
10955                         /**
10956                          * All of the language information can be stored in a file on the
10957                          * server-side, which DataTables will look up if this parameter is passed.
10958                          * It must store the URL of the language file, which is in a JSON format,
10959                          * and the object has the same properties as the oLanguage object in the
10960                          * initialiser object (i.e. the above parameters). Please refer to one of
10961                          * the example language files to see how this works in action.
10962                          *  @type string
10963                          *  @default <i>Empty string - i.e. disabled</i>
10964                          *
10965                          *  @dtopt Language
10966                          *  @name DataTable.defaults.language.url
10967                          *
10968                          *  @example
10969                          *    $(document).ready( function() {
10970                          *      $('#example').dataTable( {
10971                          *        "language": {
10972                          *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
10973                          *        }
10974                          *      } );
10975                          *    } );
10976                          */
10977                         "sUrl": "",
10978         
10979         
10980                         /**
10981                          * Text shown inside the table records when the is no information to be
10982                          * displayed after filtering. `emptyTable` is shown when there is simply no
10983                          * information in the table at all (regardless of filtering).
10984                          *  @type string
10985                          *  @default No matching records found
10986                          *
10987                          *  @dtopt Language
10988                          *  @name DataTable.defaults.language.zeroRecords
10989                          *
10990                          *  @example
10991                          *    $(document).ready( function() {
10992                          *      $('#example').dataTable( {
10993                          *        "language": {
10994                          *          "zeroRecords": "No records to display"
10995                          *        }
10996                          *      } );
10997                          *    } );
10998                          */
10999                         "sZeroRecords": "No matching records found"
11000                 },
11001         
11002         
11003                 /**
11004                  * This parameter allows you to have define the global filtering state at
11005                  * initialisation time. As an object the `search` parameter must be
11006                  * defined, but all other parameters are optional. When `regex` is true,
11007                  * the search string will be treated as a regular expression, when false
11008                  * (default) it will be treated as a straight string. When `smart`
11009                  * DataTables will use it's smart filtering methods (to word match at
11010                  * any point in the data), when false this will not be done.
11011                  *  @namespace
11012                  *  @extends DataTable.models.oSearch
11013                  *
11014                  *  @dtopt Options
11015                  *  @name DataTable.defaults.search
11016                  *
11017                  *  @example
11018                  *    $(document).ready( function() {
11019                  *      $('#example').dataTable( {
11020                  *        "search": {"search": "Initial search"}
11021                  *      } );
11022                  *    } )
11023                  */
11024                 "oSearch": $.extend( {}, DataTable.models.oSearch ),
11025         
11026         
11027                 /**
11028                  * __Deprecated__ The functionality provided by this parameter has now been
11029                  * superseded by that provided through `ajax`, which should be used instead.
11030                  *
11031                  * By default DataTables will look for the property `data` (or `aaData` for
11032                  * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11033                  * source or for server-side processing - this parameter allows that
11034                  * property to be changed. You can use Javascript dotted object notation to
11035                  * get a data source for multiple levels of nesting.
11036                  *  @type string
11037                  *  @default data
11038                  *
11039                  *  @dtopt Options
11040                  *  @dtopt Server-side
11041                  *  @name DataTable.defaults.ajaxDataProp
11042                  *
11043                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
11044                  */
11045                 "sAjaxDataProp": "data",
11046         
11047         
11048                 /**
11049                  * __Deprecated__ The functionality provided by this parameter has now been
11050                  * superseded by that provided through `ajax`, which should be used instead.
11051                  *
11052                  * You can instruct DataTables to load data from an external
11053                  * source using this parameter (use aData if you want to pass data in you
11054                  * already have). Simply provide a url a JSON object can be obtained from.
11055                  *  @type string
11056                  *  @default null
11057                  *
11058                  *  @dtopt Options
11059                  *  @dtopt Server-side
11060                  *  @name DataTable.defaults.ajaxSource
11061                  *
11062                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
11063                  */
11064                 "sAjaxSource": null,
11065         
11066         
11067                 /**
11068                  * This initialisation variable allows you to specify exactly where in the
11069                  * DOM you want DataTables to inject the various controls it adds to the page
11070                  * (for example you might want the pagination controls at the top of the
11071                  * table). DIV elements (with or without a custom class) can also be added to
11072                  * aid styling. The follow syntax is used:
11073                  *   <ul>
11074                  *     <li>The following options are allowed:
11075                  *       <ul>
11076                  *         <li>'l' - Length changing</li>
11077                  *         <li>'f' - Filtering input</li>
11078                  *         <li>'t' - The table!</li>
11079                  *         <li>'i' - Information</li>
11080                  *         <li>'p' - Pagination</li>
11081                  *         <li>'r' - pRocessing</li>
11082                  *       </ul>
11083                  *     </li>
11084                  *     <li>The following constants are allowed:
11085                  *       <ul>
11086                  *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11087                  *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11088                  *       </ul>
11089                  *     </li>
11090                  *     <li>The following syntax is expected:
11091                  *       <ul>
11092                  *         <li>'&lt;' and '&gt;' - div elements</li>
11093                  *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11094                  *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11095                  *       </ul>
11096                  *     </li>
11097                  *     <li>Examples:
11098                  *       <ul>
11099                  *         <li>'&lt;"wrapper"flipt&gt;'</li>
11100                  *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11101                  *       </ul>
11102                  *     </li>
11103                  *   </ul>
11104                  *  @type string
11105                  *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11106                  *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11107                  *
11108                  *  @dtopt Options
11109                  *  @name DataTable.defaults.dom
11110                  *
11111                  *  @example
11112                  *    $(document).ready( function() {
11113                  *      $('#example').dataTable( {
11114                  *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11115                  *      } );
11116                  *    } );
11117                  */
11118                 "sDom": "lfrtip",
11119         
11120         
11121                 /**
11122                  * DataTables features four different built-in options for the buttons to
11123                  * display for pagination control:
11124                  *
11125                  * * `simple` - 'Previous' and 'Next' buttons only
11126                  * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11127                  * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11128                  * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus
11129                  *   page numbers
11130                  *  
11131                  * Further methods can be added using {@link DataTable.ext.oPagination}.
11132                  *  @type string
11133                  *  @default simple_numbers
11134                  *
11135                  *  @dtopt Options
11136                  *  @name DataTable.defaults.pagingType
11137                  *
11138                  *  @example
11139                  *    $(document).ready( function() {
11140                  *      $('#example').dataTable( {
11141                  *        "pagingType": "full_numbers"
11142                  *      } );
11143                  *    } )
11144                  */
11145                 "sPaginationType": "simple_numbers",
11146         
11147         
11148                 /**
11149                  * Enable horizontal scrolling. When a table is too wide to fit into a
11150                  * certain layout, or you have a large number of columns in the table, you
11151                  * can enable x-scrolling to show the table in a viewport, which can be
11152                  * scrolled. This property can be `true` which will allow the table to
11153                  * scroll horizontally when needed, or any CSS unit, or a number (in which
11154                  * case it will be treated as a pixel measurement). Setting as simply `true`
11155                  * is recommended.
11156                  *  @type boolean|string
11157                  *  @default <i>blank string - i.e. disabled</i>
11158                  *
11159                  *  @dtopt Features
11160                  *  @name DataTable.defaults.scrollX
11161                  *
11162                  *  @example
11163                  *    $(document).ready( function() {
11164                  *      $('#example').dataTable( {
11165                  *        "scrollX": true,
11166                  *        "scrollCollapse": true
11167                  *      } );
11168                  *    } );
11169                  */
11170                 "sScrollX": "",
11171         
11172         
11173                 /**
11174                  * This property can be used to force a DataTable to use more width than it
11175                  * might otherwise do when x-scrolling is enabled. For example if you have a
11176                  * table which requires to be well spaced, this parameter is useful for
11177                  * "over-sizing" the table, and thus forcing scrolling. This property can by
11178                  * any CSS unit, or a number (in which case it will be treated as a pixel
11179                  * measurement).
11180                  *  @type string
11181                  *  @default <i>blank string - i.e. disabled</i>
11182                  *
11183                  *  @dtopt Options
11184                  *  @name DataTable.defaults.scrollXInner
11185                  *
11186                  *  @example
11187                  *    $(document).ready( function() {
11188                  *      $('#example').dataTable( {
11189                  *        "scrollX": "100%",
11190                  *        "scrollXInner": "110%"
11191                  *      } );
11192                  *    } );
11193                  */
11194                 "sScrollXInner": "",
11195         
11196         
11197                 /**
11198                  * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
11199                  * to the given height, and enable scrolling for any data which overflows the
11200                  * current viewport. This can be used as an alternative to paging to display
11201                  * a lot of data in a small area (although paging and scrolling can both be
11202                  * enabled at the same time). This property can be any CSS unit, or a number
11203                  * (in which case it will be treated as a pixel measurement).
11204                  *  @type string
11205                  *  @default <i>blank string - i.e. disabled</i>
11206                  *
11207                  *  @dtopt Features
11208                  *  @name DataTable.defaults.scrollY
11209                  *
11210                  *  @example
11211                  *    $(document).ready( function() {
11212                  *      $('#example').dataTable( {
11213                  *        "scrollY": "200px",
11214                  *        "paginate": false
11215                  *      } );
11216                  *    } );
11217                  */
11218                 "sScrollY": "",
11219         
11220         
11221                 /**
11222                  * __Deprecated__ The functionality provided by this parameter has now been
11223                  * superseded by that provided through `ajax`, which should be used instead.
11224                  *
11225                  * Set the HTTP method that is used to make the Ajax call for server-side
11226                  * processing or Ajax sourced data.
11227                  *  @type string
11228                  *  @default GET
11229                  *
11230                  *  @dtopt Options
11231                  *  @dtopt Server-side
11232                  *  @name DataTable.defaults.serverMethod
11233                  *
11234                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
11235                  */
11236                 "sServerMethod": "GET",
11237         
11238         
11239                 /**
11240                  * DataTables makes use of renderers when displaying HTML elements for
11241                  * a table. These renderers can be added or modified by plug-ins to
11242                  * generate suitable mark-up for a site. For example the Bootstrap
11243                  * integration plug-in for DataTables uses a paging button renderer to
11244                  * display pagination buttons in the mark-up required by Bootstrap.
11245                  *
11246                  * For further information about the renderers available see
11247                  * DataTable.ext.renderer
11248                  *  @type string|object
11249                  *  @default null
11250                  *
11251                  *  @name DataTable.defaults.renderer
11252                  *
11253                  */
11254                 "renderer": null
11255         };
11256         
11257         _fnHungarianMap( DataTable.defaults );
11258         
11259         
11260         
11261         /*
11262          * Developer note - See note in model.defaults.js about the use of Hungarian
11263          * notation and camel case.
11264          */
11265         
11266         /**
11267          * Column options that can be given to DataTables at initialisation time.
11268          *  @namespace
11269          */
11270         DataTable.defaults.column = {
11271                 /**
11272                  * Define which column(s) an order will occur on for this column. This
11273                  * allows a column's ordering to take multiple columns into account when
11274                  * doing a sort or use the data from a different column. For example first
11275                  * name / last name columns make sense to do a multi-column sort over the
11276                  * two columns.
11277                  *  @type array|int
11278                  *  @default null <i>Takes the value of the column index automatically</i>
11279                  *
11280                  *  @name DataTable.defaults.column.orderData
11281                  *  @dtopt Columns
11282                  *
11283                  *  @example
11284                  *    // Using `columnDefs`
11285                  *    $(document).ready( function() {
11286                  *      $('#example').dataTable( {
11287                  *        "columnDefs": [
11288                  *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
11289                  *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
11290                  *          { "orderData": 2, "targets": [ 2 ] }
11291                  *        ]
11292                  *      } );
11293                  *    } );
11294                  *
11295                  *  @example
11296                  *    // Using `columns`
11297                  *    $(document).ready( function() {
11298                  *      $('#example').dataTable( {
11299                  *        "columns": [
11300                  *          { "orderData": [ 0, 1 ] },
11301                  *          { "orderData": [ 1, 0 ] },
11302                  *          { "orderData": 2 },
11303                  *          null,
11304                  *          null
11305                  *        ]
11306                  *      } );
11307                  *    } );
11308                  */
11309                 "aDataSort": null,
11310                 "iDataSort": -1,
11311         
11312         
11313                 /**
11314                  * You can control the default ordering direction, and even alter the
11315                  * behaviour of the sort handler (i.e. only allow ascending ordering etc)
11316                  * using this parameter.
11317                  *  @type array
11318                  *  @default [ 'asc', 'desc' ]
11319                  *
11320                  *  @name DataTable.defaults.column.orderSequence
11321                  *  @dtopt Columns
11322                  *
11323                  *  @example
11324                  *    // Using `columnDefs`
11325                  *    $(document).ready( function() {
11326                  *      $('#example').dataTable( {
11327                  *        "columnDefs": [
11328                  *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
11329                  *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
11330                  *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
11331                  *        ]
11332                  *      } );
11333                  *    } );
11334                  *
11335                  *  @example
11336                  *    // Using `columns`
11337                  *    $(document).ready( function() {
11338                  *      $('#example').dataTable( {
11339                  *        "columns": [
11340                  *          null,
11341                  *          { "orderSequence": [ "asc" ] },
11342                  *          { "orderSequence": [ "desc", "asc", "asc" ] },
11343                  *          { "orderSequence": [ "desc" ] },
11344                  *          null
11345                  *        ]
11346                  *      } );
11347                  *    } );
11348                  */
11349                 "asSorting": [ 'asc', 'desc' ],
11350         
11351         
11352                 /**
11353                  * Enable or disable filtering on the data in this column.
11354                  *  @type boolean
11355                  *  @default true
11356                  *
11357                  *  @name DataTable.defaults.column.searchable
11358                  *  @dtopt Columns
11359                  *
11360                  *  @example
11361                  *    // Using `columnDefs`
11362                  *    $(document).ready( function() {
11363                  *      $('#example').dataTable( {
11364                  *        "columnDefs": [
11365                  *          { "searchable": false, "targets": [ 0 ] }
11366                  *        ] } );
11367                  *    } );
11368                  *
11369                  *  @example
11370                  *    // Using `columns`
11371                  *    $(document).ready( function() {
11372                  *      $('#example').dataTable( {
11373                  *        "columns": [
11374                  *          { "searchable": false },
11375                  *          null,
11376                  *          null,
11377                  *          null,
11378                  *          null
11379                  *        ] } );
11380                  *    } );
11381                  */
11382                 "bSearchable": true,
11383         
11384         
11385                 /**
11386                  * Enable or disable ordering on this column.
11387                  *  @type boolean
11388                  *  @default true
11389                  *
11390                  *  @name DataTable.defaults.column.orderable
11391                  *  @dtopt Columns
11392                  *
11393                  *  @example
11394                  *    // Using `columnDefs`
11395                  *    $(document).ready( function() {
11396                  *      $('#example').dataTable( {
11397                  *        "columnDefs": [
11398                  *          { "orderable": false, "targets": [ 0 ] }
11399                  *        ] } );
11400                  *    } );
11401                  *
11402                  *  @example
11403                  *    // Using `columns`
11404                  *    $(document).ready( function() {
11405                  *      $('#example').dataTable( {
11406                  *        "columns": [
11407                  *          { "orderable": false },
11408                  *          null,
11409                  *          null,
11410                  *          null,
11411                  *          null
11412                  *        ] } );
11413                  *    } );
11414                  */
11415                 "bSortable": true,
11416         
11417         
11418                 /**
11419                  * Enable or disable the display of this column.
11420                  *  @type boolean
11421                  *  @default true
11422                  *
11423                  *  @name DataTable.defaults.column.visible
11424                  *  @dtopt Columns
11425                  *
11426                  *  @example
11427                  *    // Using `columnDefs`
11428                  *    $(document).ready( function() {
11429                  *      $('#example').dataTable( {
11430                  *        "columnDefs": [
11431                  *          { "visible": false, "targets": [ 0 ] }
11432                  *        ] } );
11433                  *    } );
11434                  *
11435                  *  @example
11436                  *    // Using `columns`
11437                  *    $(document).ready( function() {
11438                  *      $('#example').dataTable( {
11439                  *        "columns": [
11440                  *          { "visible": false },
11441                  *          null,
11442                  *          null,
11443                  *          null,
11444                  *          null
11445                  *        ] } );
11446                  *    } );
11447                  */
11448                 "bVisible": true,
11449         
11450         
11451                 /**
11452                  * Developer definable function that is called whenever a cell is created (Ajax source,
11453                  * etc) or processed for input (DOM source). This can be used as a compliment to mRender
11454                  * allowing you to modify the DOM element (add background colour for example) when the
11455                  * element is available.
11456                  *  @type function
11457                  *  @param {element} td The TD node that has been created
11458                  *  @param {*} cellData The Data for the cell
11459                  *  @param {array|object} rowData The data for the whole row
11460                  *  @param {int} row The row index for the aoData data store
11461                  *  @param {int} col The column index for aoColumns
11462                  *
11463                  *  @name DataTable.defaults.column.createdCell
11464                  *  @dtopt Columns
11465                  *
11466                  *  @example
11467                  *    $(document).ready( function() {
11468                  *      $('#example').dataTable( {
11469                  *        "columnDefs": [ {
11470                  *          "targets": [3],
11471                  *          "createdCell": function (td, cellData, rowData, row, col) {
11472                  *            if ( cellData == "1.7" ) {
11473                  *              $(td).css('color', 'blue')
11474                  *            }
11475                  *          }
11476                  *        } ]
11477                  *      });
11478                  *    } );
11479                  */
11480                 "fnCreatedCell": null,
11481         
11482         
11483                 /**
11484                  * This parameter has been replaced by `data` in DataTables to ensure naming
11485                  * consistency. `dataProp` can still be used, as there is backwards
11486                  * compatibility in DataTables for this option, but it is strongly
11487                  * recommended that you use `data` in preference to `dataProp`.
11488                  *  @name DataTable.defaults.column.dataProp
11489                  */
11490         
11491         
11492                 /**
11493                  * This property can be used to read data from any data source property,
11494                  * including deeply nested objects / properties. `data` can be given in a
11495                  * number of different ways which effect its behaviour:
11496                  *
11497                  * * `integer` - treated as an array index for the data source. This is the
11498                  *   default that DataTables uses (incrementally increased for each column).
11499                  * * `string` - read an object property from the data source. There are
11500                  *   three 'special' options that can be used in the string to alter how
11501                  *   DataTables reads the data from the source object:
11502                  *    * `.` - Dotted Javascript notation. Just as you use a `.` in
11503                  *      Javascript to read from nested objects, so to can the options
11504                  *      specified in `data`. For example: `browser.version` or
11505                  *      `browser.name`. If your object parameter name contains a period, use
11506                  *      `\\` to escape it - i.e. `first\\.name`.
11507                  *    * `[]` - Array notation. DataTables can automatically combine data
11508                  *      from and array source, joining the data with the characters provided
11509                  *      between the two brackets. For example: `name[, ]` would provide a
11510                  *      comma-space separated list from the source array. If no characters
11511                  *      are provided between the brackets, the original array source is
11512                  *      returned.
11513                  *    * `()` - Function notation. Adding `()` to the end of a parameter will
11514                  *      execute a function of the name given. For example: `browser()` for a
11515                  *      simple function on the data source, `browser.version()` for a
11516                  *      function in a nested property or even `browser().version` to get an
11517                  *      object property if the function called returns an object. Note that
11518                  *      function notation is recommended for use in `render` rather than
11519                  *      `data` as it is much simpler to use as a renderer.
11520                  * * `null` - use the original data source for the row rather than plucking
11521                  *   data directly from it. This action has effects on two other
11522                  *   initialisation options:
11523                  *    * `defaultContent` - When null is given as the `data` option and
11524                  *      `defaultContent` is specified for the column, the value defined by
11525                  *      `defaultContent` will be used for the cell.
11526                  *    * `render` - When null is used for the `data` option and the `render`
11527                  *      option is specified for the column, the whole data source for the
11528                  *      row is used for the renderer.
11529                  * * `function` - the function given will be executed whenever DataTables
11530                  *   needs to set or get the data for a cell in the column. The function
11531                  *   takes three parameters:
11532                  *    * Parameters:
11533                  *      * `{array|object}` The data source for the row
11534                  *      * `{string}` The type call data requested - this will be 'set' when
11535                  *        setting data or 'filter', 'display', 'type', 'sort' or undefined
11536                  *        when gathering data. Note that when `undefined` is given for the
11537                  *        type DataTables expects to get the raw data for the object back<
11538                  *      * `{*}` Data to set when the second parameter is 'set'.
11539                  *    * Return:
11540                  *      * The return value from the function is not required when 'set' is
11541                  *        the type of call, but otherwise the return is what will be used
11542                  *        for the data requested.
11543                  *
11544                  * Note that `data` is a getter and setter option. If you just require
11545                  * formatting of data for output, you will likely want to use `render` which
11546                  * is simply a getter and thus simpler to use.
11547                  *
11548                  * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
11549                  * name change reflects the flexibility of this property and is consistent
11550                  * with the naming of mRender. If 'mDataProp' is given, then it will still
11551                  * be used by DataTables, as it automatically maps the old name to the new
11552                  * if required.
11553                  *
11554                  *  @type string|int|function|null
11555                  *  @default null <i>Use automatically calculated column index</i>
11556                  *
11557                  *  @name DataTable.defaults.column.data
11558                  *  @dtopt Columns
11559                  *
11560                  *  @example
11561                  *    // Read table data from objects
11562                  *    // JSON structure for each row:
11563                  *    //   {
11564                  *    //      "engine": {value},
11565                  *    //      "browser": {value},
11566                  *    //      "platform": {value},
11567                  *    //      "version": {value},
11568                  *    //      "grade": {value}
11569                  *    //   }
11570                  *    $(document).ready( function() {
11571                  *      $('#example').dataTable( {
11572                  *        "ajaxSource": "sources/objects.txt",
11573                  *        "columns": [
11574                  *          { "data": "engine" },
11575                  *          { "data": "browser" },
11576                  *          { "data": "platform" },
11577                  *          { "data": "version" },
11578                  *          { "data": "grade" }
11579                  *        ]
11580                  *      } );
11581                  *    } );
11582                  *
11583                  *  @example
11584                  *    // Read information from deeply nested objects
11585                  *    // JSON structure for each row:
11586                  *    //   {
11587                  *    //      "engine": {value},
11588                  *    //      "browser": {value},
11589                  *    //      "platform": {
11590                  *    //         "inner": {value}
11591                  *    //      },
11592                  *    //      "details": [
11593                  *    //         {value}, {value}
11594                  *    //      ]
11595                  *    //   }
11596                  *    $(document).ready( function() {
11597                  *      $('#example').dataTable( {
11598                  *        "ajaxSource": "sources/deep.txt",
11599                  *        "columns": [
11600                  *          { "data": "engine" },
11601                  *          { "data": "browser" },
11602                  *          { "data": "platform.inner" },
11603                  *          { "data": "platform.details.0" },
11604                  *          { "data": "platform.details.1" }
11605                  *        ]
11606                  *      } );
11607                  *    } );
11608                  *
11609                  *  @example
11610                  *    // Using `data` as a function to provide different information for
11611                  *    // sorting, filtering and display. In this case, currency (price)
11612                  *    $(document).ready( function() {
11613                  *      $('#example').dataTable( {
11614                  *        "columnDefs": [ {
11615                  *          "targets": [ 0 ],
11616                  *          "data": function ( source, type, val ) {
11617                  *            if (type === 'set') {
11618                  *              source.price = val;
11619                  *              // Store the computed dislay and filter values for efficiency
11620                  *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
11621                  *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
11622                  *              return;
11623                  *            }
11624                  *            else if (type === 'display') {
11625                  *              return source.price_display;
11626                  *            }
11627                  *            else if (type === 'filter') {
11628                  *              return source.price_filter;
11629                  *            }
11630                  *            // 'sort', 'type' and undefined all just use the integer
11631                  *            return source.price;
11632                  *          }
11633                  *        } ]
11634                  *      } );
11635                  *    } );
11636                  *
11637                  *  @example
11638                  *    // Using default content
11639                  *    $(document).ready( function() {
11640                  *      $('#example').dataTable( {
11641                  *        "columnDefs": [ {
11642                  *          "targets": [ 0 ],
11643                  *          "data": null,
11644                  *          "defaultContent": "Click to edit"
11645                  *        } ]
11646                  *      } );
11647                  *    } );
11648                  *
11649                  *  @example
11650                  *    // Using array notation - outputting a list from an array
11651                  *    $(document).ready( function() {
11652                  *      $('#example').dataTable( {
11653                  *        "columnDefs": [ {
11654                  *          "targets": [ 0 ],
11655                  *          "data": "name[, ]"
11656                  *        } ]
11657                  *      } );
11658                  *    } );
11659                  *
11660                  */
11661                 "mData": null,
11662         
11663         
11664                 /**
11665                  * This property is the rendering partner to `data` and it is suggested that
11666                  * when you want to manipulate data for display (including filtering,
11667                  * sorting etc) without altering the underlying data for the table, use this
11668                  * property. `render` can be considered to be the the read only companion to
11669                  * `data` which is read / write (then as such more complex). Like `data`
11670                  * this option can be given in a number of different ways to effect its
11671                  * behaviour:
11672                  *
11673                  * * `integer` - treated as an array index for the data source. This is the
11674                  *   default that DataTables uses (incrementally increased for each column).
11675                  * * `string` - read an object property from the data source. There are
11676                  *   three 'special' options that can be used in the string to alter how
11677                  *   DataTables reads the data from the source object:
11678                  *    * `.` - Dotted Javascript notation. Just as you use a `.` in
11679                  *      Javascript to read from nested objects, so to can the options
11680                  *      specified in `data`. For example: `browser.version` or
11681                  *      `browser.name`. If your object parameter name contains a period, use
11682                  *      `\\` to escape it - i.e. `first\\.name`.
11683                  *    * `[]` - Array notation. DataTables can automatically combine data
11684                  *      from and array source, joining the data with the characters provided
11685                  *      between the two brackets. For example: `name[, ]` would provide a
11686                  *      comma-space separated list from the source array. If no characters
11687                  *      are provided between the brackets, the original array source is
11688                  *      returned.
11689                  *    * `()` - Function notation. Adding `()` to the end of a parameter will
11690                  *      execute a function of the name given. For example: `browser()` for a
11691                  *      simple function on the data source, `browser.version()` for a
11692                  *      function in a nested property or even `browser().version` to get an
11693                  *      object property if the function called returns an object.
11694                  * * `object` - use different data for the different data types requested by
11695                  *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
11696                  *   of the object is the data type the property refers to and the value can
11697                  *   defined using an integer, string or function using the same rules as
11698                  *   `render` normally does. Note that an `_` option _must_ be specified.
11699                  *   This is the default value to use if you haven't specified a value for
11700                  *   the data type requested by DataTables.
11701                  * * `function` - the function given will be executed whenever DataTables
11702                  *   needs to set or get the data for a cell in the column. The function
11703                  *   takes three parameters:
11704                  *    * Parameters:
11705                  *      * {array|object} The data source for the row (based on `data`)
11706                  *      * {string} The type call data requested - this will be 'filter',
11707                  *        'display', 'type' or 'sort'.
11708                  *      * {array|object} The full data source for the row (not based on
11709                  *        `data`)
11710                  *    * Return:
11711                  *      * The return value from the function is what will be used for the
11712                  *        data requested.
11713                  *
11714                  *  @type string|int|function|object|null
11715                  *  @default null Use the data source value.
11716                  *
11717                  *  @name DataTable.defaults.column.render
11718                  *  @dtopt Columns
11719                  *
11720                  *  @example
11721                  *    // Create a comma separated list from an array of objects
11722                  *    $(document).ready( function() {
11723                  *      $('#example').dataTable( {
11724                  *        "ajaxSource": "sources/deep.txt",
11725                  *        "columns": [
11726                  *          { "data": "engine" },
11727                  *          { "data": "browser" },
11728                  *          {
11729                  *            "data": "platform",
11730                  *            "render": "[, ].name"
11731                  *          }
11732                  *        ]
11733                  *      } );
11734                  *    } );
11735                  *
11736                  *  @example
11737                  *    // Execute a function to obtain data
11738                  *    $(document).ready( function() {
11739                  *      $('#example').dataTable( {
11740                  *        "columnDefs": [ {
11741                  *          "targets": [ 0 ],
11742                  *          "data": null, // Use the full data source object for the renderer's source
11743                  *          "render": "browserName()"
11744                  *        } ]
11745                  *      } );
11746                  *    } );
11747                  *
11748                  *  @example
11749                  *    // As an object, extracting different data for the different types
11750                  *    // This would be used with a data source such as:
11751                  *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
11752                  *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
11753                  *    // (which has both forms) is used for filtering for if a user inputs either format, while
11754                  *    // the formatted phone number is the one that is shown in the table.
11755                  *    $(document).ready( function() {
11756                  *      $('#example').dataTable( {
11757                  *        "columnDefs": [ {
11758                  *          "targets": [ 0 ],
11759                  *          "data": null, // Use the full data source object for the renderer's source
11760                  *          "render": {
11761                  *            "_": "phone",
11762                  *            "filter": "phone_filter",
11763                  *            "display": "phone_display"
11764                  *          }
11765                  *        } ]
11766                  *      } );
11767                  *    } );
11768                  *
11769                  *  @example
11770                  *    // Use as a function to create a link from the data source
11771                  *    $(document).ready( function() {
11772                  *      $('#example').dataTable( {
11773                  *        "columnDefs": [ {
11774                  *          "targets": [ 0 ],
11775                  *          "data": "download_link",
11776                  *          "render": function ( data, type, full ) {
11777                  *            return '<a href="'+data+'">Download</a>';
11778                  *          }
11779                  *        } ]
11780                  *      } );
11781                  *    } );
11782                  */
11783                 "mRender": null,
11784         
11785         
11786                 /**
11787                  * Change the cell type created for the column - either TD cells or TH cells. This
11788                  * can be useful as TH cells have semantic meaning in the table body, allowing them
11789                  * to act as a header for a row (you may wish to add scope='row' to the TH elements).
11790                  *  @type string
11791                  *  @default td
11792                  *
11793                  *  @name DataTable.defaults.column.cellType
11794                  *  @dtopt Columns
11795                  *
11796                  *  @example
11797                  *    // Make the first column use TH cells
11798                  *    $(document).ready( function() {
11799                  *      $('#example').dataTable( {
11800                  *        "columnDefs": [ {
11801                  *          "targets": [ 0 ],
11802                  *          "cellType": "th"
11803                  *        } ]
11804                  *      } );
11805                  *    } );
11806                  */
11807                 "sCellType": "td",
11808         
11809         
11810                 /**
11811                  * Class to give to each cell in this column.
11812                  *  @type string
11813                  *  @default <i>Empty string</i>
11814                  *
11815                  *  @name DataTable.defaults.column.class
11816                  *  @dtopt Columns
11817                  *
11818                  *  @example
11819                  *    // Using `columnDefs`
11820                  *    $(document).ready( function() {
11821                  *      $('#example').dataTable( {
11822                  *        "columnDefs": [
11823                  *          { "class": "my_class", "targets": [ 0 ] }
11824                  *        ]
11825                  *      } );
11826                  *    } );
11827                  *
11828                  *  @example
11829                  *    // Using `columns`
11830                  *    $(document).ready( function() {
11831                  *      $('#example').dataTable( {
11832                  *        "columns": [
11833                  *          { "class": "my_class" },
11834                  *          null,
11835                  *          null,
11836                  *          null,
11837                  *          null
11838                  *        ]
11839                  *      } );
11840                  *    } );
11841                  */
11842                 "sClass": "",
11843         
11844                 /**
11845                  * When DataTables calculates the column widths to assign to each column,
11846                  * it finds the longest string in each column and then constructs a
11847                  * temporary table and reads the widths from that. The problem with this
11848                  * is that "mmm" is much wider then "iiii", but the latter is a longer
11849                  * string - thus the calculation can go wrong (doing it properly and putting
11850                  * it into an DOM object and measuring that is horribly(!) slow). Thus as
11851                  * a "work around" we provide this option. It will append its value to the
11852                  * text that is found to be the longest string for the column - i.e. padding.
11853                  * Generally you shouldn't need this!
11854                  *  @type string
11855                  *  @default <i>Empty string<i>
11856                  *
11857                  *  @name DataTable.defaults.column.contentPadding
11858                  *  @dtopt Columns
11859                  *
11860                  *  @example
11861                  *    // Using `columns`
11862                  *    $(document).ready( function() {
11863                  *      $('#example').dataTable( {
11864                  *        "columns": [
11865                  *          null,
11866                  *          null,
11867                  *          null,
11868                  *          {
11869                  *            "contentPadding": "mmm"
11870                  *          }
11871                  *        ]
11872                  *      } );
11873                  *    } );
11874                  */
11875                 "sContentPadding": "",
11876         
11877         
11878                 /**
11879                  * Allows a default value to be given for a column's data, and will be used
11880                  * whenever a null data source is encountered (this can be because `data`
11881                  * is set to null, or because the data source itself is null).
11882                  *  @type string
11883                  *  @default null
11884                  *
11885                  *  @name DataTable.defaults.column.defaultContent
11886                  *  @dtopt Columns
11887                  *
11888                  *  @example
11889                  *    // Using `columnDefs`
11890                  *    $(document).ready( function() {
11891                  *      $('#example').dataTable( {
11892                  *        "columnDefs": [
11893                  *          {
11894                  *            "data": null,
11895                  *            "defaultContent": "Edit",
11896                  *            "targets": [ -1 ]
11897                  *          }
11898                  *        ]
11899                  *      } );
11900                  *    } );
11901                  *
11902                  *  @example
11903                  *    // Using `columns`
11904                  *    $(document).ready( function() {
11905                  *      $('#example').dataTable( {
11906                  *        "columns": [
11907                  *          null,
11908                  *          null,
11909                  *          null,
11910                  *          {
11911                  *            "data": null,
11912                  *            "defaultContent": "Edit"
11913                  *          }
11914                  *        ]
11915                  *      } );
11916                  *    } );
11917                  */
11918                 "sDefaultContent": null,
11919         
11920         
11921                 /**
11922                  * This parameter is only used in DataTables' server-side processing. It can
11923                  * be exceptionally useful to know what columns are being displayed on the
11924                  * client side, and to map these to database fields. When defined, the names
11925                  * also allow DataTables to reorder information from the server if it comes
11926                  * back in an unexpected order (i.e. if you switch your columns around on the
11927                  * client-side, your server-side code does not also need updating).
11928                  *  @type string
11929                  *  @default <i>Empty string</i>
11930                  *
11931                  *  @name DataTable.defaults.column.name
11932                  *  @dtopt Columns
11933                  *
11934                  *  @example
11935                  *    // Using `columnDefs`
11936                  *    $(document).ready( function() {
11937                  *      $('#example').dataTable( {
11938                  *        "columnDefs": [
11939                  *          { "name": "engine", "targets": [ 0 ] },
11940                  *          { "name": "browser", "targets": [ 1 ] },
11941                  *          { "name": "platform", "targets": [ 2 ] },
11942                  *          { "name": "version", "targets": [ 3 ] },
11943                  *          { "name": "grade", "targets": [ 4 ] }
11944                  *        ]
11945                  *      } );
11946                  *    } );
11947                  *
11948                  *  @example
11949                  *    // Using `columns`
11950                  *    $(document).ready( function() {
11951                  *      $('#example').dataTable( {
11952                  *        "columns": [
11953                  *          { "name": "engine" },
11954                  *          { "name": "browser" },
11955                  *          { "name": "platform" },
11956                  *          { "name": "version" },
11957                  *          { "name": "grade" }
11958                  *        ]
11959                  *      } );
11960                  *    } );
11961                  */
11962                 "sName": "",
11963         
11964         
11965                 /**
11966                  * Defines a data source type for the ordering which can be used to read
11967                  * real-time information from the table (updating the internally cached
11968                  * version) prior to ordering. This allows ordering to occur on user
11969                  * editable elements such as form inputs.
11970                  *  @type string
11971                  *  @default std
11972                  *
11973                  *  @name DataTable.defaults.column.orderDataType
11974                  *  @dtopt Columns
11975                  *
11976                  *  @example
11977                  *    // Using `columnDefs`
11978                  *    $(document).ready( function() {
11979                  *      $('#example').dataTable( {
11980                  *        "columnDefs": [
11981                  *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
11982                  *          { "type": "numeric", "targets": [ 3 ] },
11983                  *          { "orderDataType": "dom-select", "targets": [ 4 ] },
11984                  *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
11985                  *        ]
11986                  *      } );
11987                  *    } );
11988                  *
11989                  *  @example
11990                  *    // Using `columns`
11991                  *    $(document).ready( function() {
11992                  *      $('#example').dataTable( {
11993                  *        "columns": [
11994                  *          null,
11995                  *          null,
11996                  *          { "orderDataType": "dom-text" },
11997                  *          { "orderDataType": "dom-text", "type": "numeric" },
11998                  *          { "orderDataType": "dom-select" },
11999                  *          { "orderDataType": "dom-checkbox" }
12000                  *        ]
12001                  *      } );
12002                  *    } );
12003                  */
12004                 "sSortDataType": "std",
12005         
12006         
12007                 /**
12008                  * The title of this column.
12009                  *  @type string
12010                  *  @default null <i>Derived from the 'TH' value for this column in the
12011                  *    original HTML table.</i>
12012                  *
12013                  *  @name DataTable.defaults.column.title
12014                  *  @dtopt Columns
12015                  *
12016                  *  @example
12017                  *    // Using `columnDefs`
12018                  *    $(document).ready( function() {
12019                  *      $('#example').dataTable( {
12020                  *        "columnDefs": [
12021                  *          { "title": "My column title", "targets": [ 0 ] }
12022                  *        ]
12023                  *      } );
12024                  *    } );
12025                  *
12026                  *  @example
12027                  *    // Using `columns`
12028                  *    $(document).ready( function() {
12029                  *      $('#example').dataTable( {
12030                  *        "columns": [
12031                  *          { "title": "My column title" },
12032                  *          null,
12033                  *          null,
12034                  *          null,
12035                  *          null
12036                  *        ]
12037                  *      } );
12038                  *    } );
12039                  */
12040                 "sTitle": null,
12041         
12042         
12043                 /**
12044                  * The type allows you to specify how the data for this column will be
12045                  * ordered. Four types (string, numeric, date and html (which will strip
12046                  * HTML tags before ordering)) are currently available. Note that only date
12047                  * formats understood by Javascript's Date() object will be accepted as type
12048                  * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12049                  * 'numeric', 'date' or 'html' (by default). Further types can be adding
12050                  * through plug-ins.
12051                  *  @type string
12052                  *  @default null <i>Auto-detected from raw data</i>
12053                  *
12054                  *  @name DataTable.defaults.column.type
12055                  *  @dtopt Columns
12056                  *
12057                  *  @example
12058                  *    // Using `columnDefs`
12059                  *    $(document).ready( function() {
12060                  *      $('#example').dataTable( {
12061                  *        "columnDefs": [
12062                  *          { "type": "html", "targets": [ 0 ] }
12063                  *        ]
12064                  *      } );
12065                  *    } );
12066                  *
12067                  *  @example
12068                  *    // Using `columns`
12069                  *    $(document).ready( function() {
12070                  *      $('#example').dataTable( {
12071                  *        "columns": [
12072                  *          { "type": "html" },
12073                  *          null,
12074                  *          null,
12075                  *          null,
12076                  *          null
12077                  *        ]
12078                  *      } );
12079                  *    } );
12080                  */
12081                 "sType": null,
12082         
12083         
12084                 /**
12085                  * Defining the width of the column, this parameter may take any CSS value
12086                  * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12087                  * been given a specific width through this interface ensuring that the table
12088                  * remains readable.
12089                  *  @type string
12090                  *  @default null <i>Automatic</i>
12091                  *
12092                  *  @name DataTable.defaults.column.width
12093                  *  @dtopt Columns
12094                  *
12095                  *  @example
12096                  *    // Using `columnDefs`
12097                  *    $(document).ready( function() {
12098                  *      $('#example').dataTable( {
12099                  *        "columnDefs": [
12100                  *          { "width": "20%", "targets": [ 0 ] }
12101                  *        ]
12102                  *      } );
12103                  *    } );
12104                  *
12105                  *  @example
12106                  *    // Using `columns`
12107                  *    $(document).ready( function() {
12108                  *      $('#example').dataTable( {
12109                  *        "columns": [
12110                  *          { "width": "20%" },
12111                  *          null,
12112                  *          null,
12113                  *          null,
12114                  *          null
12115                  *        ]
12116                  *      } );
12117                  *    } );
12118                  */
12119                 "sWidth": null
12120         };
12121         
12122         _fnHungarianMap( DataTable.defaults.column );
12123         
12124         
12125         
12126         /**
12127          * DataTables settings object - this holds all the information needed for a
12128          * given table, including configuration, data and current application of the
12129          * table options. DataTables does not have a single instance for each DataTable
12130          * with the settings attached to that instance, but rather instances of the
12131          * DataTable "class" are created on-the-fly as needed (typically by a
12132          * $().dataTable() call) and the settings object is then applied to that
12133          * instance.
12134          *
12135          * Note that this object is related to {@link DataTable.defaults} but this
12136          * one is the internal data store for DataTables's cache of columns. It should
12137          * NOT be manipulated outside of DataTables. Any configuration should be done
12138          * through the initialisation options.
12139          *  @namespace
12140          *  @todo Really should attach the settings object to individual instances so we
12141          *    don't need to create new instances on each $().dataTable() call (if the
12142          *    table already exists). It would also save passing oSettings around and
12143          *    into every single function. However, this is a very significant
12144          *    architecture change for DataTables and will almost certainly break
12145          *    backwards compatibility with older installations. This is something that
12146          *    will be done in 2.0.
12147          */
12148         DataTable.models.oSettings = {
12149                 /**
12150                  * Primary features of DataTables and their enablement state.
12151                  *  @namespace
12152                  */
12153                 "oFeatures": {
12154         
12155                         /**
12156                          * Flag to say if DataTables should automatically try to calculate the
12157                          * optimum table and columns widths (true) or not (false).
12158                          * Note that this parameter will be set by the initialisation routine. To
12159                          * set a default use {@link DataTable.defaults}.
12160                          *  @type boolean
12161                          */
12162                         "bAutoWidth": null,
12163         
12164                         /**
12165                          * Delay the creation of TR and TD elements until they are actually
12166                          * needed by a driven page draw. This can give a significant speed
12167                          * increase for Ajax source and Javascript source data, but makes no
12168                          * difference at all fro DOM and server-side processing tables.
12169                          * Note that this parameter will be set by the initialisation routine. To
12170                          * set a default use {@link DataTable.defaults}.
12171                          *  @type boolean
12172                          */
12173                         "bDeferRender": null,
12174         
12175                         /**
12176                          * Enable filtering on the table or not. Note that if this is disabled
12177                          * then there is no filtering at all on the table, including fnFilter.
12178                          * To just remove the filtering input use sDom and remove the 'f' option.
12179                          * Note that this parameter will be set by the initialisation routine. To
12180                          * set a default use {@link DataTable.defaults}.
12181                          *  @type boolean
12182                          */
12183                         "bFilter": null,
12184         
12185                         /**
12186                          * Table information element (the 'Showing x of y records' div) enable
12187                          * flag.
12188                          * Note that this parameter will be set by the initialisation routine. To
12189                          * set a default use {@link DataTable.defaults}.
12190                          *  @type boolean
12191                          */
12192                         "bInfo": null,
12193         
12194                         /**
12195                          * Present a user control allowing the end user to change the page size
12196                          * when pagination is enabled.
12197                          * Note that this parameter will be set by the initialisation routine. To
12198                          * set a default use {@link DataTable.defaults}.
12199                          *  @type boolean
12200                          */
12201                         "bLengthChange": null,
12202         
12203                         /**
12204                          * Pagination enabled or not. Note that if this is disabled then length
12205                          * changing must also be disabled.
12206                          * Note that this parameter will be set by the initialisation routine. To
12207                          * set a default use {@link DataTable.defaults}.
12208                          *  @type boolean
12209                          */
12210                         "bPaginate": null,
12211         
12212                         /**
12213                          * Processing indicator enable flag whenever DataTables is enacting a
12214                          * user request - typically an Ajax request for server-side processing.
12215                          * Note that this parameter will be set by the initialisation routine. To
12216                          * set a default use {@link DataTable.defaults}.
12217                          *  @type boolean
12218                          */
12219                         "bProcessing": null,
12220         
12221                         /**
12222                          * Server-side processing enabled flag - when enabled DataTables will
12223                          * get all data from the server for every draw - there is no filtering,
12224                          * sorting or paging done on the client-side.
12225                          * Note that this parameter will be set by the initialisation routine. To
12226                          * set a default use {@link DataTable.defaults}.
12227                          *  @type boolean
12228                          */
12229                         "bServerSide": null,
12230         
12231                         /**
12232                          * Sorting enablement flag.
12233                          * Note that this parameter will be set by the initialisation routine. To
12234                          * set a default use {@link DataTable.defaults}.
12235                          *  @type boolean
12236                          */
12237                         "bSort": null,
12238         
12239                         /**
12240                          * Multi-column sorting
12241                          * Note that this parameter will be set by the initialisation routine. To
12242                          * set a default use {@link DataTable.defaults}.
12243                          *  @type boolean
12244                          */
12245                         "bSortMulti": null,
12246         
12247                         /**
12248                          * Apply a class to the columns which are being sorted to provide a
12249                          * visual highlight or not. This can slow things down when enabled since
12250                          * there is a lot of DOM interaction.
12251                          * Note that this parameter will be set by the initialisation routine. To
12252                          * set a default use {@link DataTable.defaults}.
12253                          *  @type boolean
12254                          */
12255                         "bSortClasses": null,
12256         
12257                         /**
12258                          * State saving enablement flag.
12259                          * Note that this parameter will be set by the initialisation routine. To
12260                          * set a default use {@link DataTable.defaults}.
12261                          *  @type boolean
12262                          */
12263                         "bStateSave": null
12264                 },
12265         
12266         
12267                 /**
12268                  * Scrolling settings for a table.
12269                  *  @namespace
12270                  */
12271                 "oScroll": {
12272                         /**
12273                          * When the table is shorter in height than sScrollY, collapse the
12274                          * table container down to the height of the table (when true).
12275                          * Note that this parameter will be set by the initialisation routine. To
12276                          * set a default use {@link DataTable.defaults}.
12277                          *  @type boolean
12278                          */
12279                         "bCollapse": null,
12280         
12281                         /**
12282                          * Width of the scrollbar for the web-browser's platform. Calculated
12283                          * during table initialisation.
12284                          *  @type int
12285                          *  @default 0
12286                          */
12287                         "iBarWidth": 0,
12288         
12289                         /**
12290                          * Viewport width for horizontal scrolling. Horizontal scrolling is
12291                          * disabled if an empty string.
12292                          * Note that this parameter will be set by the initialisation routine. To
12293                          * set a default use {@link DataTable.defaults}.
12294                          *  @type string
12295                          */
12296                         "sX": null,
12297         
12298                         /**
12299                          * Width to expand the table to when using x-scrolling. Typically you
12300                          * should not need to use this.
12301                          * Note that this parameter will be set by the initialisation routine. To
12302                          * set a default use {@link DataTable.defaults}.
12303                          *  @type string
12304                          *  @deprecated
12305                          */
12306                         "sXInner": null,
12307         
12308                         /**
12309                          * Viewport height for vertical scrolling. Vertical scrolling is disabled
12310                          * if an empty string.
12311                          * Note that this parameter will be set by the initialisation routine. To
12312                          * set a default use {@link DataTable.defaults}.
12313                          *  @type string
12314                          */
12315                         "sY": null
12316                 },
12317         
12318                 /**
12319                  * Language information for the table.
12320                  *  @namespace
12321                  *  @extends DataTable.defaults.oLanguage
12322                  */
12323                 "oLanguage": {
12324                         /**
12325                          * Information callback function. See
12326                          * {@link DataTable.defaults.fnInfoCallback}
12327                          *  @type function
12328                          *  @default null
12329                          */
12330                         "fnInfoCallback": null
12331                 },
12332         
12333                 /**
12334                  * Browser support parameters
12335                  *  @namespace
12336                  */
12337                 "oBrowser": {
12338                         /**
12339                          * Indicate if the browser incorrectly calculates width:100% inside a
12340                          * scrolling element (IE6/7)
12341                          *  @type boolean
12342                          *  @default false
12343                          */
12344                         "bScrollOversize": false,
12345         
12346                         /**
12347                          * Determine if the vertical scrollbar is on the right or left of the
12348                          * scrolling container - needed for rtl language layout, although not
12349                          * all browsers move the scrollbar (Safari).
12350                          *  @type boolean
12351                          *  @default false
12352                          */
12353                         "bScrollbarLeft": false
12354                 },
12355         
12356         
12357                 "ajax": null,
12358         
12359         
12360                 /**
12361                  * Array referencing the nodes which are used for the features. The
12362                  * parameters of this object match what is allowed by sDom - i.e.
12363                  *   <ul>
12364                  *     <li>'l' - Length changing</li>
12365                  *     <li>'f' - Filtering input</li>
12366                  *     <li>'t' - The table!</li>
12367                  *     <li>'i' - Information</li>
12368                  *     <li>'p' - Pagination</li>
12369                  *     <li>'r' - pRocessing</li>
12370                  *   </ul>
12371                  *  @type array
12372                  *  @default []
12373                  */
12374                 "aanFeatures": [],
12375         
12376                 /**
12377                  * Store data information - see {@link DataTable.models.oRow} for detailed
12378                  * information.
12379                  *  @type array
12380                  *  @default []
12381                  */
12382                 "aoData": [],
12383         
12384                 /**
12385                  * Array of indexes which are in the current display (after filtering etc)
12386                  *  @type array
12387                  *  @default []
12388                  */
12389                 "aiDisplay": [],
12390         
12391                 /**
12392                  * Array of indexes for display - no filtering
12393                  *  @type array
12394                  *  @default []
12395                  */
12396                 "aiDisplayMaster": [],
12397         
12398                 /**
12399                  * Store information about each column that is in use
12400                  *  @type array
12401                  *  @default []
12402                  */
12403                 "aoColumns": [],
12404         
12405                 /**
12406                  * Store information about the table's header
12407                  *  @type array
12408                  *  @default []
12409                  */
12410                 "aoHeader": [],
12411         
12412                 /**
12413                  * Store information about the table's footer
12414                  *  @type array
12415                  *  @default []
12416                  */
12417                 "aoFooter": [],
12418         
12419                 /**
12420                  * Store the applied global search information in case we want to force a
12421                  * research or compare the old search to a new one.
12422                  * Note that this parameter will be set by the initialisation routine. To
12423                  * set a default use {@link DataTable.defaults}.
12424                  *  @namespace
12425                  *  @extends DataTable.models.oSearch
12426                  */
12427                 "oPreviousSearch": {},
12428         
12429                 /**
12430                  * Store the applied search for each column - see
12431                  * {@link DataTable.models.oSearch} for the format that is used for the
12432                  * filtering information for each column.
12433                  *  @type array
12434                  *  @default []
12435                  */
12436                 "aoPreSearchCols": [],
12437         
12438                 /**
12439                  * Sorting that is applied to the table. Note that the inner arrays are
12440                  * used in the following manner:
12441                  * <ul>
12442                  *   <li>Index 0 - column number</li>
12443                  *   <li>Index 1 - current sorting direction</li>
12444                  * </ul>
12445                  * Note that this parameter will be set by the initialisation routine. To
12446                  * set a default use {@link DataTable.defaults}.
12447                  *  @type array
12448                  *  @todo These inner arrays should really be objects
12449                  */
12450                 "aaSorting": null,
12451         
12452                 /**
12453                  * Sorting that is always applied to the table (i.e. prefixed in front of
12454                  * aaSorting).
12455                  * Note that this parameter will be set by the initialisation routine. To
12456                  * set a default use {@link DataTable.defaults}.
12457                  *  @type array
12458                  *  @default []
12459                  */
12460                 "aaSortingFixed": [],
12461         
12462                 /**
12463                  * Classes to use for the striping of a table.
12464                  * Note that this parameter will be set by the initialisation routine. To
12465                  * set a default use {@link DataTable.defaults}.
12466                  *  @type array
12467                  *  @default []
12468                  */
12469                 "asStripeClasses": null,
12470         
12471                 /**
12472                  * If restoring a table - we should restore its striping classes as well
12473                  *  @type array
12474                  *  @default []
12475                  */
12476                 "asDestroyStripes": [],
12477         
12478                 /**
12479                  * If restoring a table - we should restore its width
12480                  *  @type int
12481                  *  @default 0
12482                  */
12483                 "sDestroyWidth": 0,
12484         
12485                 /**
12486                  * Callback functions array for every time a row is inserted (i.e. on a draw).
12487                  *  @type array
12488                  *  @default []
12489                  */
12490                 "aoRowCallback": [],
12491         
12492                 /**
12493                  * Callback functions for the header on each draw.
12494                  *  @type array
12495                  *  @default []
12496                  */
12497                 "aoHeaderCallback": [],
12498         
12499                 /**
12500                  * Callback function for the footer on each draw.
12501                  *  @type array
12502                  *  @default []
12503                  */
12504                 "aoFooterCallback": [],
12505         
12506                 /**
12507                  * Array of callback functions for draw callback functions
12508                  *  @type array
12509                  *  @default []
12510                  */
12511                 "aoDrawCallback": [],
12512         
12513                 /**
12514                  * Array of callback functions for row created function
12515                  *  @type array
12516                  *  @default []
12517                  */
12518                 "aoRowCreatedCallback": [],
12519         
12520                 /**
12521                  * Callback functions for just before the table is redrawn. A return of
12522                  * false will be used to cancel the draw.
12523                  *  @type array
12524                  *  @default []
12525                  */
12526                 "aoPreDrawCallback": [],
12527         
12528                 /**
12529                  * Callback functions for when the table has been initialised.
12530                  *  @type array
12531                  *  @default []
12532                  */
12533                 "aoInitComplete": [],
12534         
12535         
12536                 /**
12537                  * Callbacks for modifying the settings to be stored for state saving, prior to
12538                  * saving state.
12539                  *  @type array
12540                  *  @default []
12541                  */
12542                 "aoStateSaveParams": [],
12543         
12544                 /**
12545                  * Callbacks for modifying the settings that have been stored for state saving
12546                  * prior to using the stored values to restore the state.
12547                  *  @type array
12548                  *  @default []
12549                  */
12550                 "aoStateLoadParams": [],
12551         
12552                 /**
12553                  * Callbacks for operating on the settings object once the saved state has been
12554                  * loaded
12555                  *  @type array
12556                  *  @default []
12557                  */
12558                 "aoStateLoaded": [],
12559         
12560                 /**
12561                  * Cache the table ID for quick access
12562                  *  @type string
12563                  *  @default <i>Empty string</i>
12564                  */
12565                 "sTableId": "",
12566         
12567                 /**
12568                  * The TABLE node for the main table
12569                  *  @type node
12570                  *  @default null
12571                  */
12572                 "nTable": null,
12573         
12574                 /**
12575                  * Permanent ref to the thead element
12576                  *  @type node
12577                  *  @default null
12578                  */
12579                 "nTHead": null,
12580         
12581                 /**
12582                  * Permanent ref to the tfoot element - if it exists
12583                  *  @type node
12584                  *  @default null
12585                  */
12586                 "nTFoot": null,
12587         
12588                 /**
12589                  * Permanent ref to the tbody element
12590                  *  @type node
12591                  *  @default null
12592                  */
12593                 "nTBody": null,
12594         
12595                 /**
12596                  * Cache the wrapper node (contains all DataTables controlled elements)
12597                  *  @type node
12598                  *  @default null
12599                  */
12600                 "nTableWrapper": null,
12601         
12602                 /**
12603                  * Indicate if when using server-side processing the loading of data
12604                  * should be deferred until the second draw.
12605                  * Note that this parameter will be set by the initialisation routine. To
12606                  * set a default use {@link DataTable.defaults}.
12607                  *  @type boolean
12608                  *  @default false
12609                  */
12610                 "bDeferLoading": false,
12611         
12612                 /**
12613                  * Indicate if all required information has been read in
12614                  *  @type boolean
12615                  *  @default false
12616                  */
12617                 "bInitialised": false,
12618         
12619                 /**
12620                  * Information about open rows. Each object in the array has the parameters
12621                  * 'nTr' and 'nParent'
12622                  *  @type array
12623                  *  @default []
12624                  */
12625                 "aoOpenRows": [],
12626         
12627                 /**
12628                  * Dictate the positioning of DataTables' control elements - see
12629                  * {@link DataTable.model.oInit.sDom}.
12630                  * Note that this parameter will be set by the initialisation routine. To
12631                  * set a default use {@link DataTable.defaults}.
12632                  *  @type string
12633                  *  @default null
12634                  */
12635                 "sDom": null,
12636         
12637                 /**
12638                  * Which type of pagination should be used.
12639                  * Note that this parameter will be set by the initialisation routine. To
12640                  * set a default use {@link DataTable.defaults}.
12641                  *  @type string
12642                  *  @default two_button
12643                  */
12644                 "sPaginationType": "two_button",
12645         
12646                 /**
12647                  * The state duration (for `stateSave`) in seconds.
12648                  * Note that this parameter will be set by the initialisation routine. To
12649                  * set a default use {@link DataTable.defaults}.
12650                  *  @type int
12651                  *  @default 0
12652                  */
12653                 "iStateDuration": 0,
12654         
12655                 /**
12656                  * Array of callback functions for state saving. Each array element is an
12657                  * object with the following parameters:
12658                  *   <ul>
12659                  *     <li>function:fn - function to call. Takes two parameters, oSettings
12660                  *       and the JSON string to save that has been thus far created. Returns
12661                  *       a JSON string to be inserted into a json object
12662                  *       (i.e. '"param": [ 0, 1, 2]')</li>
12663                  *     <li>string:sName - name of callback</li>
12664                  *   </ul>
12665                  *  @type array
12666                  *  @default []
12667                  */
12668                 "aoStateSave": [],
12669         
12670                 /**
12671                  * Array of callback functions for state loading. Each array element is an
12672                  * object with the following parameters:
12673                  *   <ul>
12674                  *     <li>function:fn - function to call. Takes two parameters, oSettings
12675                  *       and the object stored. May return false to cancel state loading</li>
12676                  *     <li>string:sName - name of callback</li>
12677                  *   </ul>
12678                  *  @type array
12679                  *  @default []
12680                  */
12681                 "aoStateLoad": [],
12682         
12683                 /**
12684                  * State that was loaded. Useful for back reference
12685                  *  @type object
12686                  *  @default null
12687                  */
12688                 "oLoadedState": null,
12689         
12690                 /**
12691                  * Source url for AJAX data for the table.
12692                  * Note that this parameter will be set by the initialisation routine. To
12693                  * set a default use {@link DataTable.defaults}.
12694                  *  @type string
12695                  *  @default null
12696                  */
12697                 "sAjaxSource": null,
12698         
12699                 /**
12700                  * Property from a given object from which to read the table data from. This
12701                  * can be an empty string (when not server-side processing), in which case
12702                  * it is  assumed an an array is given directly.
12703                  * Note that this parameter will be set by the initialisation routine. To
12704                  * set a default use {@link DataTable.defaults}.
12705                  *  @type string
12706                  */
12707                 "sAjaxDataProp": null,
12708         
12709                 /**
12710                  * Note if draw should be blocked while getting data
12711                  *  @type boolean
12712                  *  @default true
12713                  */
12714                 "bAjaxDataGet": true,
12715         
12716                 /**
12717                  * The last jQuery XHR object that was used for server-side data gathering.
12718                  * This can be used for working with the XHR information in one of the
12719                  * callbacks
12720                  *  @type object
12721                  *  @default null
12722                  */
12723                 "jqXHR": null,
12724         
12725                 /**
12726                  * JSON returned from the server in the last Ajax request
12727                  *  @type object
12728                  *  @default undefined
12729                  */
12730                 "json": undefined,
12731         
12732                 /**
12733                  * Data submitted as part of the last Ajax request
12734                  *  @type object
12735                  *  @default undefined
12736                  */
12737                 "oAjaxData": undefined,
12738         
12739                 /**
12740                  * Function to get the server-side data.
12741                  * Note that this parameter will be set by the initialisation routine. To
12742                  * set a default use {@link DataTable.defaults}.
12743                  *  @type function
12744                  */
12745                 "fnServerData": null,
12746         
12747                 /**
12748                  * Functions which are called prior to sending an Ajax request so extra
12749                  * parameters can easily be sent to the server
12750                  *  @type array
12751                  *  @default []
12752                  */
12753                 "aoServerParams": [],
12754         
12755                 /**
12756                  * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
12757                  * required).
12758                  * Note that this parameter will be set by the initialisation routine. To
12759                  * set a default use {@link DataTable.defaults}.
12760                  *  @type string
12761                  */
12762                 "sServerMethod": null,
12763         
12764                 /**
12765                  * Format numbers for display.
12766                  * Note that this parameter will be set by the initialisation routine. To
12767                  * set a default use {@link DataTable.defaults}.
12768                  *  @type function
12769                  */
12770                 "fnFormatNumber": null,
12771         
12772                 /**
12773                  * List of options that can be used for the user selectable length menu.
12774                  * Note that this parameter will be set by the initialisation routine. To
12775                  * set a default use {@link DataTable.defaults}.
12776                  *  @type array
12777                  *  @default []
12778                  */
12779                 "aLengthMenu": null,
12780         
12781                 /**
12782                  * Counter for the draws that the table does. Also used as a tracker for
12783                  * server-side processing
12784                  *  @type int
12785                  *  @default 0
12786                  */
12787                 "iDraw": 0,
12788         
12789                 /**
12790                  * Indicate if a redraw is being done - useful for Ajax
12791                  *  @type boolean
12792                  *  @default false
12793                  */
12794                 "bDrawing": false,
12795         
12796                 /**
12797                  * Draw index (iDraw) of the last error when parsing the returned data
12798                  *  @type int
12799                  *  @default -1
12800                  */
12801                 "iDrawError": -1,
12802         
12803                 /**
12804                  * Paging display length
12805                  *  @type int
12806                  *  @default 10
12807                  */
12808                 "_iDisplayLength": 10,
12809         
12810                 /**
12811                  * Paging start point - aiDisplay index
12812                  *  @type int
12813                  *  @default 0
12814                  */
12815                 "_iDisplayStart": 0,
12816         
12817                 /**
12818                  * Server-side processing - number of records in the result set
12819                  * (i.e. before filtering), Use fnRecordsTotal rather than
12820                  * this property to get the value of the number of records, regardless of
12821                  * the server-side processing setting.
12822                  *  @type int
12823                  *  @default 0
12824                  *  @private
12825                  */
12826                 "_iRecordsTotal": 0,
12827         
12828                 /**
12829                  * Server-side processing - number of records in the current display set
12830                  * (i.e. after filtering). Use fnRecordsDisplay rather than
12831                  * this property to get the value of the number of records, regardless of
12832                  * the server-side processing setting.
12833                  *  @type boolean
12834                  *  @default 0
12835                  *  @private
12836                  */
12837                 "_iRecordsDisplay": 0,
12838         
12839                 /**
12840                  * Flag to indicate if jQuery UI marking and classes should be used.
12841                  * Note that this parameter will be set by the initialisation routine. To
12842                  * set a default use {@link DataTable.defaults}.
12843                  *  @type boolean
12844                  */
12845                 "bJUI": null,
12846         
12847                 /**
12848                  * The classes to use for the table
12849                  *  @type object
12850                  *  @default {}
12851                  */
12852                 "oClasses": {},
12853         
12854                 /**
12855                  * Flag attached to the settings object so you can check in the draw
12856                  * callback if filtering has been done in the draw. Deprecated in favour of
12857                  * events.
12858                  *  @type boolean
12859                  *  @default false
12860                  *  @deprecated
12861                  */
12862                 "bFiltered": false,
12863         
12864                 /**
12865                  * Flag attached to the settings object so you can check in the draw
12866                  * callback if sorting has been done in the draw. Deprecated in favour of
12867                  * events.
12868                  *  @type boolean
12869                  *  @default false
12870                  *  @deprecated
12871                  */
12872                 "bSorted": false,
12873         
12874                 /**
12875                  * Indicate that if multiple rows are in the header and there is more than
12876                  * one unique cell per column, if the top one (true) or bottom one (false)
12877                  * should be used for sorting / title by DataTables.
12878                  * Note that this parameter will be set by the initialisation routine. To
12879                  * set a default use {@link DataTable.defaults}.
12880                  *  @type boolean
12881                  */
12882                 "bSortCellsTop": null,
12883         
12884                 /**
12885                  * Initialisation object that is used for the table
12886                  *  @type object
12887                  *  @default null
12888                  */
12889                 "oInit": null,
12890         
12891                 /**
12892                  * Destroy callback functions - for plug-ins to attach themselves to the
12893                  * destroy so they can clean up markup and events.
12894                  *  @type array
12895                  *  @default []
12896                  */
12897                 "aoDestroyCallback": [],
12898         
12899         
12900                 /**
12901                  * Get the number of records in the current record set, before filtering
12902                  *  @type function
12903                  */
12904                 "fnRecordsTotal": function ()
12905                 {
12906                         return _fnDataSource( this ) == 'ssp' ?
12907                                 this._iRecordsTotal * 1 :
12908                                 this.aiDisplayMaster.length;
12909                 },
12910         
12911                 /**
12912                  * Get the number of records in the current record set, after filtering
12913                  *  @type function
12914                  */
12915                 "fnRecordsDisplay": function ()
12916                 {
12917                         return _fnDataSource( this ) == 'ssp' ?
12918                                 this._iRecordsDisplay * 1 :
12919                                 this.aiDisplay.length;
12920                 },
12921         
12922                 /**
12923                  * Get the display end point - aiDisplay index
12924                  *  @type function
12925                  */
12926                 "fnDisplayEnd": function ()
12927                 {
12928                         var
12929                                 len      = this._iDisplayLength,
12930                                 start    = this._iDisplayStart,
12931                                 calc     = start + len,
12932                                 records  = this.aiDisplay.length,
12933                                 features = this.oFeatures,
12934                                 paginate = features.bPaginate;
12935         
12936                         if ( features.bServerSide ) {
12937                                 return paginate === false || len === -1 ?
12938                                         start + records :
12939                                         Math.min( start+len, this._iRecordsDisplay );
12940                         }
12941                         else {
12942                                 return ! paginate || calc>records || len===-1 ?
12943                                         records :
12944                                         calc;
12945                         }
12946                 },
12947         
12948                 /**
12949                  * The DataTables object for this table
12950                  *  @type object
12951                  *  @default null
12952                  */
12953                 "oInstance": null,
12954         
12955                 /**
12956                  * Unique identifier for each instance of the DataTables object. If there
12957                  * is an ID on the table node, then it takes that value, otherwise an
12958                  * incrementing internal counter is used.
12959                  *  @type string
12960                  *  @default null
12961                  */
12962                 "sInstance": null,
12963         
12964                 /**
12965                  * tabindex attribute value that is added to DataTables control elements, allowing
12966                  * keyboard navigation of the table and its controls.
12967                  */
12968                 "iTabIndex": 0,
12969         
12970                 /**
12971                  * DIV container for the footer scrolling table if scrolling
12972                  */
12973                 "nScrollHead": null,
12974         
12975                 /**
12976                  * DIV container for the footer scrolling table if scrolling
12977                  */
12978                 "nScrollFoot": null,
12979         
12980                 /**
12981                  * Last applied sort
12982                  *  @type array
12983                  *  @default []
12984                  */
12985                 "aLastSort": [],
12986         
12987                 /**
12988                  * Stored plug-in instances
12989                  *  @type object
12990                  *  @default {}
12991                  */
12992                 "oPlugins": {}
12993         };
12994
12995         /**
12996          * Extension object for DataTables that is used to provide all extension
12997          * options.
12998          *
12999          * Note that the `DataTable.ext` object is available through
13000          * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13001          * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13002          *  @namespace
13003          *  @extends DataTable.models.ext
13004          */
13005         
13006         
13007         /**
13008          * DataTables extensions
13009          * 
13010          * This namespace acts as a collection area for plug-ins that can be used to
13011          * extend DataTables capabilities. Indeed many of the build in methods
13012          * use this method to provide their own capabilities (sorting methods for
13013          * example).
13014          *
13015          * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13016          * reasons
13017          *
13018          *  @namespace
13019          */
13020         DataTable.ext = _ext = {
13021                 /**
13022                  * Element class names
13023                  *
13024                  *  @type object
13025                  *  @default {}
13026                  */
13027                 classes: {},
13028         
13029         
13030                 /**
13031                  * Error reporting.
13032                  * 
13033                  * How should DataTables report an error. Can take the value 'alert' or
13034                  * 'throw'
13035                  *
13036                  *  @type string
13037                  *  @default alert
13038                  */
13039                 errMode: "alert",
13040         
13041         
13042                 /**
13043                  * Feature plug-ins.
13044                  * 
13045                  * This is an array of objects which describe the feature plug-ins that are
13046                  * available to DataTables. These feature plug-ins are then available for
13047                  * use through the `dom` initialisation option.
13048                  * 
13049                  * Each feature plug-in is described by an object which must have the
13050                  * following properties:
13051                  * 
13052                  * * `fnInit` - function that is used to initialise the plug-in,
13053                  * * `cFeature` - a character so the feature can be enabled by the `dom`
13054                  *   instillation option. This is case sensitive.
13055                  *
13056                  * The `fnInit` function has the following input parameters:
13057                  *
13058                  * 1. `{object}` DataTables settings object: see
13059                  *    {@link DataTable.models.oSettings}
13060                  *
13061                  * And the following return is expected:
13062                  * 
13063                  * * {node|null} The element which contains your feature. Note that the
13064                  *   return may also be void if your plug-in does not require to inject any
13065                  *   DOM elements into DataTables control (`dom`) - for example this might
13066                  *   be useful when developing a plug-in which allows table control via
13067                  *   keyboard entry
13068                  *
13069                  *  @type array
13070                  *
13071                  *  @example
13072                  *    $.fn.dataTable.ext.features.push( {
13073                  *      "fnInit": function( oSettings ) {
13074                  *        return new TableTools( { "oDTSettings": oSettings } );
13075                  *      },
13076                  *      "cFeature": "T"
13077                  *    } );
13078                  */
13079                 feature: [],
13080         
13081         
13082                 /**
13083                  * Row searching.
13084                  * 
13085                  * This method of searching is complimentary to the default type based
13086                  * searching, and a lot more comprehensive as it allows you complete control
13087                  * over the searching logic. Each element in this array is a function
13088                  * (parameters described below) that is called for every row in the table,
13089                  * and your logic decides if it should be included in the searching data set
13090                  * or not.
13091                  *
13092                  * Searching functions have the following input parameters:
13093                  *
13094                  * 1. `{object}` DataTables settings object: see
13095                  *    {@link DataTable.models.oSettings}
13096                  * 2. `{array|object}` Data for the row to be processed (same as the
13097                  *    original format that was passed in as the data source, or an array
13098                  *    from a DOM data source
13099                  * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13100                  *    can be useful to retrieve the `TR` element if you need DOM interaction.
13101                  *
13102                  * And the following return is expected:
13103                  *
13104                  * * {boolean} Include the row in the searched result set (true) or not
13105                  *   (false)
13106                  *
13107                  * Note that as with the main search ability in DataTables, technically this
13108                  * is "filtering", since it is subtractive. However, for consistency in
13109                  * naming we call it searching here.
13110                  *
13111                  *  @type array
13112                  *  @default []
13113                  *
13114                  *  @example
13115                  *    // The following example shows custom search being applied to the
13116                  *    // fourth column (i.e. the data[3] index) based on two input values
13117                  *    // from the end-user, matching the data in a certain range.
13118                  *    $.fn.dataTable.ext.search.push(
13119                  *      function( settings, data, dataIndex ) {
13120                  *        var min = document.getElementById('min').value * 1;
13121                  *        var max = document.getElementById('max').value * 1;
13122                  *        var version = data[3] == "-" ? 0 : data[3]*1;
13123                  *
13124                  *        if ( min == "" && max == "" ) {
13125                  *          return true;
13126                  *        }
13127                  *        else if ( min == "" && version < max ) {
13128                  *          return true;
13129                  *        }
13130                  *        else if ( min < version && "" == max ) {
13131                  *          return true;
13132                  *        }
13133                  *        else if ( min < version && version < max ) {
13134                  *          return true;
13135                  *        }
13136                  *        return false;
13137                  *      }
13138                  *    );
13139                  */
13140                 search: [],
13141         
13142         
13143                 /**
13144                  * Internal functions, exposed for used in plug-ins.
13145                  * 
13146                  * Please note that you should not need to use the internal methods for
13147                  * anything other than a plug-in (and even then, try to avoid if possible).
13148                  * The internal function may change between releases.
13149                  *
13150                  *  @type object
13151                  *  @default {}
13152                  */
13153                 internal: {},
13154         
13155         
13156                 /**
13157                  * Legacy configuration options. Enable and disable legacy options that
13158                  * are available in DataTables.
13159                  *
13160                  *  @type object
13161                  */
13162                 legacy: {
13163                         /**
13164                          * Enable / disable DataTables 1.9 compatible server-side processing
13165                          * requests
13166                          *
13167                          *  @type boolean
13168                          *  @default null
13169                          */
13170                         ajax: null
13171                 },
13172         
13173         
13174                 /**
13175                  * Pagination plug-in methods.
13176                  * 
13177                  * Each entry in this object is a function and defines which buttons should
13178                  * be shown by the pagination rendering method that is used for the table:
13179                  * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
13180                  * buttons are displayed in the document, while the functions here tell it
13181                  * what buttons to display. This is done by returning an array of button
13182                  * descriptions (what each button will do).
13183                  *
13184                  * Pagination types (the four built in options and any additional plug-in
13185                  * options defined here) can be used through the `paginationType`
13186                  * initialisation parameter.
13187                  *
13188                  * The functions defined take two parameters:
13189                  *
13190                  * 1. `{int} page` The current page index
13191                  * 2. `{int} pages` The number of pages in the table
13192                  *
13193                  * Each function is expected to return an array where each element of the
13194                  * array can be one of:
13195                  *
13196                  * * `first` - Jump to first page when activated
13197                  * * `last` - Jump to last page when activated
13198                  * * `previous` - Show previous page when activated
13199                  * * `next` - Show next page when activated
13200                  * * `{int}` - Show page of the index given
13201                  * * `{array}` - A nested array containing the above elements to add a
13202                  *   containing 'DIV' element (might be useful for styling).
13203                  *
13204                  * Note that DataTables v1.9- used this object slightly differently whereby
13205                  * an object with two functions would be defined for each plug-in. That
13206                  * ability is still supported by DataTables 1.10+ to provide backwards
13207                  * compatibility, but this option of use is now decremented and no longer
13208                  * documented in DataTables 1.10+.
13209                  *
13210                  *  @type object
13211                  *  @default {}
13212                  *
13213                  *  @example
13214                  *    // Show previous, next and current page buttons only
13215                  *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
13216                  *      return [ 'previous', page, 'next' ];
13217                  *    };
13218                  */
13219                 pager: {},
13220         
13221         
13222                 renderer: {
13223                         pageButton: {},
13224                         header: {}
13225                 },
13226         
13227         
13228                 /**
13229                  * Ordering plug-ins - custom data source
13230                  * 
13231                  * The extension options for ordering of data available here is complimentary
13232                  * to the default type based ordering that DataTables typically uses. It
13233                  * allows much greater control over the the data that is being used to
13234                  * order a column, but is necessarily therefore more complex.
13235                  * 
13236                  * This type of ordering is useful if you want to do ordering based on data
13237                  * live from the DOM (for example the contents of an 'input' element) rather
13238                  * than just the static string that DataTables knows of.
13239                  * 
13240                  * The way these plug-ins work is that you create an array of the values you
13241                  * wish to be ordering for the column in question and then return that
13242                  * array. The data in the array much be in the index order of the rows in
13243                  * the table (not the currently ordering order!). Which order data gathering
13244                  * function is run here depends on the `dt-init columns.orderDataType`
13245                  * parameter that is used for the column (if any).
13246                  *
13247                  * The functions defined take two parameters:
13248                  *
13249                  * 1. `{object}` DataTables settings object: see
13250                  *    {@link DataTable.models.oSettings}
13251                  * 2. `{int}` Target column index
13252                  *
13253                  * Each function is expected to return an array:
13254                  *
13255                  * * `{array}` Data for the column to be ordering upon
13256                  *
13257                  *  @type array
13258                  *
13259                  *  @example
13260                  *    // Ordering using `input` node values
13261                  *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
13262                  *    {
13263                  *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
13264                  *        return $('input', td).val();
13265                  *      } );
13266                  *    }
13267                  */
13268                 order: {},
13269         
13270         
13271                 /**
13272                  * Type based plug-ins.
13273                  *
13274                  * Each column in DataTables has a type assigned to it, either by automatic
13275                  * detection or by direct assignment using the `type` option for the column.
13276                  * The type of a column will effect how it is ordering and search (plug-ins
13277                  * can also make use of the column type if required).
13278                  *
13279                  * @namespace
13280                  */
13281                 type: {
13282                         /**
13283                          * Type detection functions.
13284                          *
13285                          * The functions defined in this object are used to automatically detect
13286                          * a column's type, making initialisation of DataTables super easy, even
13287                          * when complex data is in the table.
13288                          *
13289                          * The functions defined take two parameters:
13290                          *
13291                      *  1. `{*}` Data from the column cell to be analysed
13292                      *  2. `{settings}` DataTables settings object. This can be used to
13293                      *     perform context specific type detection - for example detection
13294                      *     based on language settings such as using a comma for a decimal
13295                      *     place. Generally speaking the options from the settings will not
13296                      *     be required
13297                          *
13298                          * Each function is expected to return:
13299                          *
13300                          * * `{string|null}` Data type detected, or null if unknown (and thus
13301                          *   pass it on to the other type detection functions.
13302                          *
13303                          *  @type array
13304                          *
13305                          *  @example
13306                          *    // Currency type detection plug-in:
13307                          *    $.fn.dataTable.ext.type.detect.push(
13308                          *      function ( data, settings ) {
13309                          *        // Check the numeric part
13310                          *        if ( ! $.isNumeric( data.substring(1) ) ) {
13311                          *          return null;
13312                          *        }
13313                          *
13314                          *        // Check prefixed by currency
13315                          *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
13316                          *          return 'currency';
13317                          *        }
13318                          *        return null;
13319                          *      }
13320                          *    );
13321                          */
13322                         detect: [],
13323         
13324         
13325                         /**
13326                          * Type based search formatting.
13327                          *
13328                          * The type based searching functions can be used to pre-format the
13329                          * data to be search on. For example, it can be used to strip HTML
13330                          * tags or to de-format telephone numbers for numeric only searching.
13331                          *
13332                          * Note that is a search is not defined for a column of a given type,
13333                          * no search formatting will be performed.
13334                          * 
13335                          * Pre-processing of searching data plug-ins - When you assign the sType
13336                          * for a column (or have it automatically detected for you by DataTables
13337                          * or a type detection plug-in), you will typically be using this for
13338                          * custom sorting, but it can also be used to provide custom searching
13339                          * by allowing you to pre-processing the data and returning the data in
13340                          * the format that should be searched upon. This is done by adding
13341                          * functions this object with a parameter name which matches the sType
13342                          * for that target column. This is the corollary of <i>afnSortData</i>
13343                          * for searching data.
13344                          *
13345                          * The functions defined take a single parameter:
13346                          *
13347                      *  1. `{*}` Data from the column cell to be prepared for searching
13348                          *
13349                          * Each function is expected to return:
13350                          *
13351                          * * `{string|null}` Formatted string that will be used for the searching.
13352                          *
13353                          *  @type object
13354                          *  @default {}
13355                          *
13356                          *  @example
13357                          *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
13358                          *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
13359                          *    }
13360                          */
13361                         search: {},
13362         
13363         
13364                         /**
13365                          * Type based ordering.
13366                          *
13367                          * The column type tells DataTables what ordering to apply to the table
13368                          * when a column is sorted upon. The order for each type that is defined,
13369                          * is defined by the functions available in this object.
13370                          *
13371                          * Each ordering option can be described by three properties added to
13372                          * this object:
13373                          *
13374                          * * `{type}-pre` - Pre-formatting function
13375                          * * `{type}-asc` - Ascending order function
13376                          * * `{type}-desc` - Descending order function
13377                          *
13378                          * All three can be used together, only `{type}-pre` or only
13379                          * `{type}-asc` and `{type}-desc` together. It is generally recommended
13380                          * that only `{type}-pre` is used, as this provides the optimal
13381                          * implementation in terms of speed, although the others are provided
13382                          * for compatibility with existing Javascript sort functions.
13383                          *
13384                          * `{type}-pre`: Functions defined take a single parameter:
13385                          *
13386                      *  1. `{*}` Data from the column cell to be prepared for ordering
13387                          *
13388                          * And return:
13389                          *
13390                          * * `{*}` Data to be sorted upon
13391                          *
13392                          * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
13393                          * functions, taking two parameters:
13394                          *
13395                      *  1. `{*}` Data to compare to the second parameter
13396                      *  2. `{*}` Data to compare to the first parameter
13397                          *
13398                          * And returning:
13399                          *
13400                          * * `{*}` Ordering match: <0 if first parameter should be sorted lower
13401                          *   than the second parameter, ===0 if the two parameters are equal and
13402                          *   >0 if the first parameter should be sorted height than the second
13403                          *   parameter.
13404                          * 
13405                          *  @type object
13406                          *  @default {}
13407                          *
13408                          *  @example
13409                          *    // Numeric ordering of formatted numbers with a pre-formatter
13410                          *    $.extend( $.fn.dataTable.ext.type.order, {
13411                          *      "string-pre": function(x) {
13412                          *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
13413                          *        return parseFloat( a );
13414                          *      }
13415                          *    } );
13416                          *
13417                          *  @example
13418                          *    // Case-sensitive string ordering, with no pre-formatting method
13419                          *    $.extend( $.fn.dataTable.ext.order, {
13420                          *      "string-case-asc": function(x,y) {
13421                          *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
13422                          *      },
13423                          *      "string-case-desc": function(x,y) {
13424                          *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
13425                          *      }
13426                          *    } );
13427                          */
13428                         order: {}
13429                 },
13430         
13431                 /**
13432                  * Unique DataTables instance counter
13433                  *
13434                  * @type int
13435                  * @private
13436                  */
13437                 _unique: 0,
13438         
13439         
13440                 //
13441                 // Depreciated
13442                 // The following properties are retained for backwards compatiblity only.
13443                 // The should not be used in new projects and will be removed in a future
13444                 // version
13445                 //
13446         
13447                 /**
13448                  * Version check function.
13449                  *  @type function
13450                  *  @depreciated Since 1.10
13451                  */
13452                 fnVersionCheck: DataTable.fnVersionCheck,
13453         
13454         
13455                 /**
13456                  * Index for what 'this' index API functions should use
13457                  *  @type int
13458                  *  @deprecated Since v1.10
13459                  */
13460                 iApiIndex: 0,
13461         
13462         
13463                 /**
13464                  * jQuery UI class container
13465                  *  @type object
13466                  *  @deprecated Since v1.10
13467                  */
13468                 oJUIClasses: {},
13469         
13470         
13471                 /**
13472                  * Software version
13473                  *  @type string
13474                  *  @deprecated Since v1.10
13475                  */
13476                 sVersion: DataTable.version
13477         };
13478         
13479         
13480         //
13481         // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
13482         //
13483         $.extend( _ext, {
13484                 afnFiltering: _ext.search,
13485                 aTypes:       _ext.type.detect,
13486                 ofnSearch:    _ext.type.search,
13487                 oSort:        _ext.type.order,
13488                 afnSortData:  _ext.order,
13489                 aoFeatures:   _ext.feature,
13490                 oApi:         _ext.internal,
13491                 oStdClasses:  _ext.classes,
13492                 oPagination:  _ext.pager
13493         } );
13494         
13495         
13496         $.extend( DataTable.ext.classes, {
13497                 "sTable": "dataTable",
13498                 "sNoFooter": "no-footer",
13499         
13500                 /* Paging buttons */
13501                 "sPageButton": "paginate_button",
13502                 "sPageButtonActive": "current",
13503                 "sPageButtonDisabled": "disabled",
13504         
13505                 /* Striping classes */
13506                 "sStripeOdd": "odd",
13507                 "sStripeEven": "even",
13508         
13509                 /* Empty row */
13510                 "sRowEmpty": "dataTables_empty",
13511         
13512                 /* Features */
13513                 "sWrapper": "dataTables_wrapper",
13514                 "sFilter": "dataTables_filter",
13515                 "sInfo": "dataTables_info",
13516                 "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
13517                 "sLength": "dataTables_length",
13518                 "sProcessing": "dataTables_processing",
13519         
13520                 /* Sorting */
13521                 "sSortAsc": "sorting_asc",
13522                 "sSortDesc": "sorting_desc",
13523                 "sSortable": "sorting", /* Sortable in both directions */
13524                 "sSortableAsc": "sorting_asc_disabled",
13525                 "sSortableDesc": "sorting_desc_disabled",
13526                 "sSortableNone": "sorting_disabled",
13527                 "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
13528         
13529                 /* Filtering */
13530                 "sFilterInput": "",
13531         
13532                 /* Page length */
13533                 "sLengthSelect": "",
13534         
13535                 /* Scrolling */
13536                 "sScrollWrapper": "dataTables_scroll",
13537                 "sScrollHead": "dataTables_scrollHead",
13538                 "sScrollHeadInner": "dataTables_scrollHeadInner",
13539                 "sScrollBody": "dataTables_scrollBody",
13540                 "sScrollFoot": "dataTables_scrollFoot",
13541                 "sScrollFootInner": "dataTables_scrollFootInner",
13542         
13543                 /* Misc */
13544                 "sHeaderTH": "",
13545                 "sFooterTH": "",
13546         
13547                 // Deprecated
13548                 "sSortJUIAsc": "",
13549                 "sSortJUIDesc": "",
13550                 "sSortJUI": "",
13551                 "sSortJUIAscAllowed": "",
13552                 "sSortJUIDescAllowed": "",
13553                 "sSortJUIWrapper": "",
13554                 "sSortIcon": "",
13555                 "sJUIHeader": "",
13556                 "sJUIFooter": ""
13557         } );
13558         
13559         
13560         (function() {
13561         
13562         // Reused strings for better compression. Closure compiler appears to have a
13563         // weird edge case where it is trying to expand strings rather than use the
13564         // variable version. This results in about 200 bytes being added, for very
13565         // little preference benefit since it this run on script load only.
13566         var _empty = '';
13567         _empty = '';
13568         
13569         var _stateDefault = _empty + 'ui-state-default';
13570         var _sortIcon     = _empty + 'css_right ui-icon ui-icon-';
13571         var _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix';
13572         
13573         $.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, {
13574                 /* Full numbers paging buttons */
13575                 "sPageButton":         "fg-button ui-button "+_stateDefault,
13576                 "sPageButtonActive":   "ui-state-disabled",
13577                 "sPageButtonDisabled": "ui-state-disabled",
13578         
13579                 /* Features */
13580                 "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
13581                         "ui-buttonset-multi paging_", /* Note that the type is postfixed */
13582         
13583                 /* Sorting */
13584                 "sSortAsc":            _stateDefault+" sorting_asc",
13585                 "sSortDesc":           _stateDefault+" sorting_desc",
13586                 "sSortable":           _stateDefault+" sorting",
13587                 "sSortableAsc":        _stateDefault+" sorting_asc_disabled",
13588                 "sSortableDesc":       _stateDefault+" sorting_desc_disabled",
13589                 "sSortableNone":       _stateDefault+" sorting_disabled",
13590                 "sSortJUIAsc":         _sortIcon+"triangle-1-n",
13591                 "sSortJUIDesc":        _sortIcon+"triangle-1-s",
13592                 "sSortJUI":            _sortIcon+"carat-2-n-s",
13593                 "sSortJUIAscAllowed":  _sortIcon+"carat-1-n",
13594                 "sSortJUIDescAllowed": _sortIcon+"carat-1-s",
13595                 "sSortJUIWrapper":     "DataTables_sort_wrapper",
13596                 "sSortIcon":           "DataTables_sort_icon",
13597         
13598                 /* Scrolling */
13599                 "sScrollHead": "dataTables_scrollHead "+_stateDefault,
13600                 "sScrollFoot": "dataTables_scrollFoot "+_stateDefault,
13601         
13602                 /* Misc */
13603                 "sHeaderTH":  _stateDefault,
13604                 "sFooterTH":  _stateDefault,
13605                 "sJUIHeader": _headerFooter+" ui-corner-tl ui-corner-tr",
13606                 "sJUIFooter": _headerFooter+" ui-corner-bl ui-corner-br"
13607         } );
13608         
13609         }());
13610         
13611         
13612         
13613         var extPagination = DataTable.ext.pager;
13614         
13615         function _numbers ( page, pages ) {
13616                 var
13617                         numbers = [],
13618                         buttons = extPagination.numbers_length,
13619                         half = Math.floor( buttons / 2 ),
13620                         i = 1;
13621         
13622                 if ( pages <= buttons ) {
13623                         numbers = _range( 0, pages );
13624                 }
13625                 else if ( page <= half ) {
13626                         numbers = _range( 0, buttons-2 );
13627                         numbers.push( 'ellipsis' );
13628                         numbers.push( pages-1 );
13629                 }
13630                 else if ( page >= pages - 1 - half ) {
13631                         numbers = _range( pages-(buttons-2), pages );
13632                         numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
13633                         numbers.splice( 0, 0, 0 );
13634                 }
13635                 else {
13636                         numbers = _range( page-1, page+2 );
13637                         numbers.push( 'ellipsis' );
13638                         numbers.push( pages-1 );
13639                         numbers.splice( 0, 0, 'ellipsis' );
13640                         numbers.splice( 0, 0, 0 );
13641                 }
13642         
13643                 numbers.DT_el = 'span';
13644                 return numbers;
13645         }
13646         
13647         
13648         $.extend( extPagination, {
13649                 simple: function ( page, pages ) {
13650                         return [ 'previous', 'next' ];
13651                 },
13652         
13653                 full: function ( page, pages ) {
13654                         return [  'first', 'previous', 'next', 'last' ];
13655                 },
13656         
13657                 simple_numbers: function ( page, pages ) {
13658                         return [ 'previous', _numbers(page, pages), 'next' ];
13659                 },
13660         
13661                 full_numbers: function ( page, pages ) {
13662                         return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
13663                 },
13664         
13665                 // For testing and plug-ins to use
13666                 _numbers: _numbers,
13667                 numbers_length: 7
13668         } );
13669         
13670         
13671         $.extend( true, DataTable.ext.renderer, {
13672                 pageButton: {
13673                         _: function ( settings, host, idx, buttons, page, pages ) {
13674                                 var classes = settings.oClasses;
13675                                 var lang = settings.oLanguage.oPaginate;
13676                                 var btnDisplay, btnClass, counter=0;
13677         
13678                                 var attach = function( container, buttons ) {
13679                                         var i, ien, node, button;
13680                                         var clickHandler = function ( e ) {
13681                                                 _fnPageChange( settings, e.data.action, true );
13682                                         };
13683         
13684                                         for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
13685                                                 button = buttons[i];
13686         
13687                                                 if ( $.isArray( button ) ) {
13688                                                         var inner = $( '<'+(button.DT_el || 'div')+'/>' )
13689                                                                 .appendTo( container );
13690                                                         attach( inner, button );
13691                                                 }
13692                                                 else {
13693                                                         btnDisplay = '';
13694                                                         btnClass = '';
13695         
13696                                                         switch ( button ) {
13697                                                                 case 'ellipsis':
13698                                                                         container.append('<span>&hellip;</span>');
13699                                                                         break;
13700         
13701                                                                 case 'first':
13702                                                                         btnDisplay = lang.sFirst;
13703                                                                         btnClass = button + (page > 0 ?
13704                                                                                 '' : ' '+classes.sPageButtonDisabled);
13705                                                                         break;
13706         
13707                                                                 case 'previous':
13708                                                                         btnDisplay = lang.sPrevious;
13709                                                                         btnClass = button + (page > 0 ?
13710                                                                                 '' : ' '+classes.sPageButtonDisabled);
13711                                                                         break;
13712         
13713                                                                 case 'next':
13714                                                                         btnDisplay = lang.sNext;
13715                                                                         btnClass = button + (page < pages-1 ?
13716                                                                                 '' : ' '+classes.sPageButtonDisabled);
13717                                                                         break;
13718         
13719                                                                 case 'last':
13720                                                                         btnDisplay = lang.sLast;
13721                                                                         btnClass = button + (page < pages-1 ?
13722                                                                                 '' : ' '+classes.sPageButtonDisabled);
13723                                                                         break;
13724         
13725                                                                 default:
13726                                                                         btnDisplay = button + 1;
13727                                                                         btnClass = page === button ?
13728                                                                                 classes.sPageButtonActive : '';
13729                                                                         break;
13730                                                         }
13731         
13732                                                         if ( btnDisplay ) {
13733                                                                 node = $('<a>', {
13734                                                                                 'class': classes.sPageButton+' '+btnClass,
13735                                                                                 'aria-controls': settings.sTableId,
13736                                                                                 'data-dt-idx': counter,
13737                                                                                 'tabindex': settings.iTabIndex,
13738                                                                                 'id': idx === 0 && typeof button === 'string' ?
13739                                                                                         settings.sTableId +'_'+ button :
13740                                                                                         null
13741                                                                         } )
13742                                                                         .html( btnDisplay )
13743                                                                         .appendTo( container );
13744         
13745                                                                 _fnBindAction(
13746                                                                         node, {action: button}, clickHandler
13747                                                                 );
13748         
13749                                                                 counter++;
13750                                                         }
13751                                                 }
13752                                         }
13753                                 };
13754         
13755                                 // Because this approach is destroying and recreating the paging
13756                                 // elements, focus is lost on the select button which is bad for
13757                                 // accessibility. So we want to restore focus once the draw has
13758                                 // completed
13759                                 var activeEl = $(document.activeElement).data('dt-idx');
13760         
13761                                 attach( $(host).empty(), buttons );
13762         
13763                                 if ( activeEl !== null ) {
13764                                         $(host).find( '[data-dt-idx='+activeEl+']' ).focus();
13765                                 }
13766                         }
13767                 }
13768         } );
13769         
13770         
13771         
13772         var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
13773                 if ( !d || d === '-' ) {
13774                         return -Infinity;
13775                 }
13776         
13777                 // If a decimal place other than `.` is used, it needs to be given to the
13778                 // function so we can detect it and replace with a `.` which is the only
13779                 // decimal place Javascript recognises - it is not locale aware.
13780                 if ( decimalPlace ) {
13781                         d = _numToDecimal( d, decimalPlace );
13782                 }
13783         
13784                 if ( d.replace ) {
13785                         if ( re1 ) {
13786                                 d = d.replace( re1, '' );
13787                         }
13788         
13789                         if ( re2 ) {
13790                                 d = d.replace( re2, '' );
13791                         }
13792                 }
13793         
13794                 return d * 1;
13795         };
13796         
13797         
13798         // Add the numeric 'deformatting' functions for sorting. This is done in a
13799         // function to provide an easy ability for the language options to add
13800         // additional methods if a non-period decimal place is used.
13801         function _addNumericSort ( decimalPlace ) {
13802                 $.each(
13803                         {
13804                                 // Plain numbers
13805                                 "num": function ( d ) {
13806                                         return __numericReplace( d, decimalPlace );
13807                                 },
13808         
13809                                 // Formatted numbers
13810                                 "num-fmt": function ( d ) {
13811                                         return __numericReplace( d, decimalPlace, _re_formatted_numeric );
13812                                 },
13813         
13814                                 // HTML numeric
13815                                 "html-num": function ( d ) {
13816                                         return __numericReplace( d, decimalPlace, _re_html );
13817                                 },
13818         
13819                                 // HTML numeric, formatted
13820                                 "html-num-fmt": function ( d ) {
13821                                         return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
13822                                 }
13823                         },
13824                         function ( key, fn ) {
13825                                 _ext.type.order[ key+decimalPlace+'-pre' ] = fn;
13826                         }
13827                 );
13828         }
13829         
13830         
13831         // Default sort methods
13832         $.extend( _ext.type.order, {
13833                 // Dates
13834                 "date-pre": function ( d ) {
13835                         return Date.parse( d ) || 0;
13836                 },
13837         
13838                 // html
13839                 "html-pre": function ( a ) {
13840                         return ! a ?
13841                                 '' :
13842                                 a.replace ?
13843                                         a.replace( /<.*?>/g, "" ).toLowerCase() :
13844                                         a+'';
13845                 },
13846         
13847                 // string
13848                 "string-pre": function ( a ) {
13849                         return typeof a === 'string' ?
13850                                 a.toLowerCase() :
13851                                 ! a || ! a.toString ?
13852                                         '' :
13853                                         a.toString();
13854                 },
13855         
13856                 // string-asc and -desc are retained only for compatibility with the old
13857                 // sort methods
13858                 "string-asc": function ( x, y ) {
13859                         return ((x < y) ? -1 : ((x > y) ? 1 : 0));
13860                 },
13861         
13862                 "string-desc": function ( x, y ) {
13863                         return ((x < y) ? 1 : ((x > y) ? -1 : 0));
13864                 }
13865         } );
13866         
13867         
13868         // Numeric sorting types - order doesn't matter here
13869         _addNumericSort( '' );
13870         
13871         
13872         // Built in type detection. See model.ext.aTypes for information about
13873         // what is required from this methods.
13874         $.extend( DataTable.ext.type.detect, [
13875                 // Plain numbers - first since V8 detects some plain numbers as dates
13876                 // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
13877                 function ( d, settings )
13878                 {
13879                         var decimal = settings.oLanguage.sDecimal;
13880                         return _isNumber( d, decimal ) ? 'num'+decimal : null;
13881                 },
13882         
13883                 // Dates (only those recognised by the browser's Date.parse)
13884                 function ( d, settings )
13885                 {
13886                         // V8 will remove any unknown characters at the start of the expression,
13887                         // leading to false matches such as `$245.12` being a valid date. See
13888                         // forum thread 18941 for detail.
13889                         if ( d && ! _re_date_start.test(d) ) {
13890                                 return null;
13891                         }
13892                         var parsed = Date.parse(d);
13893                         return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
13894                 },
13895         
13896                 // Formatted numbers
13897                 function ( d, settings )
13898                 {
13899                         var decimal = settings.oLanguage.sDecimal;
13900                         return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
13901                 },
13902         
13903                 // HTML numeric
13904                 function ( d, settings )
13905                 {
13906                         var decimal = settings.oLanguage.sDecimal;
13907                         return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
13908                 },
13909         
13910                 // HTML numeric, formatted
13911                 function ( d, settings )
13912                 {
13913                         var decimal = settings.oLanguage.sDecimal;
13914                         return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
13915                 },
13916         
13917                 // HTML (this is strict checking - there must be html)
13918                 function ( d, settings )
13919                 {
13920                         return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
13921                                 'html' : null;
13922                 }
13923         ] );
13924         
13925         
13926         
13927         // Filter formatting functions. See model.ext.ofnSearch for information about
13928         // what is required from these methods.
13929         
13930         
13931         $.extend( DataTable.ext.type.search, {
13932                 html: function ( data ) {
13933                         return _empty(data) ?
13934                                 '' :
13935                                 typeof data === 'string' ?
13936                                         data
13937                                                 .replace( _re_new_lines, " " )
13938                                                 .replace( _re_html, "" ) :
13939                                         '';
13940                 },
13941         
13942                 string: function ( data ) {
13943                         return _empty(data) ?
13944                                 '' :
13945                                 typeof data === 'string' ?
13946                                         data.replace( _re_new_lines, " " ) :
13947                                         data;
13948                 }
13949         } );
13950         
13951         
13952         
13953         $.extend( true, DataTable.ext.renderer, {
13954                 header: {
13955                         _: function ( settings, cell, column, classes ) {
13956                                 // No additional mark-up required
13957                                 // Attach a sort listener to update on sort - note that using the
13958                                 // `DT` namespace will allow the event to be removed automatically
13959                                 // on destroy, while the `dt` namespaced event is the one we are
13960                                 // listening for
13961                                 $(settings.nTable).on( 'order.dt.DT', function ( e, settings, sorting, columns ) {
13962                                         var colIdx = column.idx;
13963         
13964                                         cell
13965                                                 .removeClass(
13966                                                         column.sSortingClass +' '+
13967                                                         classes.sSortAsc +' '+
13968                                                         classes.sSortDesc
13969                                                 )
13970                                                 .addClass( columns[ colIdx ] == 'asc' ?
13971                                                         classes.sSortAsc : columns[ colIdx ] == 'desc' ?
13972                                                                 classes.sSortDesc :
13973                                                                 column.sSortingClass
13974                                                 );
13975                                 } );
13976                         },
13977         
13978                         jqueryui: function ( settings, cell, column, classes ) {
13979                                 var colIdx = column.idx;
13980         
13981                                 $('<div/>')
13982                                         .addClass( classes.sSortJUIWrapper )
13983                                         .append( cell.contents() )
13984                                         .append( $('<span/>')
13985                                                 .addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
13986                                         )
13987                                         .appendTo( cell );
13988         
13989                                 // Attach a sort listener to update on sort
13990                                 $(settings.nTable).on( 'order.dt.DT', function ( e, settings, sorting, columns ) {
13991                                         cell
13992                                                 .removeClass( classes.sSortAsc +" "+classes.sSortDesc )
13993                                                 .addClass( columns[ colIdx ] == 'asc' ?
13994                                                         classes.sSortAsc : columns[ colIdx ] == 'desc' ?
13995                                                                 classes.sSortDesc :
13996                                                                 column.sSortingClass
13997                                                 );
13998         
13999                                         cell
14000                                                 .find( 'span.'+classes.sSortIcon )
14001                                                 .removeClass(
14002                                                         classes.sSortJUIAsc +" "+
14003                                                         classes.sSortJUIDesc +" "+
14004                                                         classes.sSortJUI +" "+
14005                                                         classes.sSortJUIAscAllowed +" "+
14006                                                         classes.sSortJUIDescAllowed
14007                                                 )
14008                                                 .addClass( columns[ colIdx ] == 'asc' ?
14009                                                         classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14010                                                                 classes.sSortJUIDesc :
14011                                                                 column.sSortingClassJUI
14012                                                 );
14013                                 } );
14014                         }
14015                 }
14016         } );
14017         
14018         /*
14019          * Public helper functions. These aren't used internally by DataTables, or
14020          * called by any of the options passed into DataTables, but they can be used
14021          * externally by developers working with DataTables. They are helper functions
14022          * to make working with DataTables a little bit easier.
14023          */
14024         
14025         /**
14026          * Helpers for `columns.render`.
14027          *
14028          * The options defined here can be used with the `columns.render` initialisation
14029          * option to provide a display renderer. The following functions are defined:
14030          *
14031          * * `number` - Will format numeric data (defined by `columns.data`) for
14032          *   display, retaining the original unformatted data for sorting and filtering.
14033          *   It takes 4 parameters:
14034          *   * `string` - Thousands grouping separator
14035          *   * `string` - Decimal point indicator
14036          *   * `integer` - Number of decimal points to show
14037          *   * `string` (optional) - Prefix.
14038          *
14039          * @example
14040          *   // Column definition using the number renderer
14041          *   {
14042          *     data: "salary",
14043          *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14044          *   }
14045          *
14046          * @namespace
14047          */
14048         DataTable.render = {
14049                 number: function ( thousands, decimal, precision, prefix ) {
14050                         return {
14051                                 display: function ( d ) {
14052                                         d = parseFloat( d );
14053                                         var intPart = parseInt( d, 10 );
14054                                         var floatPart = precision ?
14055                                                 (decimal+(d - intPart).toFixed( precision )).substring( 2 ):
14056                                                 '';
14057         
14058                                         return (prefix||'') +
14059                                                 intPart.toString().replace(
14060                                                         /\B(?=(\d{3})+(?!\d))/g, thousands
14061                                                 ) +
14062                                                 floatPart;
14063                                 }
14064                         };
14065                 }
14066         };
14067         
14068         
14069         /*
14070          * This is really a good bit rubbish this method of exposing the internal methods
14071          * publicly... - To be fixed in 2.0 using methods on the prototype
14072          */
14073         
14074         
14075         /**
14076          * Create a wrapper function for exporting an internal functions to an external API.
14077          *  @param {string} fn API function name
14078          *  @returns {function} wrapped function
14079          *  @memberof DataTable#internal
14080          */
14081         function _fnExternApiFunc (fn)
14082         {
14083                 return function() {
14084                         var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
14085                                 Array.prototype.slice.call(arguments)
14086                         );
14087                         return DataTable.ext.internal[fn].apply( this, args );
14088                 };
14089         }
14090         
14091         
14092         /**
14093          * Reference to internal functions for use by plug-in developers. Note that
14094          * these methods are references to internal functions and are considered to be
14095          * private. If you use these methods, be aware that they are liable to change
14096          * between versions.
14097          *  @namespace
14098          */
14099         $.extend( DataTable.ext.internal, {
14100                 _fnExternApiFunc: _fnExternApiFunc,
14101                 _fnBuildAjax: _fnBuildAjax,
14102                 _fnAjaxUpdate: _fnAjaxUpdate,
14103                 _fnAjaxParameters: _fnAjaxParameters,
14104                 _fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
14105                 _fnAjaxDataSrc: _fnAjaxDataSrc,
14106                 _fnAddColumn: _fnAddColumn,
14107                 _fnColumnOptions: _fnColumnOptions,
14108                 _fnAdjustColumnSizing: _fnAdjustColumnSizing,
14109                 _fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
14110                 _fnColumnIndexToVisible: _fnColumnIndexToVisible,
14111                 _fnVisbleColumns: _fnVisbleColumns,
14112                 _fnGetColumns: _fnGetColumns,
14113                 _fnColumnTypes: _fnColumnTypes,
14114                 _fnApplyColumnDefs: _fnApplyColumnDefs,
14115                 _fnHungarianMap: _fnHungarianMap,
14116                 _fnCamelToHungarian: _fnCamelToHungarian,
14117                 _fnLanguageCompat: _fnLanguageCompat,
14118                 _fnBrowserDetect: _fnBrowserDetect,
14119                 _fnAddData: _fnAddData,
14120                 _fnAddTr: _fnAddTr,
14121                 _fnNodeToDataIndex: _fnNodeToDataIndex,
14122                 _fnNodeToColumnIndex: _fnNodeToColumnIndex,
14123                 _fnGetCellData: _fnGetCellData,
14124                 _fnSetCellData: _fnSetCellData,
14125                 _fnSplitObjNotation: _fnSplitObjNotation,
14126                 _fnGetObjectDataFn: _fnGetObjectDataFn,
14127                 _fnSetObjectDataFn: _fnSetObjectDataFn,
14128                 _fnGetDataMaster: _fnGetDataMaster,
14129                 _fnClearTable: _fnClearTable,
14130                 _fnDeleteIndex: _fnDeleteIndex,
14131                 _fnInvalidateRow: _fnInvalidateRow,
14132                 _fnGetRowElements: _fnGetRowElements,
14133                 _fnCreateTr: _fnCreateTr,
14134                 _fnBuildHead: _fnBuildHead,
14135                 _fnDrawHead: _fnDrawHead,
14136                 _fnDraw: _fnDraw,
14137                 _fnReDraw: _fnReDraw,
14138                 _fnAddOptionsHtml: _fnAddOptionsHtml,
14139                 _fnDetectHeader: _fnDetectHeader,
14140                 _fnGetUniqueThs: _fnGetUniqueThs,
14141                 _fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
14142                 _fnFilterComplete: _fnFilterComplete,
14143                 _fnFilterCustom: _fnFilterCustom,
14144                 _fnFilterColumn: _fnFilterColumn,
14145                 _fnFilter: _fnFilter,
14146                 _fnFilterCreateSearch: _fnFilterCreateSearch,
14147                 _fnEscapeRegex: _fnEscapeRegex,
14148                 _fnFilterData: _fnFilterData,
14149                 _fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
14150                 _fnUpdateInfo: _fnUpdateInfo,
14151                 _fnInfoMacros: _fnInfoMacros,
14152                 _fnInitialise: _fnInitialise,
14153                 _fnInitComplete: _fnInitComplete,
14154                 _fnLengthChange: _fnLengthChange,
14155                 _fnFeatureHtmlLength: _fnFeatureHtmlLength,
14156                 _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
14157                 _fnPageChange: _fnPageChange,
14158                 _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
14159                 _fnProcessingDisplay: _fnProcessingDisplay,
14160                 _fnFeatureHtmlTable: _fnFeatureHtmlTable,
14161                 _fnScrollDraw: _fnScrollDraw,
14162                 _fnApplyToChildren: _fnApplyToChildren,
14163                 _fnCalculateColumnWidths: _fnCalculateColumnWidths,
14164                 _fnThrottle: _fnThrottle,
14165                 _fnConvertToWidth: _fnConvertToWidth,
14166                 _fnScrollingWidthAdjust: _fnScrollingWidthAdjust,
14167                 _fnGetWidestNode: _fnGetWidestNode,
14168                 _fnGetMaxLenString: _fnGetMaxLenString,
14169                 _fnStringToCss: _fnStringToCss,
14170                 _fnScrollBarWidth: _fnScrollBarWidth,
14171                 _fnSortFlatten: _fnSortFlatten,
14172                 _fnSort: _fnSort,
14173                 _fnSortAria: _fnSortAria,
14174                 _fnSortListener: _fnSortListener,
14175                 _fnSortAttachListener: _fnSortAttachListener,
14176                 _fnSortingClasses: _fnSortingClasses,
14177                 _fnSortData: _fnSortData,
14178                 _fnSaveState: _fnSaveState,
14179                 _fnLoadState: _fnLoadState,
14180                 _fnSettingsFromNode: _fnSettingsFromNode,
14181                 _fnLog: _fnLog,
14182                 _fnMap: _fnMap,
14183                 _fnBindAction: _fnBindAction,
14184                 _fnCallbackReg: _fnCallbackReg,
14185                 _fnCallbackFire: _fnCallbackFire,
14186                 _fnLengthOverflow: _fnLengthOverflow,
14187                 _fnRenderer: _fnRenderer,
14188                 _fnDataSource: _fnDataSource,
14189                 _fnRowAttributes: _fnRowAttributes,
14190                 _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
14191                                                 // in 1.10, so this dead-end function is
14192                                                 // added to prevent errors
14193         } );
14194         
14195
14196         // jQuery access
14197         $.fn.dataTable = DataTable;
14198
14199         // Legacy aliases
14200         $.fn.dataTableSettings = DataTable.settings;
14201         $.fn.dataTableExt = DataTable.ext;
14202
14203         // With a capital `D` we return a DataTables API instance rather than a
14204         // jQuery object
14205         $.fn.DataTable = function ( opts ) {
14206                 return $(this).dataTable( opts ).api();
14207         };
14208
14209         // All properties that are available to $.fn.dataTable should also be
14210         // available on $.fn.DataTable
14211         $.each( DataTable, function ( prop, val ) {
14212                 $.fn.DataTable[ prop ] = val;
14213         } );
14214
14215
14216         // Information about events fired by DataTables - for documentation.
14217         /**
14218          * Draw event, fired whenever the table is redrawn on the page, at the same
14219          * point as fnDrawCallback. This may be useful for binding events or
14220          * performing calculations when the table is altered at all.
14221          *  @name DataTable#draw.dt
14222          *  @event
14223          *  @param {event} e jQuery event object
14224          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14225          */
14226
14227         /**
14228          * Search event, fired when the searching applied to the table (using the
14229          * built-in global search, or column filters) is altered.
14230          *  @name DataTable#search.dt
14231          *  @event
14232          *  @param {event} e jQuery event object
14233          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14234          */
14235
14236         /**
14237          * Page change event, fired when the paging of the table is altered.
14238          *  @name DataTable#page.dt
14239          *  @event
14240          *  @param {event} e jQuery event object
14241          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14242          */
14243
14244         /**
14245          * Order event, fired when the ordering applied to the table is altered.
14246          *  @name DataTable#order.dt
14247          *  @event
14248          *  @param {event} e jQuery event object
14249          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14250          */
14251
14252         /**
14253          * DataTables initialisation complete event, fired when the table is fully
14254          * drawn, including Ajax data loaded, if Ajax data is required.
14255          *  @name DataTable#init.dt
14256          *  @event
14257          *  @param {event} e jQuery event object
14258          *  @param {object} oSettings DataTables settings object
14259          *  @param {object} json The JSON object request from the server - only
14260          *    present if client-side Ajax sourced data is used</li></ol>
14261          */
14262
14263         /**
14264          * State save event, fired when the table has changed state a new state save
14265          * is required. This event allows modification of the state saving object
14266          * prior to actually doing the save, including addition or other state
14267          * properties (for plug-ins) or modification of a DataTables core property.
14268          *  @name DataTable#stateSaveParams.dt
14269          *  @event
14270          *  @param {event} e jQuery event object
14271          *  @param {object} oSettings DataTables settings object
14272          *  @param {object} json The state information to be saved
14273          */
14274
14275         /**
14276          * State load event, fired when the table is loading state from the stored
14277          * data, but prior to the settings object being modified by the saved state
14278          * - allowing modification of the saved state is required or loading of
14279          * state for a plug-in.
14280          *  @name DataTable#stateLoadParams.dt
14281          *  @event
14282          *  @param {event} e jQuery event object
14283          *  @param {object} oSettings DataTables settings object
14284          *  @param {object} json The saved state information
14285          */
14286
14287         /**
14288          * State loaded event, fired when state has been loaded from stored data and
14289          * the settings object has been modified by the loaded data.
14290          *  @name DataTable#stateLoaded.dt
14291          *  @event
14292          *  @param {event} e jQuery event object
14293          *  @param {object} oSettings DataTables settings object
14294          *  @param {object} json The saved state information
14295          */
14296
14297         /**
14298          * Processing event, fired when DataTables is doing some kind of processing
14299          * (be it, order, searcg or anything else). It can be used to indicate to
14300          * the end user that there is something happening, or that something has
14301          * finished.
14302          *  @name DataTable#processing.dt
14303          *  @event
14304          *  @param {event} e jQuery event object
14305          *  @param {object} oSettings DataTables settings object
14306          *  @param {boolean} bShow Flag for if DataTables is doing processing or not
14307          */
14308
14309         /**
14310          * Ajax (XHR) event, fired whenever an Ajax request is completed from a
14311          * request to made to the server for new data. This event is called before
14312          * DataTables processed the returned data, so it can also be used to pre-
14313          * process the data returned from the server, if needed.
14314          *
14315          * Note that this trigger is called in `fnServerData`, if you override
14316          * `fnServerData` and which to use this event, you need to trigger it in you
14317          * success function.
14318          *  @name DataTable#xhr.dt
14319          *  @event
14320          *  @param {event} e jQuery event object
14321          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14322          *  @param {object} json JSON returned from the server
14323          *
14324          *  @example
14325          *     // Use a custom property returned from the server in another DOM element
14326          *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
14327          *       $('#status').html( json.status );
14328          *     } );
14329          *
14330          *  @example
14331          *     // Pre-process the data returned from the server
14332          *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
14333          *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
14334          *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
14335          *       }
14336          *       // Note no return - manipulate the data directly in the JSON object.
14337          *     } );
14338          */
14339
14340         /**
14341          * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
14342          * or passing the bDestroy:true parameter in the initialisation object. This
14343          * can be used to remove bound events, added DOM nodes, etc.
14344          *  @name DataTable#destroy.dt
14345          *  @event
14346          *  @param {event} e jQuery event object
14347          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14348          */
14349
14350         /**
14351          * Page length change event, fired when number of records to show on each
14352          * page (the length) is changed.
14353          *  @name DataTable#length.dt
14354          *  @event
14355          *  @param {event} e jQuery event object
14356          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14357          *  @param {integer} len New length
14358          */
14359
14360         /**
14361          * Column sizing has changed.
14362          *  @name DataTable#column-sizing.dt
14363          *  @event
14364          *  @param {event} e jQuery event object
14365          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14366          */
14367
14368         /**
14369          * Column visibility has changed.
14370          *  @name DataTable#column-visibility.dt
14371          *  @event
14372          *  @param {event} e jQuery event object
14373          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14374          *  @param {int} column Column index
14375          *  @param {bool} vis `false` if column now hidden, or `true` if visible
14376          */
14377
14378         return $.fn.dataTable;
14379 }));
14380
14381 }(window, document));
14382