]> git.somenet.org - fsinf/pub/w2c.git/blob - jquery.dataTables.js
gruppenfotoerlaubnis feld geadded
[fsinf/pub/w2c.git] / jquery.dataTables.js
1 /*! DataTables 1.10.7
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.7
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,_fnInvalidate,_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         module.exports = 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 = /^[\w\+\-]/;
109         var _re_date_end = /[\w\+\-]$/;
110         
111         // Escape regular expression special characters
112         var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
113         
114         // http://en.wikipedia.org/wiki/Foreign_exchange_market
115         // - \u20BD - Russian ruble.
116         // - \u20a9 - South Korean Won
117         // - \u20BA - Turkish Lira
118         // - \u20B9 - Indian Rupee
119         // - R - Brazil (R$) and South Africa
120         // - fr - Swiss Franc
121         // - kr - Swedish krona, Norwegian krone and Danish krone
122         // - \u2009 is thin space and \u202F is narrow no-break space, both used in many
123         //   standards as thousands separators.
124         var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi;
125         
126         
127         var _empty = function ( d ) {
128                 return !d || d === true || d === '-' ? true : false;
129         };
130         
131         
132         var _intVal = function ( s ) {
133                 var integer = parseInt( s, 10 );
134                 return !isNaN(integer) && isFinite(s) ? integer : null;
135         };
136         
137         // Convert from a formatted number with characters other than `.` as the
138         // decimal place, to a Javascript number
139         var _numToDecimal = function ( num, decimalPoint ) {
140                 // Cache created regular expressions for speed as this function is called often
141                 if ( ! _re_dic[ decimalPoint ] ) {
142                         _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
143                 }
144                 return typeof num === 'string' && decimalPoint !== '.' ?
145                         num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
146                         num;
147         };
148         
149         
150         var _isNumber = function ( d, decimalPoint, formatted ) {
151                 var strType = typeof d === 'string';
152         
153                 // If empty return immediately so there must be a number if it is a
154                 // formatted string (this stops the string "k", or "kr", etc being detected
155                 // as a formatted number for currency
156                 if ( _empty( d ) ) {
157                         return true;
158                 }
159         
160                 if ( decimalPoint && strType ) {
161                         d = _numToDecimal( d, decimalPoint );
162                 }
163         
164                 if ( formatted && strType ) {
165                         d = d.replace( _re_formatted_numeric, '' );
166                 }
167         
168                 return !isNaN( parseFloat(d) ) && isFinite( d );
169         };
170         
171         
172         // A string without HTML in it can be considered to be HTML still
173         var _isHtml = function ( d ) {
174                 return _empty( d ) || typeof d === 'string';
175         };
176         
177         
178         var _htmlNumeric = function ( d, decimalPoint, formatted ) {
179                 if ( _empty( d ) ) {
180                         return true;
181                 }
182         
183                 var html = _isHtml( d );
184                 return ! html ?
185                         null :
186                         _isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
187                                 true :
188                                 null;
189         };
190         
191         
192         var _pluck = function ( a, prop, prop2 ) {
193                 var out = [];
194                 var i=0, ien=a.length;
195         
196                 // Could have the test in the loop for slightly smaller code, but speed
197                 // is essential here
198                 if ( prop2 !== undefined ) {
199                         for ( ; i<ien ; i++ ) {
200                                 if ( a[i] && a[i][ prop ] ) {
201                                         out.push( a[i][ prop ][ prop2 ] );
202                                 }
203                         }
204                 }
205                 else {
206                         for ( ; i<ien ; i++ ) {
207                                 if ( a[i] ) {
208                                         out.push( a[i][ prop ] );
209                                 }
210                         }
211                 }
212         
213                 return out;
214         };
215         
216         
217         // Basically the same as _pluck, but rather than looping over `a` we use `order`
218         // as the indexes to pick from `a`
219         var _pluck_order = function ( a, order, prop, prop2 )
220         {
221                 var out = [];
222                 var i=0, ien=order.length;
223         
224                 // Could have the test in the loop for slightly smaller code, but speed
225                 // is essential here
226                 if ( prop2 !== undefined ) {
227                         for ( ; i<ien ; i++ ) {
228                                 if ( a[ order[i] ][ prop ] ) {
229                                         out.push( a[ order[i] ][ prop ][ prop2 ] );
230                                 }
231                         }
232                 }
233                 else {
234                         for ( ; i<ien ; i++ ) {
235                                 out.push( a[ order[i] ][ prop ] );
236                         }
237                 }
238         
239                 return out;
240         };
241         
242         
243         var _range = function ( len, start )
244         {
245                 var out = [];
246                 var end;
247         
248                 if ( start === undefined ) {
249                         start = 0;
250                         end = len;
251                 }
252                 else {
253                         end = start;
254                         start = len;
255                 }
256         
257                 for ( var i=start ; i<end ; i++ ) {
258                         out.push( i );
259                 }
260         
261                 return out;
262         };
263         
264         
265         var _removeEmpty = function ( a )
266         {
267                 var out = [];
268         
269                 for ( var i=0, ien=a.length ; i<ien ; i++ ) {
270                         if ( a[i] ) { // careful - will remove all falsy values!
271                                 out.push( a[i] );
272                         }
273                 }
274         
275                 return out;
276         };
277         
278         
279         var _stripHtml = function ( d ) {
280                 return d.replace( _re_html, '' );
281         };
282         
283         
284         /**
285          * Find the unique elements in a source array.
286          *
287          * @param  {array} src Source array
288          * @return {array} Array of unique items
289          * @ignore
290          */
291         var _unique = function ( src )
292         {
293                 // A faster unique method is to use object keys to identify used values,
294                 // but this doesn't work with arrays or objects, which we must also
295                 // consider. See jsperf.com/compare-array-unique-versions/4 for more
296                 // information.
297                 var
298                         out = [],
299                         val,
300                         i, ien=src.length,
301                         j, k=0;
302         
303                 again: for ( i=0 ; i<ien ; i++ ) {
304                         val = src[i];
305         
306                         for ( j=0 ; j<k ; j++ ) {
307                                 if ( out[j] === val ) {
308                                         continue again;
309                                 }
310                         }
311         
312                         out.push( val );
313                         k++;
314                 }
315         
316                 return out;
317         };
318         
319         
320         
321         /**
322          * Create a mapping object that allows camel case parameters to be looked up
323          * for their Hungarian counterparts. The mapping is stored in a private
324          * parameter called `_hungarianMap` which can be accessed on the source object.
325          *  @param {object} o
326          *  @memberof DataTable#oApi
327          */
328         function _fnHungarianMap ( o )
329         {
330                 var
331                         hungarian = 'a aa ai ao as b fn i m o s ',
332                         match,
333                         newKey,
334                         map = {};
335         
336                 $.each( o, function (key, val) {
337                         match = key.match(/^([^A-Z]+?)([A-Z])/);
338         
339                         if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
340                         {
341                                 newKey = key.replace( match[0], match[2].toLowerCase() );
342                                 map[ newKey ] = key;
343         
344                                 if ( match[1] === 'o' )
345                                 {
346                                         _fnHungarianMap( o[key] );
347                                 }
348                         }
349                 } );
350         
351                 o._hungarianMap = map;
352         }
353         
354         
355         /**
356          * Convert from camel case parameters to Hungarian, based on a Hungarian map
357          * created by _fnHungarianMap.
358          *  @param {object} src The model object which holds all parameters that can be
359          *    mapped.
360          *  @param {object} user The object to convert from camel case to Hungarian.
361          *  @param {boolean} force When set to `true`, properties which already have a
362          *    Hungarian value in the `user` object will be overwritten. Otherwise they
363          *    won't be.
364          *  @memberof DataTable#oApi
365          */
366         function _fnCamelToHungarian ( src, user, force )
367         {
368                 if ( ! src._hungarianMap ) {
369                         _fnHungarianMap( src );
370                 }
371         
372                 var hungarianKey;
373         
374                 $.each( user, function (key, val) {
375                         hungarianKey = src._hungarianMap[ key ];
376         
377                         if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
378                         {
379                                 // For objects, we need to buzz down into the object to copy parameters
380                                 if ( hungarianKey.charAt(0) === 'o' )
381                                 {
382                                         // Copy the camelCase options over to the hungarian
383                                         if ( ! user[ hungarianKey ] ) {
384                                                 user[ hungarianKey ] = {};
385                                         }
386                                         $.extend( true, user[hungarianKey], user[key] );
387         
388                                         _fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
389                                 }
390                                 else {
391                                         user[hungarianKey] = user[ key ];
392                                 }
393                         }
394                 } );
395         }
396         
397         
398         /**
399          * Language compatibility - when certain options are given, and others aren't, we
400          * need to duplicate the values over, in order to provide backwards compatibility
401          * with older language files.
402          *  @param {object} oSettings dataTables settings object
403          *  @memberof DataTable#oApi
404          */
405         function _fnLanguageCompat( lang )
406         {
407                 var defaults = DataTable.defaults.oLanguage;
408                 var zeroRecords = lang.sZeroRecords;
409         
410                 /* Backwards compatibility - if there is no sEmptyTable given, then use the same as
411                  * sZeroRecords - assuming that is given.
412                  */
413                 if ( ! lang.sEmptyTable && zeroRecords &&
414                         defaults.sEmptyTable === "No data available in table" )
415                 {
416                         _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
417                 }
418         
419                 /* Likewise with loading records */
420                 if ( ! lang.sLoadingRecords && zeroRecords &&
421                         defaults.sLoadingRecords === "Loading..." )
422                 {
423                         _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
424                 }
425         
426                 // Old parameter name of the thousands separator mapped onto the new
427                 if ( lang.sInfoThousands ) {
428                         lang.sThousands = lang.sInfoThousands;
429                 }
430         
431                 var decimal = lang.sDecimal;
432                 if ( decimal ) {
433                         _addNumericSort( decimal );
434                 }
435         }
436         
437         
438         /**
439          * Map one parameter onto another
440          *  @param {object} o Object to map
441          *  @param {*} knew The new parameter name
442          *  @param {*} old The old parameter name
443          */
444         var _fnCompatMap = function ( o, knew, old ) {
445                 if ( o[ knew ] !== undefined ) {
446                         o[ old ] = o[ knew ];
447                 }
448         };
449         
450         
451         /**
452          * Provide backwards compatibility for the main DT options. Note that the new
453          * options are mapped onto the old parameters, so this is an external interface
454          * change only.
455          *  @param {object} init Object to map
456          */
457         function _fnCompatOpts ( init )
458         {
459                 _fnCompatMap( init, 'ordering',      'bSort' );
460                 _fnCompatMap( init, 'orderMulti',    'bSortMulti' );
461                 _fnCompatMap( init, 'orderClasses',  'bSortClasses' );
462                 _fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
463                 _fnCompatMap( init, 'order',         'aaSorting' );
464                 _fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
465                 _fnCompatMap( init, 'paging',        'bPaginate' );
466                 _fnCompatMap( init, 'pagingType',    'sPaginationType' );
467                 _fnCompatMap( init, 'pageLength',    'iDisplayLength' );
468                 _fnCompatMap( init, 'searching',     'bFilter' );
469         
470                 // Column search objects are in an array, so it needs to be converted
471                 // element by element
472                 var searchCols = init.aoSearchCols;
473         
474                 if ( searchCols ) {
475                         for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
476                                 if ( searchCols[i] ) {
477                                         _fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
478                                 }
479                         }
480                 }
481         }
482         
483         
484         /**
485          * Provide backwards compatibility for column options. Note that the new options
486          * are mapped onto the old parameters, so this is an external interface change
487          * only.
488          *  @param {object} init Object to map
489          */
490         function _fnCompatCols ( init )
491         {
492                 _fnCompatMap( init, 'orderable',     'bSortable' );
493                 _fnCompatMap( init, 'orderData',     'aDataSort' );
494                 _fnCompatMap( init, 'orderSequence', 'asSorting' );
495                 _fnCompatMap( init, 'orderDataType', 'sortDataType' );
496         
497                 // orderData can be given as an integer
498                 var dataSort = init.aDataSort;
499                 if ( dataSort && ! $.isArray( dataSort ) ) {
500                         init.aDataSort = [ dataSort ];
501                 }
502         }
503         
504         
505         /**
506          * Browser feature detection for capabilities, quirks
507          *  @param {object} settings dataTables settings object
508          *  @memberof DataTable#oApi
509          */
510         function _fnBrowserDetect( settings )
511         {
512                 var browser = settings.oBrowser;
513         
514                 // Scrolling feature / quirks detection
515                 var n = $('<div/>')
516                         .css( {
517                                 position: 'absolute',
518                                 top: 0,
519                                 left: 0,
520                                 height: 1,
521                                 width: 1,
522                                 overflow: 'hidden'
523                         } )
524                         .append(
525                                 $('<div/>')
526                                         .css( {
527                                                 position: 'absolute',
528                                                 top: 1,
529                                                 left: 1,
530                                                 width: 100,
531                                                 overflow: 'scroll'
532                                         } )
533                                         .append(
534                                                 $('<div class="test"/>')
535                                                         .css( {
536                                                                 width: '100%',
537                                                                 height: 10
538                                                         } )
539                                         )
540                         )
541                         .appendTo( 'body' );
542         
543                 var test = n.find('.test');
544         
545                 // IE6/7 will oversize a width 100% element inside a scrolling element, to
546                 // include the width of the scrollbar, while other browsers ensure the inner
547                 // element is contained without forcing scrolling
548                 browser.bScrollOversize = test[0].offsetWidth === 100;
549         
550                 // In rtl text layout, some browsers (most, but not all) will place the
551                 // scrollbar on the left, rather than the right.
552                 browser.bScrollbarLeft = Math.round( test.offset().left ) !== 1;
553         
554                 n.remove();
555         }
556         
557         
558         /**
559          * Array.prototype reduce[Right] method, used for browsers which don't support
560          * JS 1.6. Done this way to reduce code size, since we iterate either way
561          *  @param {object} settings dataTables settings object
562          *  @memberof DataTable#oApi
563          */
564         function _fnReduce ( that, fn, init, start, end, inc )
565         {
566                 var
567                         i = start,
568                         value,
569                         isSet = false;
570         
571                 if ( init !== undefined ) {
572                         value = init;
573                         isSet = true;
574                 }
575         
576                 while ( i !== end ) {
577                         if ( ! that.hasOwnProperty(i) ) {
578                                 continue;
579                         }
580         
581                         value = isSet ?
582                                 fn( value, that[i], i, that ) :
583                                 that[i];
584         
585                         isSet = true;
586                         i += inc;
587                 }
588         
589                 return value;
590         }
591         
592         /**
593          * Add a column to the list used for the table with default values
594          *  @param {object} oSettings dataTables settings object
595          *  @param {node} nTh The th element for this column
596          *  @memberof DataTable#oApi
597          */
598         function _fnAddColumn( oSettings, nTh )
599         {
600                 // Add column to aoColumns array
601                 var oDefaults = DataTable.defaults.column;
602                 var iCol = oSettings.aoColumns.length;
603                 var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
604                         "nTh": nTh ? nTh : document.createElement('th'),
605                         "sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
606                         "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
607                         "mData": oDefaults.mData ? oDefaults.mData : iCol,
608                         idx: iCol
609                 } );
610                 oSettings.aoColumns.push( oCol );
611         
612                 // Add search object for column specific search. Note that the `searchCols[ iCol ]`
613                 // passed into extend can be undefined. This allows the user to give a default
614                 // with only some of the parameters defined, and also not give a default
615                 var searchCols = oSettings.aoPreSearchCols;
616                 searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
617         
618                 // Use the default column options function to initialise classes etc
619                 _fnColumnOptions( oSettings, iCol, $(nTh).data() );
620         }
621         
622         
623         /**
624          * Apply options for a column
625          *  @param {object} oSettings dataTables settings object
626          *  @param {int} iCol column index to consider
627          *  @param {object} oOptions object with sType, bVisible and bSearchable etc
628          *  @memberof DataTable#oApi
629          */
630         function _fnColumnOptions( oSettings, iCol, oOptions )
631         {
632                 var oCol = oSettings.aoColumns[ iCol ];
633                 var oClasses = oSettings.oClasses;
634                 var th = $(oCol.nTh);
635         
636                 // Try to get width information from the DOM. We can't get it from CSS
637                 // as we'd need to parse the CSS stylesheet. `width` option can override
638                 if ( ! oCol.sWidthOrig ) {
639                         // Width attribute
640                         oCol.sWidthOrig = th.attr('width') || null;
641         
642                         // Style attribute
643                         var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
644                         if ( t ) {
645                                 oCol.sWidthOrig = t[1];
646                         }
647                 }
648         
649                 /* User specified column options */
650                 if ( oOptions !== undefined && oOptions !== null )
651                 {
652                         // Backwards compatibility
653                         _fnCompatCols( oOptions );
654         
655                         // Map camel case parameters to their Hungarian counterparts
656                         _fnCamelToHungarian( DataTable.defaults.column, oOptions );
657         
658                         /* Backwards compatibility for mDataProp */
659                         if ( oOptions.mDataProp !== undefined && !oOptions.mData )
660                         {
661                                 oOptions.mData = oOptions.mDataProp;
662                         }
663         
664                         if ( oOptions.sType )
665                         {
666                                 oCol._sManualType = oOptions.sType;
667                         }
668         
669                         // `class` is a reserved word in Javascript, so we need to provide
670                         // the ability to use a valid name for the camel case input
671                         if ( oOptions.className && ! oOptions.sClass )
672                         {
673                                 oOptions.sClass = oOptions.className;
674                         }
675         
676                         $.extend( oCol, oOptions );
677                         _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
678         
679                         /* iDataSort to be applied (backwards compatibility), but aDataSort will take
680                          * priority if defined
681                          */
682                         if ( oOptions.iDataSort !== undefined )
683                         {
684                                 oCol.aDataSort = [ oOptions.iDataSort ];
685                         }
686                         _fnMap( oCol, oOptions, "aDataSort" );
687                 }
688         
689                 /* Cache the data get and set functions for speed */
690                 var mDataSrc = oCol.mData;
691                 var mData = _fnGetObjectDataFn( mDataSrc );
692                 var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
693         
694                 var attrTest = function( src ) {
695                         return typeof src === 'string' && src.indexOf('@') !== -1;
696                 };
697                 oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
698                         attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
699                 );
700         
701                 oCol.fnGetData = function (rowData, type, meta) {
702                         var innerData = mData( rowData, type, undefined, meta );
703         
704                         return mRender && type ?
705                                 mRender( innerData, type, rowData, meta ) :
706                                 innerData;
707                 };
708                 oCol.fnSetData = function ( rowData, val, meta ) {
709                         return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
710                 };
711         
712                 // Indicate if DataTables should read DOM data as an object or array
713                 // Used in _fnGetRowElements
714                 if ( typeof mDataSrc !== 'number' ) {
715                         oSettings._rowReadObject = true;
716                 }
717         
718                 /* Feature sorting overrides column specific when off */
719                 if ( !oSettings.oFeatures.bSort )
720                 {
721                         oCol.bSortable = false;
722                         th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
723                 }
724         
725                 /* Check that the class assignment is correct for sorting */
726                 var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
727                 var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
728                 if ( !oCol.bSortable || (!bAsc && !bDesc) )
729                 {
730                         oCol.sSortingClass = oClasses.sSortableNone;
731                         oCol.sSortingClassJUI = "";
732                 }
733                 else if ( bAsc && !bDesc )
734                 {
735                         oCol.sSortingClass = oClasses.sSortableAsc;
736                         oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
737                 }
738                 else if ( !bAsc && bDesc )
739                 {
740                         oCol.sSortingClass = oClasses.sSortableDesc;
741                         oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
742                 }
743                 else
744                 {
745                         oCol.sSortingClass = oClasses.sSortable;
746                         oCol.sSortingClassJUI = oClasses.sSortJUI;
747                 }
748         }
749         
750         
751         /**
752          * Adjust the table column widths for new data. Note: you would probably want to
753          * do a redraw after calling this function!
754          *  @param {object} settings dataTables settings object
755          *  @memberof DataTable#oApi
756          */
757         function _fnAdjustColumnSizing ( settings )
758         {
759                 /* Not interested in doing column width calculation if auto-width is disabled */
760                 if ( settings.oFeatures.bAutoWidth !== false )
761                 {
762                         var columns = settings.aoColumns;
763         
764                         _fnCalculateColumnWidths( settings );
765                         for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
766                         {
767                                 columns[i].nTh.style.width = columns[i].sWidth;
768                         }
769                 }
770         
771                 var scroll = settings.oScroll;
772                 if ( scroll.sY !== '' || scroll.sX !== '')
773                 {
774                         _fnScrollDraw( settings );
775                 }
776         
777                 _fnCallbackFire( settings, null, 'column-sizing', [settings] );
778         }
779         
780         
781         /**
782          * Covert the index of a visible column to the index in the data array (take account
783          * of hidden columns)
784          *  @param {object} oSettings dataTables settings object
785          *  @param {int} iMatch Visible column index to lookup
786          *  @returns {int} i the data index
787          *  @memberof DataTable#oApi
788          */
789         function _fnVisibleToColumnIndex( oSettings, iMatch )
790         {
791                 var aiVis = _fnGetColumns( oSettings, 'bVisible' );
792         
793                 return typeof aiVis[iMatch] === 'number' ?
794                         aiVis[iMatch] :
795                         null;
796         }
797         
798         
799         /**
800          * Covert the index of an index in the data array and convert it to the visible
801          *   column index (take account of hidden columns)
802          *  @param {int} iMatch Column index to lookup
803          *  @param {object} oSettings dataTables settings object
804          *  @returns {int} i the data index
805          *  @memberof DataTable#oApi
806          */
807         function _fnColumnIndexToVisible( oSettings, iMatch )
808         {
809                 var aiVis = _fnGetColumns( oSettings, 'bVisible' );
810                 var iPos = $.inArray( iMatch, aiVis );
811         
812                 return iPos !== -1 ? iPos : null;
813         }
814         
815         
816         /**
817          * Get the number of visible columns
818          *  @param {object} oSettings dataTables settings object
819          *  @returns {int} i the number of visible columns
820          *  @memberof DataTable#oApi
821          */
822         function _fnVisbleColumns( oSettings )
823         {
824                 return _fnGetColumns( oSettings, 'bVisible' ).length;
825         }
826         
827         
828         /**
829          * Get an array of column indexes that match a given property
830          *  @param {object} oSettings dataTables settings object
831          *  @param {string} sParam Parameter in aoColumns to look for - typically
832          *    bVisible or bSearchable
833          *  @returns {array} Array of indexes with matched properties
834          *  @memberof DataTable#oApi
835          */
836         function _fnGetColumns( oSettings, sParam )
837         {
838                 var a = [];
839         
840                 $.map( oSettings.aoColumns, function(val, i) {
841                         if ( val[sParam] ) {
842                                 a.push( i );
843                         }
844                 } );
845         
846                 return a;
847         }
848         
849         
850         /**
851          * Calculate the 'type' of a column
852          *  @param {object} settings dataTables settings object
853          *  @memberof DataTable#oApi
854          */
855         function _fnColumnTypes ( settings )
856         {
857                 var columns = settings.aoColumns;
858                 var data = settings.aoData;
859                 var types = DataTable.ext.type.detect;
860                 var i, ien, j, jen, k, ken;
861                 var col, cell, detectedType, cache;
862         
863                 // For each column, spin over the 
864                 for ( i=0, ien=columns.length ; i<ien ; i++ ) {
865                         col = columns[i];
866                         cache = [];
867         
868                         if ( ! col.sType && col._sManualType ) {
869                                 col.sType = col._sManualType;
870                         }
871                         else if ( ! col.sType ) {
872                                 for ( j=0, jen=types.length ; j<jen ; j++ ) {
873                                         for ( k=0, ken=data.length ; k<ken ; k++ ) {
874                                                 // Use a cache array so we only need to get the type data
875                                                 // from the formatter once (when using multiple detectors)
876                                                 if ( cache[k] === undefined ) {
877                                                         cache[k] = _fnGetCellData( settings, k, i, 'type' );
878                                                 }
879         
880                                                 detectedType = types[j]( cache[k], settings );
881         
882                                                 // If null, then this type can't apply to this column, so
883                                                 // rather than testing all cells, break out. There is an
884                                                 // exception for the last type which is `html`. We need to
885                                                 // scan all rows since it is possible to mix string and HTML
886                                                 // types
887                                                 if ( ! detectedType && j !== types.length-1 ) {
888                                                         break;
889                                                 }
890         
891                                                 // Only a single match is needed for html type since it is
892                                                 // bottom of the pile and very similar to string
893                                                 if ( detectedType === 'html' ) {
894                                                         break;
895                                                 }
896                                         }
897         
898                                         // Type is valid for all data points in the column - use this
899                                         // type
900                                         if ( detectedType ) {
901                                                 col.sType = detectedType;
902                                                 break;
903                                         }
904                                 }
905         
906                                 // Fall back - if no type was detected, always use string
907                                 if ( ! col.sType ) {
908                                         col.sType = 'string';
909                                 }
910                         }
911                 }
912         }
913         
914         
915         /**
916          * Take the column definitions and static columns arrays and calculate how
917          * they relate to column indexes. The callback function will then apply the
918          * definition found for a column to a suitable configuration object.
919          *  @param {object} oSettings dataTables settings object
920          *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
921          *  @param {array} aoCols The aoColumns array that defines columns individually
922          *  @param {function} fn Callback function - takes two parameters, the calculated
923          *    column index and the definition for that column.
924          *  @memberof DataTable#oApi
925          */
926         function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
927         {
928                 var i, iLen, j, jLen, k, kLen, def;
929                 var columns = oSettings.aoColumns;
930         
931                 // Column definitions with aTargets
932                 if ( aoColDefs )
933                 {
934                         /* Loop over the definitions array - loop in reverse so first instance has priority */
935                         for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
936                         {
937                                 def = aoColDefs[i];
938         
939                                 /* Each definition can target multiple columns, as it is an array */
940                                 var aTargets = def.targets !== undefined ?
941                                         def.targets :
942                                         def.aTargets;
943         
944                                 if ( ! $.isArray( aTargets ) )
945                                 {
946                                         aTargets = [ aTargets ];
947                                 }
948         
949                                 for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
950                                 {
951                                         if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
952                                         {
953                                                 /* Add columns that we don't yet know about */
954                                                 while( columns.length <= aTargets[j] )
955                                                 {
956                                                         _fnAddColumn( oSettings );
957                                                 }
958         
959                                                 /* Integer, basic index */
960                                                 fn( aTargets[j], def );
961                                         }
962                                         else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
963                                         {
964                                                 /* Negative integer, right to left column counting */
965                                                 fn( columns.length+aTargets[j], def );
966                                         }
967                                         else if ( typeof aTargets[j] === 'string' )
968                                         {
969                                                 /* Class name matching on TH element */
970                                                 for ( k=0, kLen=columns.length ; k<kLen ; k++ )
971                                                 {
972                                                         if ( aTargets[j] == "_all" ||
973                                                              $(columns[k].nTh).hasClass( aTargets[j] ) )
974                                                         {
975                                                                 fn( k, def );
976                                                         }
977                                                 }
978                                         }
979                                 }
980                         }
981                 }
982         
983                 // Statically defined columns array
984                 if ( aoCols )
985                 {
986                         for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
987                         {
988                                 fn( i, aoCols[i] );
989                         }
990                 }
991         }
992         
993         /**
994          * Add a data array to the table, creating DOM node etc. This is the parallel to
995          * _fnGatherData, but for adding rows from a Javascript source, rather than a
996          * DOM source.
997          *  @param {object} oSettings dataTables settings object
998          *  @param {array} aData data array to be added
999          *  @param {node} [nTr] TR element to add to the table - optional. If not given,
1000          *    DataTables will create a row automatically
1001          *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
1002          *    if nTr is.
1003          *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
1004          *  @memberof DataTable#oApi
1005          */
1006         function _fnAddData ( oSettings, aDataIn, nTr, anTds )
1007         {
1008                 /* Create the object for storing information about this new row */
1009                 var iRow = oSettings.aoData.length;
1010                 var oData = $.extend( true, {}, DataTable.models.oRow, {
1011                         src: nTr ? 'dom' : 'data'
1012                 } );
1013         
1014                 oData._aData = aDataIn;
1015                 oSettings.aoData.push( oData );
1016         
1017                 /* Create the cells */
1018                 var nTd, sThisType;
1019                 var columns = oSettings.aoColumns;
1020                 for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
1021                 {
1022                         // When working with a row, the data source object must be populated. In
1023                         // all other cases, the data source object is already populated, so we
1024                         // don't overwrite it, which might break bindings etc
1025                         if ( nTr ) {
1026                                 _fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) );
1027                         }
1028                         columns[i].sType = null;
1029                 }
1030         
1031                 /* Add to the display array */
1032                 oSettings.aiDisplayMaster.push( iRow );
1033         
1034                 /* Create the DOM information, or register it if already present */
1035                 if ( nTr || ! oSettings.oFeatures.bDeferRender )
1036                 {
1037                         _fnCreateTr( oSettings, iRow, nTr, anTds );
1038                 }
1039         
1040                 return iRow;
1041         }
1042         
1043         
1044         /**
1045          * Add one or more TR elements to the table. Generally we'd expect to
1046          * use this for reading data from a DOM sourced table, but it could be
1047          * used for an TR element. Note that if a TR is given, it is used (i.e.
1048          * it is not cloned).
1049          *  @param {object} settings dataTables settings object
1050          *  @param {array|node|jQuery} trs The TR element(s) to add to the table
1051          *  @returns {array} Array of indexes for the added rows
1052          *  @memberof DataTable#oApi
1053          */
1054         function _fnAddTr( settings, trs )
1055         {
1056                 var row;
1057         
1058                 // Allow an individual node to be passed in
1059                 if ( ! (trs instanceof $) ) {
1060                         trs = $(trs);
1061                 }
1062         
1063                 return trs.map( function (i, el) {
1064                         row = _fnGetRowElements( settings, el );
1065                         return _fnAddData( settings, row.data, el, row.cells );
1066                 } );
1067         }
1068         
1069         
1070         /**
1071          * Take a TR element and convert it to an index in aoData
1072          *  @param {object} oSettings dataTables settings object
1073          *  @param {node} n the TR element to find
1074          *  @returns {int} index if the node is found, null if not
1075          *  @memberof DataTable#oApi
1076          */
1077         function _fnNodeToDataIndex( oSettings, n )
1078         {
1079                 return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
1080         }
1081         
1082         
1083         /**
1084          * Take a TD element and convert it into a column data index (not the visible index)
1085          *  @param {object} oSettings dataTables settings object
1086          *  @param {int} iRow The row number the TD/TH can be found in
1087          *  @param {node} n The TD/TH element to find
1088          *  @returns {int} index if the node is found, -1 if not
1089          *  @memberof DataTable#oApi
1090          */
1091         function _fnNodeToColumnIndex( oSettings, iRow, n )
1092         {
1093                 return $.inArray( n, oSettings.aoData[ iRow ].anCells );
1094         }
1095         
1096         
1097         /**
1098          * Get the data for a given cell from the internal cache, taking into account data mapping
1099          *  @param {object} settings dataTables settings object
1100          *  @param {int} rowIdx aoData row id
1101          *  @param {int} colIdx Column index
1102          *  @param {string} type data get type ('display', 'type' 'filter' 'sort')
1103          *  @returns {*} Cell data
1104          *  @memberof DataTable#oApi
1105          */
1106         function _fnGetCellData( settings, rowIdx, colIdx, type )
1107         {
1108                 var draw           = settings.iDraw;
1109                 var col            = settings.aoColumns[colIdx];
1110                 var rowData        = settings.aoData[rowIdx]._aData;
1111                 var defaultContent = col.sDefaultContent;
1112                 var cellData       = col.fnGetData( rowData, type, {
1113                         settings: settings,
1114                         row:      rowIdx,
1115                         col:      colIdx
1116                 } );
1117         
1118                 if ( cellData === undefined ) {
1119                         if ( settings.iDrawError != draw && defaultContent === null ) {
1120                                 _fnLog( settings, 0, "Requested unknown parameter "+
1121                                         (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
1122                                         " for row "+rowIdx, 4 );
1123                                 settings.iDrawError = draw;
1124                         }
1125                         return defaultContent;
1126                 }
1127         
1128                 /* When the data source is null, we can use default column data */
1129                 if ( (cellData === rowData || cellData === null) && defaultContent !== null ) {
1130                         cellData = defaultContent;
1131                 }
1132                 else if ( typeof cellData === 'function' ) {
1133                         // If the data source is a function, then we run it and use the return,
1134                         // executing in the scope of the data object (for instances)
1135                         return cellData.call( rowData );
1136                 }
1137         
1138                 if ( cellData === null && type == 'display' ) {
1139                         return '';
1140                 }
1141                 return cellData;
1142         }
1143         
1144         
1145         /**
1146          * Set the value for a specific cell, into the internal data cache
1147          *  @param {object} settings dataTables settings object
1148          *  @param {int} rowIdx aoData row id
1149          *  @param {int} colIdx Column index
1150          *  @param {*} val Value to set
1151          *  @memberof DataTable#oApi
1152          */
1153         function _fnSetCellData( settings, rowIdx, colIdx, val )
1154         {
1155                 var col     = settings.aoColumns[colIdx];
1156                 var rowData = settings.aoData[rowIdx]._aData;
1157         
1158                 col.fnSetData( rowData, val, {
1159                         settings: settings,
1160                         row:      rowIdx,
1161                         col:      colIdx
1162                 }  );
1163         }
1164         
1165         
1166         // Private variable that is used to match action syntax in the data property object
1167         var __reArray = /\[.*?\]$/;
1168         var __reFn = /\(\)$/;
1169         
1170         /**
1171          * Split string on periods, taking into account escaped periods
1172          * @param  {string} str String to split
1173          * @return {array} Split string
1174          */
1175         function _fnSplitObjNotation( str )
1176         {
1177                 return $.map( str.match(/(\\.|[^\.])+/g), function ( s ) {
1178                         return s.replace(/\\./g, '.');
1179                 } );
1180         }
1181         
1182         
1183         /**
1184          * Return a function that can be used to get data from a source object, taking
1185          * into account the ability to use nested objects as a source
1186          *  @param {string|int|function} mSource The data source for the object
1187          *  @returns {function} Data get function
1188          *  @memberof DataTable#oApi
1189          */
1190         function _fnGetObjectDataFn( mSource )
1191         {
1192                 if ( $.isPlainObject( mSource ) )
1193                 {
1194                         /* Build an object of get functions, and wrap them in a single call */
1195                         var o = {};
1196                         $.each( mSource, function (key, val) {
1197                                 if ( val ) {
1198                                         o[key] = _fnGetObjectDataFn( val );
1199                                 }
1200                         } );
1201         
1202                         return function (data, type, row, meta) {
1203                                 var t = o[type] || o._;
1204                                 return t !== undefined ?
1205                                         t(data, type, row, meta) :
1206                                         data;
1207                         };
1208                 }
1209                 else if ( mSource === null )
1210                 {
1211                         /* Give an empty string for rendering / sorting etc */
1212                         return function (data) { // type, row and meta also passed, but not used
1213                                 return data;
1214                         };
1215                 }
1216                 else if ( typeof mSource === 'function' )
1217                 {
1218                         return function (data, type, row, meta) {
1219                                 return mSource( data, type, row, meta );
1220                         };
1221                 }
1222                 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
1223                               mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
1224                 {
1225                         /* If there is a . in the source string then the data source is in a
1226                          * nested object so we loop over the data for each level to get the next
1227                          * level down. On each loop we test for undefined, and if found immediately
1228                          * return. This allows entire objects to be missing and sDefaultContent to
1229                          * be used if defined, rather than throwing an error
1230                          */
1231                         var fetchData = function (data, type, src) {
1232                                 var arrayNotation, funcNotation, out, innerSrc;
1233         
1234                                 if ( src !== "" )
1235                                 {
1236                                         var a = _fnSplitObjNotation( src );
1237         
1238                                         for ( var i=0, iLen=a.length ; i<iLen ; i++ )
1239                                         {
1240                                                 // Check if we are dealing with special notation
1241                                                 arrayNotation = a[i].match(__reArray);
1242                                                 funcNotation = a[i].match(__reFn);
1243         
1244                                                 if ( arrayNotation )
1245                                                 {
1246                                                         // Array notation
1247                                                         a[i] = a[i].replace(__reArray, '');
1248         
1249                                                         // Condition allows simply [] to be passed in
1250                                                         if ( a[i] !== "" ) {
1251                                                                 data = data[ a[i] ];
1252                                                         }
1253                                                         out = [];
1254         
1255                                                         // Get the remainder of the nested object to get
1256                                                         a.splice( 0, i+1 );
1257                                                         innerSrc = a.join('.');
1258         
1259                                                         // Traverse each entry in the array getting the properties requested
1260                                                         for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
1261                                                                 out.push( fetchData( data[j], type, innerSrc ) );
1262                                                         }
1263         
1264                                                         // If a string is given in between the array notation indicators, that
1265                                                         // is used to join the strings together, otherwise an array is returned
1266                                                         var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
1267                                                         data = (join==="") ? out : out.join(join);
1268         
1269                                                         // The inner call to fetchData has already traversed through the remainder
1270                                                         // of the source requested, so we exit from the loop
1271                                                         break;
1272                                                 }
1273                                                 else if ( funcNotation )
1274                                                 {
1275                                                         // Function call
1276                                                         a[i] = a[i].replace(__reFn, '');
1277                                                         data = data[ a[i] ]();
1278                                                         continue;
1279                                                 }
1280         
1281                                                 if ( data === null || data[ a[i] ] === undefined )
1282                                                 {
1283                                                         return undefined;
1284                                                 }
1285                                                 data = data[ a[i] ];
1286                                         }
1287                                 }
1288         
1289                                 return data;
1290                         };
1291         
1292                         return function (data, type) { // row and meta also passed, but not used
1293                                 return fetchData( data, type, mSource );
1294                         };
1295                 }
1296                 else
1297                 {
1298                         /* Array or flat object mapping */
1299                         return function (data, type) { // row and meta also passed, but not used
1300                                 return data[mSource];
1301                         };
1302                 }
1303         }
1304         
1305         
1306         /**
1307          * Return a function that can be used to set data from a source object, taking
1308          * into account the ability to use nested objects as a source
1309          *  @param {string|int|function} mSource The data source for the object
1310          *  @returns {function} Data set function
1311          *  @memberof DataTable#oApi
1312          */
1313         function _fnSetObjectDataFn( mSource )
1314         {
1315                 if ( $.isPlainObject( mSource ) )
1316                 {
1317                         /* Unlike get, only the underscore (global) option is used for for
1318                          * setting data since we don't know the type here. This is why an object
1319                          * option is not documented for `mData` (which is read/write), but it is
1320                          * for `mRender` which is read only.
1321                          */
1322                         return _fnSetObjectDataFn( mSource._ );
1323                 }
1324                 else if ( mSource === null )
1325                 {
1326                         /* Nothing to do when the data source is null */
1327                         return function () {};
1328                 }
1329                 else if ( typeof mSource === 'function' )
1330                 {
1331                         return function (data, val, meta) {
1332                                 mSource( data, 'set', val, meta );
1333                         };
1334                 }
1335                 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
1336                               mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
1337                 {
1338                         /* Like the get, we need to get data from a nested object */
1339                         var setData = function (data, val, src) {
1340                                 var a = _fnSplitObjNotation( src ), b;
1341                                 var aLast = a[a.length-1];
1342                                 var arrayNotation, funcNotation, o, innerSrc;
1343         
1344                                 for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
1345                                 {
1346                                         // Check if we are dealing with an array notation request
1347                                         arrayNotation = a[i].match(__reArray);
1348                                         funcNotation = a[i].match(__reFn);
1349         
1350                                         if ( arrayNotation )
1351                                         {
1352                                                 a[i] = a[i].replace(__reArray, '');
1353                                                 data[ a[i] ] = [];
1354         
1355                                                 // Get the remainder of the nested object to set so we can recurse
1356                                                 b = a.slice();
1357                                                 b.splice( 0, i+1 );
1358                                                 innerSrc = b.join('.');
1359         
1360                                                 // Traverse each entry in the array setting the properties requested
1361                                                 for ( var j=0, jLen=val.length ; j<jLen ; j++ )
1362                                                 {
1363                                                         o = {};
1364                                                         setData( o, val[j], innerSrc );
1365                                                         data[ a[i] ].push( o );
1366                                                 }
1367         
1368                                                 // The inner call to setData has already traversed through the remainder
1369                                                 // of the source and has set the data, thus we can exit here
1370                                                 return;
1371                                         }
1372                                         else if ( funcNotation )
1373                                         {
1374                                                 // Function call
1375                                                 a[i] = a[i].replace(__reFn, '');
1376                                                 data = data[ a[i] ]( val );
1377                                         }
1378         
1379                                         // If the nested object doesn't currently exist - since we are
1380                                         // trying to set the value - create it
1381                                         if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
1382                                         {
1383                                                 data[ a[i] ] = {};
1384                                         }
1385                                         data = data[ a[i] ];
1386                                 }
1387         
1388                                 // Last item in the input - i.e, the actual set
1389                                 if ( aLast.match(__reFn ) )
1390                                 {
1391                                         // Function call
1392                                         data = data[ aLast.replace(__reFn, '') ]( val );
1393                                 }
1394                                 else
1395                                 {
1396                                         // If array notation is used, we just want to strip it and use the property name
1397                                         // and assign the value. If it isn't used, then we get the result we want anyway
1398                                         data[ aLast.replace(__reArray, '') ] = val;
1399                                 }
1400                         };
1401         
1402                         return function (data, val) { // meta is also passed in, but not used
1403                                 return setData( data, val, mSource );
1404                         };
1405                 }
1406                 else
1407                 {
1408                         /* Array or flat object mapping */
1409                         return function (data, val) { // meta is also passed in, but not used
1410                                 data[mSource] = val;
1411                         };
1412                 }
1413         }
1414         
1415         
1416         /**
1417          * Return an array with the full table data
1418          *  @param {object} oSettings dataTables settings object
1419          *  @returns array {array} aData Master data array
1420          *  @memberof DataTable#oApi
1421          */
1422         function _fnGetDataMaster ( settings )
1423         {
1424                 return _pluck( settings.aoData, '_aData' );
1425         }
1426         
1427         
1428         /**
1429          * Nuke the table
1430          *  @param {object} oSettings dataTables settings object
1431          *  @memberof DataTable#oApi
1432          */
1433         function _fnClearTable( settings )
1434         {
1435                 settings.aoData.length = 0;
1436                 settings.aiDisplayMaster.length = 0;
1437                 settings.aiDisplay.length = 0;
1438         }
1439         
1440         
1441          /**
1442          * Take an array of integers (index array) and remove a target integer (value - not
1443          * the key!)
1444          *  @param {array} a Index array to target
1445          *  @param {int} iTarget value to find
1446          *  @memberof DataTable#oApi
1447          */
1448         function _fnDeleteIndex( a, iTarget, splice )
1449         {
1450                 var iTargetIndex = -1;
1451         
1452                 for ( var i=0, iLen=a.length ; i<iLen ; i++ )
1453                 {
1454                         if ( a[i] == iTarget )
1455                         {
1456                                 iTargetIndex = i;
1457                         }
1458                         else if ( a[i] > iTarget )
1459                         {
1460                                 a[i]--;
1461                         }
1462                 }
1463         
1464                 if ( iTargetIndex != -1 && splice === undefined )
1465                 {
1466                         a.splice( iTargetIndex, 1 );
1467                 }
1468         }
1469         
1470         
1471         /**
1472          * Mark cached data as invalid such that a re-read of the data will occur when
1473          * the cached data is next requested. Also update from the data source object.
1474          *
1475          * @param {object} settings DataTables settings object
1476          * @param {int}    rowIdx   Row index to invalidate
1477          * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
1478          *     or 'data'
1479          * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
1480          *     row will be invalidated
1481          * @memberof DataTable#oApi
1482          *
1483          * @todo For the modularisation of v1.11 this will need to become a callback, so
1484          *   the sort and filter methods can subscribe to it. That will required
1485          *   initialisation options for sorting, which is why it is not already baked in
1486          */
1487         function _fnInvalidate( settings, rowIdx, src, colIdx )
1488         {
1489                 var row = settings.aoData[ rowIdx ];
1490                 var i, ien;
1491                 var cellWrite = function ( cell, col ) {
1492                         // This is very frustrating, but in IE if you just write directly
1493                         // to innerHTML, and elements that are overwritten are GC'ed,
1494                         // even if there is a reference to them elsewhere
1495                         while ( cell.childNodes.length ) {
1496                                 cell.removeChild( cell.firstChild );
1497                         }
1498         
1499                         cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
1500                 };
1501         
1502                 // Are we reading last data from DOM or the data object?
1503                 if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
1504                         // Read the data from the DOM
1505                         row._aData = _fnGetRowElements(
1506                                         settings, row, colIdx, colIdx === undefined ? undefined : row._aData
1507                                 )
1508                                 .data;
1509                 }
1510                 else {
1511                         // Reading from data object, update the DOM
1512                         var cells = row.anCells;
1513         
1514                         if ( cells ) {
1515                                 if ( colIdx !== undefined ) {
1516                                         cellWrite( cells[colIdx], colIdx );
1517                                 }
1518                                 else {
1519                                         for ( i=0, ien=cells.length ; i<ien ; i++ ) {
1520                                                 cellWrite( cells[i], i );
1521                                         }
1522                                 }
1523                         }
1524                 }
1525         
1526                 // For both row and cell invalidation, the cached data for sorting and
1527                 // filtering is nulled out
1528                 row._aSortData = null;
1529                 row._aFilterData = null;
1530         
1531                 // Invalidate the type for a specific column (if given) or all columns since
1532                 // the data might have changed
1533                 var cols = settings.aoColumns;
1534                 if ( colIdx !== undefined ) {
1535                         cols[ colIdx ].sType = null;
1536                 }
1537                 else {
1538                         for ( i=0, ien=cols.length ; i<ien ; i++ ) {
1539                                 cols[i].sType = null;
1540                         }
1541         
1542                         // Update DataTables special `DT_*` attributes for the row
1543                         _fnRowAttributes( row );
1544                 }
1545         }
1546         
1547         
1548         /**
1549          * Build a data source object from an HTML row, reading the contents of the
1550          * cells that are in the row.
1551          *
1552          * @param {object} settings DataTables settings object
1553          * @param {node|object} TR element from which to read data or existing row
1554          *   object from which to re-read the data from the cells
1555          * @param {int} [colIdx] Optional column index
1556          * @param {array|object} [d] Data source object. If `colIdx` is given then this
1557          *   parameter should also be given and will be used to write the data into.
1558          *   Only the column in question will be written
1559          * @returns {object} Object with two parameters: `data` the data read, in
1560          *   document order, and `cells` and array of nodes (they can be useful to the
1561          *   caller, so rather than needing a second traversal to get them, just return
1562          *   them from here).
1563          * @memberof DataTable#oApi
1564          */
1565         function _fnGetRowElements( settings, row, colIdx, d )
1566         {
1567                 var
1568                         tds = [],
1569                         td = row.firstChild,
1570                         name, col, o, i=0, contents,
1571                         columns = settings.aoColumns,
1572                         objectRead = settings._rowReadObject;
1573         
1574                 // Allow the data object to be passed in, or construct
1575                 d = d || objectRead ? {} : [];
1576         
1577                 var attr = function ( str, td  ) {
1578                         if ( typeof str === 'string' ) {
1579                                 var idx = str.indexOf('@');
1580         
1581                                 if ( idx !== -1 ) {
1582                                         var attr = str.substring( idx+1 );
1583                                         var setter = _fnSetObjectDataFn( str );
1584                                         setter( d, td.getAttribute( attr ) );
1585                                 }
1586                         }
1587                 };
1588         
1589                 // Read data from a cell and store into the data object
1590                 var cellProcess = function ( cell ) {
1591                         if ( colIdx === undefined || colIdx === i ) {
1592                                 col = columns[i];
1593                                 contents = $.trim(cell.innerHTML);
1594         
1595                                 if ( col && col._bAttrSrc ) {
1596                                         var setter = _fnSetObjectDataFn( col.mData._ );
1597                                         setter( d, contents );
1598         
1599                                         attr( col.mData.sort, cell );
1600                                         attr( col.mData.type, cell );
1601                                         attr( col.mData.filter, cell );
1602                                 }
1603                                 else {
1604                                         // Depending on the `data` option for the columns the data can
1605                                         // be read to either an object or an array.
1606                                         if ( objectRead ) {
1607                                                 if ( ! col._setter ) {
1608                                                         // Cache the setter function
1609                                                         col._setter = _fnSetObjectDataFn( col.mData );
1610                                                 }
1611                                                 col._setter( d, contents );
1612                                         }
1613                                         else {
1614                                                 d[i] = contents;
1615                                         }
1616                                 }
1617                         }
1618         
1619                         i++;
1620                 };
1621         
1622                 if ( td ) {
1623                         // `tr` element was passed in
1624                         while ( td ) {
1625                                 name = td.nodeName.toUpperCase();
1626         
1627                                 if ( name == "TD" || name == "TH" ) {
1628                                         cellProcess( td );
1629                                         tds.push( td );
1630                                 }
1631         
1632                                 td = td.nextSibling;
1633                         }
1634                 }
1635                 else {
1636                         // Existing row object passed in
1637                         tds = row.anCells;
1638                         
1639                         for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
1640                                 cellProcess( tds[j] );
1641                         }
1642                 }
1643         
1644                 return {
1645                         data: d,
1646                         cells: tds
1647                 };
1648         }
1649         /**
1650          * Create a new TR element (and it's TD children) for a row
1651          *  @param {object} oSettings dataTables settings object
1652          *  @param {int} iRow Row to consider
1653          *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
1654          *    DataTables will create a row automatically
1655          *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
1656          *    if nTr is.
1657          *  @memberof DataTable#oApi
1658          */
1659         function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
1660         {
1661                 var
1662                         row = oSettings.aoData[iRow],
1663                         rowData = row._aData,
1664                         cells = [],
1665                         nTr, nTd, oCol,
1666                         i, iLen;
1667         
1668                 if ( row.nTr === null )
1669                 {
1670                         nTr = nTrIn || document.createElement('tr');
1671         
1672                         row.nTr = nTr;
1673                         row.anCells = cells;
1674         
1675                         /* Use a private property on the node to allow reserve mapping from the node
1676                          * to the aoData array for fast look up
1677                          */
1678                         nTr._DT_RowIndex = iRow;
1679         
1680                         /* Special parameters can be given by the data source to be used on the row */
1681                         _fnRowAttributes( row );
1682         
1683                         /* Process each column */
1684                         for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
1685                         {
1686                                 oCol = oSettings.aoColumns[i];
1687         
1688                                 nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
1689                                 cells.push( nTd );
1690         
1691                                 // Need to create the HTML if new, or if a rendering function is defined
1692                                 if ( !nTrIn || oCol.mRender || oCol.mData !== i )
1693                                 {
1694                                         nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
1695                                 }
1696         
1697                                 /* Add user defined class */
1698                                 if ( oCol.sClass )
1699                                 {
1700                                         nTd.className += ' '+oCol.sClass;
1701                                 }
1702         
1703                                 // Visibility - add or remove as required
1704                                 if ( oCol.bVisible && ! nTrIn )
1705                                 {
1706                                         nTr.appendChild( nTd );
1707                                 }
1708                                 else if ( ! oCol.bVisible && nTrIn )
1709                                 {
1710                                         nTd.parentNode.removeChild( nTd );
1711                                 }
1712         
1713                                 if ( oCol.fnCreatedCell )
1714                                 {
1715                                         oCol.fnCreatedCell.call( oSettings.oInstance,
1716                                                 nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
1717                                         );
1718                                 }
1719                         }
1720         
1721                         _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
1722                 }
1723         
1724                 // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
1725                 // and deployed
1726                 row.nTr.setAttribute( 'role', 'row' );
1727         }
1728         
1729         
1730         /**
1731          * Add attributes to a row based on the special `DT_*` parameters in a data
1732          * source object.
1733          *  @param {object} DataTables row object for the row to be modified
1734          *  @memberof DataTable#oApi
1735          */
1736         function _fnRowAttributes( row )
1737         {
1738                 var tr = row.nTr;
1739                 var data = row._aData;
1740         
1741                 if ( tr ) {
1742                         if ( data.DT_RowId ) {
1743                                 tr.id = data.DT_RowId;
1744                         }
1745         
1746                         if ( data.DT_RowClass ) {
1747                                 // Remove any classes added by DT_RowClass before
1748                                 var a = data.DT_RowClass.split(' ');
1749                                 row.__rowc = row.__rowc ?
1750                                         _unique( row.__rowc.concat( a ) ) :
1751                                         a;
1752         
1753                                 $(tr)
1754                                         .removeClass( row.__rowc.join(' ') )
1755                                         .addClass( data.DT_RowClass );
1756                         }
1757         
1758                         if ( data.DT_RowAttr ) {
1759                                 $(tr).attr( data.DT_RowAttr );
1760                         }
1761         
1762                         if ( data.DT_RowData ) {
1763                                 $(tr).data( data.DT_RowData );
1764                         }
1765                 }
1766         }
1767         
1768         
1769         /**
1770          * Create the HTML header for the table
1771          *  @param {object} oSettings dataTables settings object
1772          *  @memberof DataTable#oApi
1773          */
1774         function _fnBuildHead( oSettings )
1775         {
1776                 var i, ien, cell, row, column;
1777                 var thead = oSettings.nTHead;
1778                 var tfoot = oSettings.nTFoot;
1779                 var createHeader = $('th, td', thead).length === 0;
1780                 var classes = oSettings.oClasses;
1781                 var columns = oSettings.aoColumns;
1782         
1783                 if ( createHeader ) {
1784                         row = $('<tr/>').appendTo( thead );
1785                 }
1786         
1787                 for ( i=0, ien=columns.length ; i<ien ; i++ ) {
1788                         column = columns[i];
1789                         cell = $( column.nTh ).addClass( column.sClass );
1790         
1791                         if ( createHeader ) {
1792                                 cell.appendTo( row );
1793                         }
1794         
1795                         // 1.11 move into sorting
1796                         if ( oSettings.oFeatures.bSort ) {
1797                                 cell.addClass( column.sSortingClass );
1798         
1799                                 if ( column.bSortable !== false ) {
1800                                         cell
1801                                                 .attr( 'tabindex', oSettings.iTabIndex )
1802                                                 .attr( 'aria-controls', oSettings.sTableId );
1803         
1804                                         _fnSortAttachListener( oSettings, column.nTh, i );
1805                                 }
1806                         }
1807         
1808                         if ( column.sTitle != cell.html() ) {
1809                                 cell.html( column.sTitle );
1810                         }
1811         
1812                         _fnRenderer( oSettings, 'header' )(
1813                                 oSettings, cell, column, classes
1814                         );
1815                 }
1816         
1817                 if ( createHeader ) {
1818                         _fnDetectHeader( oSettings.aoHeader, thead );
1819                 }
1820                 
1821                 /* ARIA role for the rows */
1822                 $(thead).find('>tr').attr('role', 'row');
1823         
1824                 /* Deal with the footer - add classes if required */
1825                 $(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
1826                 $(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
1827         
1828                 // Cache the footer cells. Note that we only take the cells from the first
1829                 // row in the footer. If there is more than one row the user wants to
1830                 // interact with, they need to use the table().foot() method. Note also this
1831                 // allows cells to be used for multiple columns using colspan
1832                 if ( tfoot !== null ) {
1833                         var cells = oSettings.aoFooter[0];
1834         
1835                         for ( i=0, ien=cells.length ; i<ien ; i++ ) {
1836                                 column = columns[i];
1837                                 column.nTf = cells[i].cell;
1838         
1839                                 if ( column.sClass ) {
1840                                         $(column.nTf).addClass( column.sClass );
1841                                 }
1842                         }
1843                 }
1844         }
1845         
1846         
1847         /**
1848          * Draw the header (or footer) element based on the column visibility states. The
1849          * methodology here is to use the layout array from _fnDetectHeader, modified for
1850          * the instantaneous column visibility, to construct the new layout. The grid is
1851          * traversed over cell at a time in a rows x columns grid fashion, although each
1852          * cell insert can cover multiple elements in the grid - which is tracks using the
1853          * aApplied array. Cell inserts in the grid will only occur where there isn't
1854          * already a cell in that position.
1855          *  @param {object} oSettings dataTables settings object
1856          *  @param array {objects} aoSource Layout array from _fnDetectHeader
1857          *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
1858          *  @memberof DataTable#oApi
1859          */
1860         function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
1861         {
1862                 var i, iLen, j, jLen, k, kLen, n, nLocalTr;
1863                 var aoLocal = [];
1864                 var aApplied = [];
1865                 var iColumns = oSettings.aoColumns.length;
1866                 var iRowspan, iColspan;
1867         
1868                 if ( ! aoSource )
1869                 {
1870                         return;
1871                 }
1872         
1873                 if (  bIncludeHidden === undefined )
1874                 {
1875                         bIncludeHidden = false;
1876                 }
1877         
1878                 /* Make a copy of the master layout array, but without the visible columns in it */
1879                 for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
1880                 {
1881                         aoLocal[i] = aoSource[i].slice();
1882                         aoLocal[i].nTr = aoSource[i].nTr;
1883         
1884                         /* Remove any columns which are currently hidden */
1885                         for ( j=iColumns-1 ; j>=0 ; j-- )
1886                         {
1887                                 if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
1888                                 {
1889                                         aoLocal[i].splice( j, 1 );
1890                                 }
1891                         }
1892         
1893                         /* Prep the applied array - it needs an element for each row */
1894                         aApplied.push( [] );
1895                 }
1896         
1897                 for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
1898                 {
1899                         nLocalTr = aoLocal[i].nTr;
1900         
1901                         /* All cells are going to be replaced, so empty out the row */
1902                         if ( nLocalTr )
1903                         {
1904                                 while( (n = nLocalTr.firstChild) )
1905                                 {
1906                                         nLocalTr.removeChild( n );
1907                                 }
1908                         }
1909         
1910                         for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
1911                         {
1912                                 iRowspan = 1;
1913                                 iColspan = 1;
1914         
1915                                 /* Check to see if there is already a cell (row/colspan) covering our target
1916                                  * insert point. If there is, then there is nothing to do.
1917                                  */
1918                                 if ( aApplied[i][j] === undefined )
1919                                 {
1920                                         nLocalTr.appendChild( aoLocal[i][j].cell );
1921                                         aApplied[i][j] = 1;
1922         
1923                                         /* Expand the cell to cover as many rows as needed */
1924                                         while ( aoLocal[i+iRowspan] !== undefined &&
1925                                                 aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
1926                                         {
1927                                                 aApplied[i+iRowspan][j] = 1;
1928                                                 iRowspan++;
1929                                         }
1930         
1931                                         /* Expand the cell to cover as many columns as needed */
1932                                         while ( aoLocal[i][j+iColspan] !== undefined &&
1933                                                 aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
1934                                         {
1935                                                 /* Must update the applied array over the rows for the columns */
1936                                                 for ( k=0 ; k<iRowspan ; k++ )
1937                                                 {
1938                                                         aApplied[i+k][j+iColspan] = 1;
1939                                                 }
1940                                                 iColspan++;
1941                                         }
1942         
1943                                         /* Do the actual expansion in the DOM */
1944                                         $(aoLocal[i][j].cell)
1945                                                 .attr('rowspan', iRowspan)
1946                                                 .attr('colspan', iColspan);
1947                                 }
1948                         }
1949                 }
1950         }
1951         
1952         
1953         /**
1954          * Insert the required TR nodes into the table for display
1955          *  @param {object} oSettings dataTables settings object
1956          *  @memberof DataTable#oApi
1957          */
1958         function _fnDraw( oSettings )
1959         {
1960                 /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
1961                 var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
1962                 if ( $.inArray( false, aPreDraw ) !== -1 )
1963                 {
1964                         _fnProcessingDisplay( oSettings, false );
1965                         return;
1966                 }
1967         
1968                 var i, iLen, n;
1969                 var anRows = [];
1970                 var iRowCount = 0;
1971                 var asStripeClasses = oSettings.asStripeClasses;
1972                 var iStripes = asStripeClasses.length;
1973                 var iOpenRows = oSettings.aoOpenRows.length;
1974                 var oLang = oSettings.oLanguage;
1975                 var iInitDisplayStart = oSettings.iInitDisplayStart;
1976                 var bServerSide = _fnDataSource( oSettings ) == 'ssp';
1977                 var aiDisplay = oSettings.aiDisplay;
1978         
1979                 oSettings.bDrawing = true;
1980         
1981                 /* Check and see if we have an initial draw position from state saving */
1982                 if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
1983                 {
1984                         oSettings._iDisplayStart = bServerSide ?
1985                                 iInitDisplayStart :
1986                                 iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
1987                                         0 :
1988                                         iInitDisplayStart;
1989         
1990                         oSettings.iInitDisplayStart = -1;
1991                 }
1992         
1993                 var iDisplayStart = oSettings._iDisplayStart;
1994                 var iDisplayEnd = oSettings.fnDisplayEnd();
1995         
1996                 /* Server-side processing draw intercept */
1997                 if ( oSettings.bDeferLoading )
1998                 {
1999                         oSettings.bDeferLoading = false;
2000                         oSettings.iDraw++;
2001                         _fnProcessingDisplay( oSettings, false );
2002                 }
2003                 else if ( !bServerSide )
2004                 {
2005                         oSettings.iDraw++;
2006                 }
2007                 else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
2008                 {
2009                         return;
2010                 }
2011         
2012                 if ( aiDisplay.length !== 0 )
2013                 {
2014                         var iStart = bServerSide ? 0 : iDisplayStart;
2015                         var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
2016         
2017                         for ( var j=iStart ; j<iEnd ; j++ )
2018                         {
2019                                 var iDataIndex = aiDisplay[j];
2020                                 var aoData = oSettings.aoData[ iDataIndex ];
2021                                 if ( aoData.nTr === null )
2022                                 {
2023                                         _fnCreateTr( oSettings, iDataIndex );
2024                                 }
2025         
2026                                 var nRow = aoData.nTr;
2027         
2028                                 /* Remove the old striping classes and then add the new one */
2029                                 if ( iStripes !== 0 )
2030                                 {
2031                                         var sStripe = asStripeClasses[ iRowCount % iStripes ];
2032                                         if ( aoData._sRowStripe != sStripe )
2033                                         {
2034                                                 $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
2035                                                 aoData._sRowStripe = sStripe;
2036                                         }
2037                                 }
2038         
2039                                 // Row callback functions - might want to manipulate the row
2040                                 // iRowCount and j are not currently documented. Are they at all
2041                                 // useful?
2042                                 _fnCallbackFire( oSettings, 'aoRowCallback', null,
2043                                         [nRow, aoData._aData, iRowCount, j] );
2044         
2045                                 anRows.push( nRow );
2046                                 iRowCount++;
2047                         }
2048                 }
2049                 else
2050                 {
2051                         /* Table is empty - create a row with an empty message in it */
2052                         var sZero = oLang.sZeroRecords;
2053                         if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
2054                         {
2055                                 sZero = oLang.sLoadingRecords;
2056                         }
2057                         else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
2058                         {
2059                                 sZero = oLang.sEmptyTable;
2060                         }
2061         
2062                         anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
2063                                 .append( $('<td />', {
2064                                         'valign':  'top',
2065                                         'colSpan': _fnVisbleColumns( oSettings ),
2066                                         'class':   oSettings.oClasses.sRowEmpty
2067                                 } ).html( sZero ) )[0];
2068                 }
2069         
2070                 /* Header and footer callbacks */
2071                 _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
2072                         _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
2073         
2074                 _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
2075                         _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
2076         
2077                 var body = $(oSettings.nTBody);
2078         
2079                 body.children().detach();
2080                 body.append( $(anRows) );
2081         
2082                 /* Call all required callback functions for the end of a draw */
2083                 _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
2084         
2085                 /* Draw is complete, sorting and filtering must be as well */
2086                 oSettings.bSorted = false;
2087                 oSettings.bFiltered = false;
2088                 oSettings.bDrawing = false;
2089         }
2090         
2091         
2092         /**
2093          * Redraw the table - taking account of the various features which are enabled
2094          *  @param {object} oSettings dataTables settings object
2095          *  @param {boolean} [holdPosition] Keep the current paging position. By default
2096          *    the paging is reset to the first page
2097          *  @memberof DataTable#oApi
2098          */
2099         function _fnReDraw( settings, holdPosition )
2100         {
2101                 var
2102                         features = settings.oFeatures,
2103                         sort     = features.bSort,
2104                         filter   = features.bFilter;
2105         
2106                 if ( sort ) {
2107                         _fnSort( settings );
2108                 }
2109         
2110                 if ( filter ) {
2111                         _fnFilterComplete( settings, settings.oPreviousSearch );
2112                 }
2113                 else {
2114                         // No filtering, so we want to just use the display master
2115                         settings.aiDisplay = settings.aiDisplayMaster.slice();
2116                 }
2117         
2118                 if ( holdPosition !== true ) {
2119                         settings._iDisplayStart = 0;
2120                 }
2121         
2122                 // Let any modules know about the draw hold position state (used by
2123                 // scrolling internally)
2124                 settings._drawHold = holdPosition;
2125         
2126                 _fnDraw( settings );
2127         
2128                 settings._drawHold = false;
2129         }
2130         
2131         
2132         /**
2133          * Add the options to the page HTML for the table
2134          *  @param {object} oSettings dataTables settings object
2135          *  @memberof DataTable#oApi
2136          */
2137         function _fnAddOptionsHtml ( oSettings )
2138         {
2139                 var classes = oSettings.oClasses;
2140                 var table = $(oSettings.nTable);
2141                 var holding = $('<div/>').insertBefore( table ); // Holding element for speed
2142                 var features = oSettings.oFeatures;
2143         
2144                 // All DataTables are wrapped in a div
2145                 var insert = $('<div/>', {
2146                         id:      oSettings.sTableId+'_wrapper',
2147                         'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
2148                 } );
2149         
2150                 oSettings.nHolding = holding[0];
2151                 oSettings.nTableWrapper = insert[0];
2152                 oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
2153         
2154                 /* Loop over the user set positioning and place the elements as needed */
2155                 var aDom = oSettings.sDom.split('');
2156                 var featureNode, cOption, nNewNode, cNext, sAttr, j;
2157                 for ( var i=0 ; i<aDom.length ; i++ )
2158                 {
2159                         featureNode = null;
2160                         cOption = aDom[i];
2161         
2162                         if ( cOption == '<' )
2163                         {
2164                                 /* New container div */
2165                                 nNewNode = $('<div/>')[0];
2166         
2167                                 /* Check to see if we should append an id and/or a class name to the container */
2168                                 cNext = aDom[i+1];
2169                                 if ( cNext == "'" || cNext == '"' )
2170                                 {
2171                                         sAttr = "";
2172                                         j = 2;
2173                                         while ( aDom[i+j] != cNext )
2174                                         {
2175                                                 sAttr += aDom[i+j];
2176                                                 j++;
2177                                         }
2178         
2179                                         /* Replace jQuery UI constants @todo depreciated */
2180                                         if ( sAttr == "H" )
2181                                         {
2182                                                 sAttr = classes.sJUIHeader;
2183                                         }
2184                                         else if ( sAttr == "F" )
2185                                         {
2186                                                 sAttr = classes.sJUIFooter;
2187                                         }
2188         
2189                                         /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
2190                                          * breaks the string into parts and applies them as needed
2191                                          */
2192                                         if ( sAttr.indexOf('.') != -1 )
2193                                         {
2194                                                 var aSplit = sAttr.split('.');
2195                                                 nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
2196                                                 nNewNode.className = aSplit[1];
2197                                         }
2198                                         else if ( sAttr.charAt(0) == "#" )
2199                                         {
2200                                                 nNewNode.id = sAttr.substr(1, sAttr.length-1);
2201                                         }
2202                                         else
2203                                         {
2204                                                 nNewNode.className = sAttr;
2205                                         }
2206         
2207                                         i += j; /* Move along the position array */
2208                                 }
2209         
2210                                 insert.append( nNewNode );
2211                                 insert = $(nNewNode);
2212                         }
2213                         else if ( cOption == '>' )
2214                         {
2215                                 /* End container div */
2216                                 insert = insert.parent();
2217                         }
2218                         // @todo Move options into their own plugins?
2219                         else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
2220                         {
2221                                 /* Length */
2222                                 featureNode = _fnFeatureHtmlLength( oSettings );
2223                         }
2224                         else if ( cOption == 'f' && features.bFilter )
2225                         {
2226                                 /* Filter */
2227                                 featureNode = _fnFeatureHtmlFilter( oSettings );
2228                         }
2229                         else if ( cOption == 'r' && features.bProcessing )
2230                         {
2231                                 /* pRocessing */
2232                                 featureNode = _fnFeatureHtmlProcessing( oSettings );
2233                         }
2234                         else if ( cOption == 't' )
2235                         {
2236                                 /* Table */
2237                                 featureNode = _fnFeatureHtmlTable( oSettings );
2238                         }
2239                         else if ( cOption ==  'i' && features.bInfo )
2240                         {
2241                                 /* Info */
2242                                 featureNode = _fnFeatureHtmlInfo( oSettings );
2243                         }
2244                         else if ( cOption == 'p' && features.bPaginate )
2245                         {
2246                                 /* Pagination */
2247                                 featureNode = _fnFeatureHtmlPaginate( oSettings );
2248                         }
2249                         else if ( DataTable.ext.feature.length !== 0 )
2250                         {
2251                                 /* Plug-in features */
2252                                 var aoFeatures = DataTable.ext.feature;
2253                                 for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
2254                                 {
2255                                         if ( cOption == aoFeatures[k].cFeature )
2256                                         {
2257                                                 featureNode = aoFeatures[k].fnInit( oSettings );
2258                                                 break;
2259                                         }
2260                                 }
2261                         }
2262         
2263                         /* Add to the 2D features array */
2264                         if ( featureNode )
2265                         {
2266                                 var aanFeatures = oSettings.aanFeatures;
2267         
2268                                 if ( ! aanFeatures[cOption] )
2269                                 {
2270                                         aanFeatures[cOption] = [];
2271                                 }
2272         
2273                                 aanFeatures[cOption].push( featureNode );
2274                                 insert.append( featureNode );
2275                         }
2276                 }
2277         
2278                 /* Built our DOM structure - replace the holding div with what we want */
2279                 holding.replaceWith( insert );
2280         }
2281         
2282         
2283         /**
2284          * Use the DOM source to create up an array of header cells. The idea here is to
2285          * create a layout grid (array) of rows x columns, which contains a reference
2286          * to the cell that that point in the grid (regardless of col/rowspan), such that
2287          * any column / row could be removed and the new grid constructed
2288          *  @param array {object} aLayout Array to store the calculated layout in
2289          *  @param {node} nThead The header/footer element for the table
2290          *  @memberof DataTable#oApi
2291          */
2292         function _fnDetectHeader ( aLayout, nThead )
2293         {
2294                 var nTrs = $(nThead).children('tr');
2295                 var nTr, nCell;
2296                 var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
2297                 var bUnique;
2298                 var fnShiftCol = function ( a, i, j ) {
2299                         var k = a[i];
2300                         while ( k[j] ) {
2301                                 j++;
2302                         }
2303                         return j;
2304                 };
2305         
2306                 aLayout.splice( 0, aLayout.length );
2307         
2308                 /* We know how many rows there are in the layout - so prep it */
2309                 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
2310                 {
2311                         aLayout.push( [] );
2312                 }
2313         
2314                 /* Calculate a layout array */
2315                 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
2316                 {
2317                         nTr = nTrs[i];
2318                         iColumn = 0;
2319         
2320                         /* For every cell in the row... */
2321                         nCell = nTr.firstChild;
2322                         while ( nCell ) {
2323                                 if ( nCell.nodeName.toUpperCase() == "TD" ||
2324                                      nCell.nodeName.toUpperCase() == "TH" )
2325                                 {
2326                                         /* Get the col and rowspan attributes from the DOM and sanitise them */
2327                                         iColspan = nCell.getAttribute('colspan') * 1;
2328                                         iRowspan = nCell.getAttribute('rowspan') * 1;
2329                                         iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
2330                                         iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
2331         
2332                                         /* There might be colspan cells already in this row, so shift our target
2333                                          * accordingly
2334                                          */
2335                                         iColShifted = fnShiftCol( aLayout, i, iColumn );
2336         
2337                                         /* Cache calculation for unique columns */
2338                                         bUnique = iColspan === 1 ? true : false;
2339         
2340                                         /* If there is col / rowspan, copy the information into the layout grid */
2341                                         for ( l=0 ; l<iColspan ; l++ )
2342                                         {
2343                                                 for ( k=0 ; k<iRowspan ; k++ )
2344                                                 {
2345                                                         aLayout[i+k][iColShifted+l] = {
2346                                                                 "cell": nCell,
2347                                                                 "unique": bUnique
2348                                                         };
2349                                                         aLayout[i+k].nTr = nTr;
2350                                                 }
2351                                         }
2352                                 }
2353                                 nCell = nCell.nextSibling;
2354                         }
2355                 }
2356         }
2357         
2358         
2359         /**
2360          * Get an array of unique th elements, one for each column
2361          *  @param {object} oSettings dataTables settings object
2362          *  @param {node} nHeader automatically detect the layout from this node - optional
2363          *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
2364          *  @returns array {node} aReturn list of unique th's
2365          *  @memberof DataTable#oApi
2366          */
2367         function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
2368         {
2369                 var aReturn = [];
2370                 if ( !aLayout )
2371                 {
2372                         aLayout = oSettings.aoHeader;
2373                         if ( nHeader )
2374                         {
2375                                 aLayout = [];
2376                                 _fnDetectHeader( aLayout, nHeader );
2377                         }
2378                 }
2379         
2380                 for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
2381                 {
2382                         for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
2383                         {
2384                                 if ( aLayout[i][j].unique &&
2385                                          (!aReturn[j] || !oSettings.bSortCellsTop) )
2386                                 {
2387                                         aReturn[j] = aLayout[i][j].cell;
2388                                 }
2389                         }
2390                 }
2391         
2392                 return aReturn;
2393         }
2394         
2395         /**
2396          * Create an Ajax call based on the table's settings, taking into account that
2397          * parameters can have multiple forms, and backwards compatibility.
2398          *
2399          * @param {object} oSettings dataTables settings object
2400          * @param {array} data Data to send to the server, required by
2401          *     DataTables - may be augmented by developer callbacks
2402          * @param {function} fn Callback function to run when data is obtained
2403          */
2404         function _fnBuildAjax( oSettings, data, fn )
2405         {
2406                 // Compatibility with 1.9-, allow fnServerData and event to manipulate
2407                 _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
2408         
2409                 // Convert to object based for 1.10+ if using the old array scheme which can
2410                 // come from server-side processing or serverParams
2411                 if ( data && $.isArray(data) ) {
2412                         var tmp = {};
2413                         var rbracket = /(.*?)\[\]$/;
2414         
2415                         $.each( data, function (key, val) {
2416                                 var match = val.name.match(rbracket);
2417         
2418                                 if ( match ) {
2419                                         // Support for arrays
2420                                         var name = match[0];
2421         
2422                                         if ( ! tmp[ name ] ) {
2423                                                 tmp[ name ] = [];
2424                                         }
2425                                         tmp[ name ].push( val.value );
2426                                 }
2427                                 else {
2428                                         tmp[val.name] = val.value;
2429                                 }
2430                         } );
2431                         data = tmp;
2432                 }
2433         
2434                 var ajaxData;
2435                 var ajax = oSettings.ajax;
2436                 var instance = oSettings.oInstance;
2437                 var callback = function ( json ) {
2438                         _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
2439                         fn( json );
2440                 };
2441         
2442                 if ( $.isPlainObject( ajax ) && ajax.data )
2443                 {
2444                         ajaxData = ajax.data;
2445         
2446                         var newData = $.isFunction( ajaxData ) ?
2447                                 ajaxData( data, oSettings ) :  // fn can manipulate data or return
2448                                 ajaxData;                      // an object object or array to merge
2449         
2450                         // If the function returned something, use that alone
2451                         data = $.isFunction( ajaxData ) && newData ?
2452                                 newData :
2453                                 $.extend( true, data, newData );
2454         
2455                         // Remove the data property as we've resolved it already and don't want
2456                         // jQuery to do it again (it is restored at the end of the function)
2457                         delete ajax.data;
2458                 }
2459         
2460                 var baseAjax = {
2461                         "data": data,
2462                         "success": function (json) {
2463                                 var error = json.error || json.sError;
2464                                 if ( error ) {
2465                                         _fnLog( oSettings, 0, error );
2466                                 }
2467         
2468                                 oSettings.json = json;
2469                                 callback( json );
2470                         },
2471                         "dataType": "json",
2472                         "cache": false,
2473                         "type": oSettings.sServerMethod,
2474                         "error": function (xhr, error, thrown) {
2475                                 var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
2476         
2477                                 if ( $.inArray( true, ret ) === -1 ) {
2478                                         if ( error == "parsererror" ) {
2479                                                 _fnLog( oSettings, 0, 'Invalid JSON response', 1 );
2480                                         }
2481                                         else if ( xhr.readyState === 4 ) {
2482                                                 _fnLog( oSettings, 0, 'Ajax error', 7 );
2483                                         }
2484                                 }
2485         
2486                                 _fnProcessingDisplay( oSettings, false );
2487                         }
2488                 };
2489         
2490                 // Store the data submitted for the API
2491                 oSettings.oAjaxData = data;
2492         
2493                 // Allow plug-ins and external processes to modify the data
2494                 _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
2495         
2496                 if ( oSettings.fnServerData )
2497                 {
2498                         // DataTables 1.9- compatibility
2499                         oSettings.fnServerData.call( instance,
2500                                 oSettings.sAjaxSource,
2501                                 $.map( data, function (val, key) { // Need to convert back to 1.9 trad format
2502                                         return { name: key, value: val };
2503                                 } ),
2504                                 callback,
2505                                 oSettings
2506                         );
2507                 }
2508                 else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
2509                 {
2510                         // DataTables 1.9- compatibility
2511                         oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
2512                                 url: ajax || oSettings.sAjaxSource
2513                         } ) );
2514                 }
2515                 else if ( $.isFunction( ajax ) )
2516                 {
2517                         // Is a function - let the caller define what needs to be done
2518                         oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
2519                 }
2520                 else
2521                 {
2522                         // Object to extend the base settings
2523                         oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
2524         
2525                         // Restore for next time around
2526                         ajax.data = ajaxData;
2527                 }
2528         }
2529         
2530         
2531         /**
2532          * Update the table using an Ajax call
2533          *  @param {object} settings dataTables settings object
2534          *  @returns {boolean} Block the table drawing or not
2535          *  @memberof DataTable#oApi
2536          */
2537         function _fnAjaxUpdate( settings )
2538         {
2539                 if ( settings.bAjaxDataGet ) {
2540                         settings.iDraw++;
2541                         _fnProcessingDisplay( settings, true );
2542         
2543                         _fnBuildAjax(
2544                                 settings,
2545                                 _fnAjaxParameters( settings ),
2546                                 function(json) {
2547                                         _fnAjaxUpdateDraw( settings, json );
2548                                 }
2549                         );
2550         
2551                         return false;
2552                 }
2553                 return true;
2554         }
2555         
2556         
2557         /**
2558          * Build up the parameters in an object needed for a server-side processing
2559          * request. Note that this is basically done twice, is different ways - a modern
2560          * method which is used by default in DataTables 1.10 which uses objects and
2561          * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
2562          * the sAjaxSource option is used in the initialisation, or the legacyAjax
2563          * option is set.
2564          *  @param {object} oSettings dataTables settings object
2565          *  @returns {bool} block the table drawing or not
2566          *  @memberof DataTable#oApi
2567          */
2568         function _fnAjaxParameters( settings )
2569         {
2570                 var
2571                         columns = settings.aoColumns,
2572                         columnCount = columns.length,
2573                         features = settings.oFeatures,
2574                         preSearch = settings.oPreviousSearch,
2575                         preColSearch = settings.aoPreSearchCols,
2576                         i, data = [], dataProp, column, columnSearch,
2577                         sort = _fnSortFlatten( settings ),
2578                         displayStart = settings._iDisplayStart,
2579                         displayLength = features.bPaginate !== false ?
2580                                 settings._iDisplayLength :
2581                                 -1;
2582         
2583                 var param = function ( name, value ) {
2584                         data.push( { 'name': name, 'value': value } );
2585                 };
2586         
2587                 // DataTables 1.9- compatible method
2588                 param( 'sEcho',          settings.iDraw );
2589                 param( 'iColumns',       columnCount );
2590                 param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
2591                 param( 'iDisplayStart',  displayStart );
2592                 param( 'iDisplayLength', displayLength );
2593         
2594                 // DataTables 1.10+ method
2595                 var d = {
2596                         draw:    settings.iDraw,
2597                         columns: [],
2598                         order:   [],
2599                         start:   displayStart,
2600                         length:  displayLength,
2601                         search:  {
2602                                 value: preSearch.sSearch,
2603                                 regex: preSearch.bRegex
2604                         }
2605                 };
2606         
2607                 for ( i=0 ; i<columnCount ; i++ ) {
2608                         column = columns[i];
2609                         columnSearch = preColSearch[i];
2610                         dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
2611         
2612                         d.columns.push( {
2613                                 data:       dataProp,
2614                                 name:       column.sName,
2615                                 searchable: column.bSearchable,
2616                                 orderable:  column.bSortable,
2617                                 search:     {
2618                                         value: columnSearch.sSearch,
2619                                         regex: columnSearch.bRegex
2620                                 }
2621                         } );
2622         
2623                         param( "mDataProp_"+i, dataProp );
2624         
2625                         if ( features.bFilter ) {
2626                                 param( 'sSearch_'+i,     columnSearch.sSearch );
2627                                 param( 'bRegex_'+i,      columnSearch.bRegex );
2628                                 param( 'bSearchable_'+i, column.bSearchable );
2629                         }
2630         
2631                         if ( features.bSort ) {
2632                                 param( 'bSortable_'+i, column.bSortable );
2633                         }
2634                 }
2635         
2636                 if ( features.bFilter ) {
2637                         param( 'sSearch', preSearch.sSearch );
2638                         param( 'bRegex', preSearch.bRegex );
2639                 }
2640         
2641                 if ( features.bSort ) {
2642                         $.each( sort, function ( i, val ) {
2643                                 d.order.push( { column: val.col, dir: val.dir } );
2644         
2645                                 param( 'iSortCol_'+i, val.col );
2646                                 param( 'sSortDir_'+i, val.dir );
2647                         } );
2648         
2649                         param( 'iSortingCols', sort.length );
2650                 }
2651         
2652                 // If the legacy.ajax parameter is null, then we automatically decide which
2653                 // form to use, based on sAjaxSource
2654                 var legacy = DataTable.ext.legacy.ajax;
2655                 if ( legacy === null ) {
2656                         return settings.sAjaxSource ? data : d;
2657                 }
2658         
2659                 // Otherwise, if legacy has been specified then we use that to decide on the
2660                 // form
2661                 return legacy ? data : d;
2662         }
2663         
2664         
2665         /**
2666          * Data the data from the server (nuking the old) and redraw the table
2667          *  @param {object} oSettings dataTables settings object
2668          *  @param {object} json json data return from the server.
2669          *  @param {string} json.sEcho Tracking flag for DataTables to match requests
2670          *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
2671          *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
2672          *  @param {array} json.aaData The data to display on this page
2673          *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
2674          *  @memberof DataTable#oApi
2675          */
2676         function _fnAjaxUpdateDraw ( settings, json )
2677         {
2678                 // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
2679                 // Support both
2680                 var compat = function ( old, modern ) {
2681                         return json[old] !== undefined ? json[old] : json[modern];
2682                 };
2683         
2684                 var data = _fnAjaxDataSrc( settings, json );
2685                 var draw            = compat( 'sEcho',                'draw' );
2686                 var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
2687                 var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
2688         
2689                 if ( draw ) {
2690                         // Protect against out of sequence returns
2691                         if ( draw*1 < settings.iDraw ) {
2692                                 return;
2693                         }
2694                         settings.iDraw = draw * 1;
2695                 }
2696         
2697                 _fnClearTable( settings );
2698                 settings._iRecordsTotal   = parseInt(recordsTotal, 10);
2699                 settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
2700         
2701                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
2702                         _fnAddData( settings, data[i] );
2703                 }
2704                 settings.aiDisplay = settings.aiDisplayMaster.slice();
2705         
2706                 settings.bAjaxDataGet = false;
2707                 _fnDraw( settings );
2708         
2709                 if ( ! settings._bInitComplete ) {
2710                         _fnInitComplete( settings, json );
2711                 }
2712         
2713                 settings.bAjaxDataGet = true;
2714                 _fnProcessingDisplay( settings, false );
2715         }
2716         
2717         
2718         /**
2719          * Get the data from the JSON data source to use for drawing a table. Using
2720          * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
2721          * source object, or from a processing function.
2722          *  @param {object} oSettings dataTables settings object
2723          *  @param  {object} json Data source object / array from the server
2724          *  @return {array} Array of data to use
2725          */
2726         function _fnAjaxDataSrc ( oSettings, json )
2727         {
2728                 var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
2729                         oSettings.ajax.dataSrc :
2730                         oSettings.sAjaxDataProp; // Compatibility with 1.9-.
2731         
2732                 // Compatibility with 1.9-. In order to read from aaData, check if the
2733                 // default has been changed, if not, check for aaData
2734                 if ( dataSrc === 'data' ) {
2735                         return json.aaData || json[dataSrc];
2736                 }
2737         
2738                 return dataSrc !== "" ?
2739                         _fnGetObjectDataFn( dataSrc )( json ) :
2740                         json;
2741         }
2742         
2743         /**
2744          * Generate the node required for filtering text
2745          *  @returns {node} Filter control element
2746          *  @param {object} oSettings dataTables settings object
2747          *  @memberof DataTable#oApi
2748          */
2749         function _fnFeatureHtmlFilter ( settings )
2750         {
2751                 var classes = settings.oClasses;
2752                 var tableId = settings.sTableId;
2753                 var language = settings.oLanguage;
2754                 var previousSearch = settings.oPreviousSearch;
2755                 var features = settings.aanFeatures;
2756                 var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
2757         
2758                 var str = language.sSearch;
2759                 str = str.match(/_INPUT_/) ?
2760                         str.replace('_INPUT_', input) :
2761                         str+input;
2762         
2763                 var filter = $('<div/>', {
2764                                 'id': ! features.f ? tableId+'_filter' : null,
2765                                 'class': classes.sFilter
2766                         } )
2767                         .append( $('<label/>' ).append( str ) );
2768         
2769                 var searchFn = function() {
2770                         /* Update all other filter input elements for the new display */
2771                         var n = features.f;
2772                         var val = !this.value ? "" : this.value; // mental IE8 fix :-(
2773         
2774                         /* Now do the filter */
2775                         if ( val != previousSearch.sSearch ) {
2776                                 _fnFilterComplete( settings, {
2777                                         "sSearch": val,
2778                                         "bRegex": previousSearch.bRegex,
2779                                         "bSmart": previousSearch.bSmart ,
2780                                         "bCaseInsensitive": previousSearch.bCaseInsensitive
2781                                 } );
2782         
2783                                 // Need to redraw, without resorting
2784                                 settings._iDisplayStart = 0;
2785                                 _fnDraw( settings );
2786                         }
2787                 };
2788         
2789                 var searchDelay = settings.searchDelay !== null ?
2790                         settings.searchDelay :
2791                         _fnDataSource( settings ) === 'ssp' ?
2792                                 400 :
2793                                 0;
2794         
2795                 var jqFilter = $('input', filter)
2796                         .val( previousSearch.sSearch )
2797                         .attr( 'placeholder', language.sSearchPlaceholder )
2798                         .bind(
2799                                 'keyup.DT search.DT input.DT paste.DT cut.DT',
2800                                 searchDelay ?
2801                                         _fnThrottle( searchFn, searchDelay ) :
2802                                         searchFn
2803                         )
2804                         .bind( 'keypress.DT', function(e) {
2805                                 /* Prevent form submission */
2806                                 if ( e.keyCode == 13 ) {
2807                                         return false;
2808                                 }
2809                         } )
2810                         .attr('aria-controls', tableId);
2811         
2812                 // Update the input elements whenever the table is filtered
2813                 $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
2814                         if ( settings === s ) {
2815                                 // IE9 throws an 'unknown error' if document.activeElement is used
2816                                 // inside an iframe or frame...
2817                                 try {
2818                                         if ( jqFilter[0] !== document.activeElement ) {
2819                                                 jqFilter.val( previousSearch.sSearch );
2820                                         }
2821                                 }
2822                                 catch ( e ) {}
2823                         }
2824                 } );
2825         
2826                 return filter[0];
2827         }
2828         
2829         
2830         /**
2831          * Filter the table using both the global filter and column based filtering
2832          *  @param {object} oSettings dataTables settings object
2833          *  @param {object} oSearch search information
2834          *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
2835          *  @memberof DataTable#oApi
2836          */
2837         function _fnFilterComplete ( oSettings, oInput, iForce )
2838         {
2839                 var oPrevSearch = oSettings.oPreviousSearch;
2840                 var aoPrevSearch = oSettings.aoPreSearchCols;
2841                 var fnSaveFilter = function ( oFilter ) {
2842                         /* Save the filtering values */
2843                         oPrevSearch.sSearch = oFilter.sSearch;
2844                         oPrevSearch.bRegex = oFilter.bRegex;
2845                         oPrevSearch.bSmart = oFilter.bSmart;
2846                         oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
2847                 };
2848                 var fnRegex = function ( o ) {
2849                         // Backwards compatibility with the bEscapeRegex option
2850                         return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
2851                 };
2852         
2853                 // Resolve any column types that are unknown due to addition or invalidation
2854                 // @todo As per sort - can this be moved into an event handler?
2855                 _fnColumnTypes( oSettings );
2856         
2857                 /* In server-side processing all filtering is done by the server, so no point hanging around here */
2858                 if ( _fnDataSource( oSettings ) != 'ssp' )
2859                 {
2860                         /* Global filter */
2861                         _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
2862                         fnSaveFilter( oInput );
2863         
2864                         /* Now do the individual column filter */
2865                         for ( var i=0 ; i<aoPrevSearch.length ; i++ )
2866                         {
2867                                 _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
2868                                         aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
2869                         }
2870         
2871                         /* Custom filtering */
2872                         _fnFilterCustom( oSettings );
2873                 }
2874                 else
2875                 {
2876                         fnSaveFilter( oInput );
2877                 }
2878         
2879                 /* Tell the draw function we have been filtering */
2880                 oSettings.bFiltered = true;
2881                 _fnCallbackFire( oSettings, null, 'search', [oSettings] );
2882         }
2883         
2884         
2885         /**
2886          * Apply custom filtering functions
2887          *  @param {object} oSettings dataTables settings object
2888          *  @memberof DataTable#oApi
2889          */
2890         function _fnFilterCustom( settings )
2891         {
2892                 var filters = DataTable.ext.search;
2893                 var displayRows = settings.aiDisplay;
2894                 var row, rowIdx;
2895         
2896                 for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
2897                         var rows = [];
2898         
2899                         // Loop over each row and see if it should be included
2900                         for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
2901                                 rowIdx = displayRows[ j ];
2902                                 row = settings.aoData[ rowIdx ];
2903         
2904                                 if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
2905                                         rows.push( rowIdx );
2906                                 }
2907                         }
2908         
2909                         // So the array reference doesn't break set the results into the
2910                         // existing array
2911                         displayRows.length = 0;
2912                         displayRows.push.apply( displayRows, rows );
2913                 }
2914         }
2915         
2916         
2917         /**
2918          * Filter the table on a per-column basis
2919          *  @param {object} oSettings dataTables settings object
2920          *  @param {string} sInput string to filter on
2921          *  @param {int} iColumn column to filter
2922          *  @param {bool} bRegex treat search string as a regular expression or not
2923          *  @param {bool} bSmart use smart filtering or not
2924          *  @param {bool} bCaseInsensitive Do case insenstive matching or not
2925          *  @memberof DataTable#oApi
2926          */
2927         function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
2928         {
2929                 if ( searchStr === '' ) {
2930                         return;
2931                 }
2932         
2933                 var data;
2934                 var display = settings.aiDisplay;
2935                 var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
2936         
2937                 for ( var i=display.length-1 ; i>=0 ; i-- ) {
2938                         data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
2939         
2940                         if ( ! rpSearch.test( data ) ) {
2941                                 display.splice( i, 1 );
2942                         }
2943                 }
2944         }
2945         
2946         
2947         /**
2948          * Filter the data table based on user input and draw the table
2949          *  @param {object} settings dataTables settings object
2950          *  @param {string} input string to filter on
2951          *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
2952          *  @param {bool} regex treat as a regular expression or not
2953          *  @param {bool} smart perform smart filtering or not
2954          *  @param {bool} caseInsensitive Do case insenstive matching or not
2955          *  @memberof DataTable#oApi
2956          */
2957         function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
2958         {
2959                 var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
2960                 var prevSearch = settings.oPreviousSearch.sSearch;
2961                 var displayMaster = settings.aiDisplayMaster;
2962                 var display, invalidated, i;
2963         
2964                 // Need to take account of custom filtering functions - always filter
2965                 if ( DataTable.ext.search.length !== 0 ) {
2966                         force = true;
2967                 }
2968         
2969                 // Check if any of the rows were invalidated
2970                 invalidated = _fnFilterData( settings );
2971         
2972                 // If the input is blank - we just want the full data set
2973                 if ( input.length <= 0 ) {
2974                         settings.aiDisplay = displayMaster.slice();
2975                 }
2976                 else {
2977                         // New search - start from the master array
2978                         if ( invalidated ||
2979                                  force ||
2980                                  prevSearch.length > input.length ||
2981                                  input.indexOf(prevSearch) !== 0 ||
2982                                  settings.bSorted // On resort, the display master needs to be
2983                                                   // re-filtered since indexes will have changed
2984                         ) {
2985                                 settings.aiDisplay = displayMaster.slice();
2986                         }
2987         
2988                         // Search the display array
2989                         display = settings.aiDisplay;
2990         
2991                         for ( i=display.length-1 ; i>=0 ; i-- ) {
2992                                 if ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
2993                                         display.splice( i, 1 );
2994                                 }
2995                         }
2996                 }
2997         }
2998         
2999         
3000         /**
3001          * Build a regular expression object suitable for searching a table
3002          *  @param {string} sSearch string to search for
3003          *  @param {bool} bRegex treat as a regular expression or not
3004          *  @param {bool} bSmart perform smart filtering or not
3005          *  @param {bool} bCaseInsensitive Do case insensitive matching or not
3006          *  @returns {RegExp} constructed object
3007          *  @memberof DataTable#oApi
3008          */
3009         function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
3010         {
3011                 search = regex ?
3012                         search :
3013                         _fnEscapeRegex( search );
3014                 
3015                 if ( smart ) {
3016                         /* For smart filtering we want to allow the search to work regardless of
3017                          * word order. We also want double quoted text to be preserved, so word
3018                          * order is important - a la google. So this is what we want to
3019                          * generate:
3020                          * 
3021                          * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
3022                          */
3023                         var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
3024                                 if ( word.charAt(0) === '"' ) {
3025                                         var m = word.match( /^"(.*)"$/ );
3026                                         word = m ? m[1] : word;
3027                                 }
3028         
3029                                 return word.replace('"', '');
3030                         } );
3031         
3032                         search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
3033                 }
3034         
3035                 return new RegExp( search, caseInsensitive ? 'i' : '' );
3036         }
3037         
3038         
3039         /**
3040          * Escape a string such that it can be used in a regular expression
3041          *  @param {string} sVal string to escape
3042          *  @returns {string} escaped string
3043          *  @memberof DataTable#oApi
3044          */
3045         function _fnEscapeRegex ( sVal )
3046         {
3047                 return sVal.replace( _re_escape_regex, '\\$1' );
3048         }
3049         
3050         
3051         
3052         var __filter_div = $('<div>')[0];
3053         var __filter_div_textContent = __filter_div.textContent !== undefined;
3054         
3055         // Update the filtering data for each row if needed (by invalidation or first run)
3056         function _fnFilterData ( settings )
3057         {
3058                 var columns = settings.aoColumns;
3059                 var column;
3060                 var i, j, ien, jen, filterData, cellData, row;
3061                 var fomatters = DataTable.ext.type.search;
3062                 var wasInvalidated = false;
3063         
3064                 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
3065                         row = settings.aoData[i];
3066         
3067                         if ( ! row._aFilterData ) {
3068                                 filterData = [];
3069         
3070                                 for ( j=0, jen=columns.length ; j<jen ; j++ ) {
3071                                         column = columns[j];
3072         
3073                                         if ( column.bSearchable ) {
3074                                                 cellData = _fnGetCellData( settings, i, j, 'filter' );
3075         
3076                                                 if ( fomatters[ column.sType ] ) {
3077                                                         cellData = fomatters[ column.sType ]( cellData );
3078                                                 }
3079         
3080                                                 // Search in DataTables 1.10 is string based. In 1.11 this
3081                                                 // should be altered to also allow strict type checking.
3082                                                 if ( cellData === null ) {
3083                                                         cellData = '';
3084                                                 }
3085         
3086                                                 if ( typeof cellData !== 'string' && cellData.toString ) {
3087                                                         cellData = cellData.toString();
3088                                                 }
3089                                         }
3090                                         else {
3091                                                 cellData = '';
3092                                         }
3093         
3094                                         // If it looks like there is an HTML entity in the string,
3095                                         // attempt to decode it so sorting works as expected. Note that
3096                                         // we could use a single line of jQuery to do this, but the DOM
3097                                         // method used here is much faster http://jsperf.com/html-decode
3098                                         if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
3099                                                 __filter_div.innerHTML = cellData;
3100                                                 cellData = __filter_div_textContent ?
3101                                                         __filter_div.textContent :
3102                                                         __filter_div.innerText;
3103                                         }
3104         
3105                                         if ( cellData.replace ) {
3106                                                 cellData = cellData.replace(/[\r\n]/g, '');
3107                                         }
3108         
3109                                         filterData.push( cellData );
3110                                 }
3111         
3112                                 row._aFilterData = filterData;
3113                                 row._sFilterRow = filterData.join('  ');
3114                                 wasInvalidated = true;
3115                         }
3116                 }
3117         
3118                 return wasInvalidated;
3119         }
3120         
3121         
3122         /**
3123          * Convert from the internal Hungarian notation to camelCase for external
3124          * interaction
3125          *  @param {object} obj Object to convert
3126          *  @returns {object} Inverted object
3127          *  @memberof DataTable#oApi
3128          */
3129         function _fnSearchToCamel ( obj )
3130         {
3131                 return {
3132                         search:          obj.sSearch,
3133                         smart:           obj.bSmart,
3134                         regex:           obj.bRegex,
3135                         caseInsensitive: obj.bCaseInsensitive
3136                 };
3137         }
3138         
3139         
3140         
3141         /**
3142          * Convert from camelCase notation to the internal Hungarian. We could use the
3143          * Hungarian convert function here, but this is cleaner
3144          *  @param {object} obj Object to convert
3145          *  @returns {object} Inverted object
3146          *  @memberof DataTable#oApi
3147          */
3148         function _fnSearchToHung ( obj )
3149         {
3150                 return {
3151                         sSearch:          obj.search,
3152                         bSmart:           obj.smart,
3153                         bRegex:           obj.regex,
3154                         bCaseInsensitive: obj.caseInsensitive
3155                 };
3156         }
3157         
3158         /**
3159          * Generate the node required for the info display
3160          *  @param {object} oSettings dataTables settings object
3161          *  @returns {node} Information element
3162          *  @memberof DataTable#oApi
3163          */
3164         function _fnFeatureHtmlInfo ( settings )
3165         {
3166                 var
3167                         tid = settings.sTableId,
3168                         nodes = settings.aanFeatures.i,
3169                         n = $('<div/>', {
3170                                 'class': settings.oClasses.sInfo,
3171                                 'id': ! nodes ? tid+'_info' : null
3172                         } );
3173         
3174                 if ( ! nodes ) {
3175                         // Update display on each draw
3176                         settings.aoDrawCallback.push( {
3177                                 "fn": _fnUpdateInfo,
3178                                 "sName": "information"
3179                         } );
3180         
3181                         n
3182                                 .attr( 'role', 'status' )
3183                                 .attr( 'aria-live', 'polite' );
3184         
3185                         // Table is described by our info div
3186                         $(settings.nTable).attr( 'aria-describedby', tid+'_info' );
3187                 }
3188         
3189                 return n[0];
3190         }
3191         
3192         
3193         /**
3194          * Update the information elements in the display
3195          *  @param {object} settings dataTables settings object
3196          *  @memberof DataTable#oApi
3197          */
3198         function _fnUpdateInfo ( settings )
3199         {
3200                 /* Show information about the table */
3201                 var nodes = settings.aanFeatures.i;
3202                 if ( nodes.length === 0 ) {
3203                         return;
3204                 }
3205         
3206                 var
3207                         lang  = settings.oLanguage,
3208                         start = settings._iDisplayStart+1,
3209                         end   = settings.fnDisplayEnd(),
3210                         max   = settings.fnRecordsTotal(),
3211                         total = settings.fnRecordsDisplay(),
3212                         out   = total ?
3213                                 lang.sInfo :
3214                                 lang.sInfoEmpty;
3215         
3216                 if ( total !== max ) {
3217                         /* Record set after filtering */
3218                         out += ' ' + lang.sInfoFiltered;
3219                 }
3220         
3221                 // Convert the macros
3222                 out += lang.sInfoPostFix;
3223                 out = _fnInfoMacros( settings, out );
3224         
3225                 var callback = lang.fnInfoCallback;
3226                 if ( callback !== null ) {
3227                         out = callback.call( settings.oInstance,
3228                                 settings, start, end, max, total, out
3229                         );
3230                 }
3231         
3232                 $(nodes).html( out );
3233         }
3234         
3235         
3236         function _fnInfoMacros ( settings, str )
3237         {
3238                 // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
3239                 // internally
3240                 var
3241                         formatter  = settings.fnFormatNumber,
3242                         start      = settings._iDisplayStart+1,
3243                         len        = settings._iDisplayLength,
3244                         vis        = settings.fnRecordsDisplay(),
3245                         all        = len === -1;
3246         
3247                 return str.
3248                         replace(/_START_/g, formatter.call( settings, start ) ).
3249                         replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
3250                         replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
3251                         replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
3252                         replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
3253                         replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
3254         }
3255         
3256         
3257         
3258         /**
3259          * Draw the table for the first time, adding all required features
3260          *  @param {object} settings dataTables settings object
3261          *  @memberof DataTable#oApi
3262          */
3263         function _fnInitialise ( settings )
3264         {
3265                 var i, iLen, iAjaxStart=settings.iInitDisplayStart;
3266                 var columns = settings.aoColumns, column;
3267                 var features = settings.oFeatures;
3268         
3269                 /* Ensure that the table data is fully initialised */
3270                 if ( ! settings.bInitialised ) {
3271                         setTimeout( function(){ _fnInitialise( settings ); }, 200 );
3272                         return;
3273                 }
3274         
3275                 /* Show the display HTML options */
3276                 _fnAddOptionsHtml( settings );
3277         
3278                 /* Build and draw the header / footer for the table */
3279                 _fnBuildHead( settings );
3280                 _fnDrawHead( settings, settings.aoHeader );
3281                 _fnDrawHead( settings, settings.aoFooter );
3282         
3283                 /* Okay to show that something is going on now */
3284                 _fnProcessingDisplay( settings, true );
3285         
3286                 /* Calculate sizes for columns */
3287                 if ( features.bAutoWidth ) {
3288                         _fnCalculateColumnWidths( settings );
3289                 }
3290         
3291                 for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
3292                         column = columns[i];
3293         
3294                         if ( column.sWidth ) {
3295                                 column.nTh.style.width = _fnStringToCss( column.sWidth );
3296                         }
3297                 }
3298         
3299                 // If there is default sorting required - let's do it. The sort function
3300                 // will do the drawing for us. Otherwise we draw the table regardless of the
3301                 // Ajax source - this allows the table to look initialised for Ajax sourcing
3302                 // data (show 'loading' message possibly)
3303                 _fnReDraw( settings );
3304         
3305                 // Server-side processing init complete is done by _fnAjaxUpdateDraw
3306                 var dataSrc = _fnDataSource( settings );
3307                 if ( dataSrc != 'ssp' ) {
3308                         // if there is an ajax source load the data
3309                         if ( dataSrc == 'ajax' ) {
3310                                 _fnBuildAjax( settings, [], function(json) {
3311                                         var aData = _fnAjaxDataSrc( settings, json );
3312         
3313                                         // Got the data - add it to the table
3314                                         for ( i=0 ; i<aData.length ; i++ ) {
3315                                                 _fnAddData( settings, aData[i] );
3316                                         }
3317         
3318                                         // Reset the init display for cookie saving. We've already done
3319                                         // a filter, and therefore cleared it before. So we need to make
3320                                         // it appear 'fresh'
3321                                         settings.iInitDisplayStart = iAjaxStart;
3322         
3323                                         _fnReDraw( settings );
3324         
3325                                         _fnProcessingDisplay( settings, false );
3326                                         _fnInitComplete( settings, json );
3327                                 }, settings );
3328                         }
3329                         else {
3330                                 _fnProcessingDisplay( settings, false );
3331                                 _fnInitComplete( settings );
3332                         }
3333                 }
3334         }
3335         
3336         
3337         /**
3338          * Draw the table for the first time, adding all required features
3339          *  @param {object} oSettings dataTables settings object
3340          *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
3341          *    with client-side processing (optional)
3342          *  @memberof DataTable#oApi
3343          */
3344         function _fnInitComplete ( settings, json )
3345         {
3346                 settings._bInitComplete = true;
3347         
3348                 // On an Ajax load we now have data and therefore want to apply the column
3349                 // sizing
3350                 if ( json ) {
3351                         _fnAdjustColumnSizing( settings );
3352                 }
3353         
3354                 _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
3355         }
3356         
3357         
3358         function _fnLengthChange ( settings, val )
3359         {
3360                 var len = parseInt( val, 10 );
3361                 settings._iDisplayLength = len;
3362         
3363                 _fnLengthOverflow( settings );
3364         
3365                 // Fire length change event
3366                 _fnCallbackFire( settings, null, 'length', [settings, len] );
3367         }
3368         
3369         
3370         /**
3371          * Generate the node required for user display length changing
3372          *  @param {object} settings dataTables settings object
3373          *  @returns {node} Display length feature node
3374          *  @memberof DataTable#oApi
3375          */
3376         function _fnFeatureHtmlLength ( settings )
3377         {
3378                 var
3379                         classes  = settings.oClasses,
3380                         tableId  = settings.sTableId,
3381                         menu     = settings.aLengthMenu,
3382                         d2       = $.isArray( menu[0] ),
3383                         lengths  = d2 ? menu[0] : menu,
3384                         language = d2 ? menu[1] : menu;
3385         
3386                 var select = $('<select/>', {
3387                         'name':          tableId+'_length',
3388                         'aria-controls': tableId,
3389                         'class':         classes.sLengthSelect
3390                 } );
3391         
3392                 for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
3393                         select[0][ i ] = new Option( language[i], lengths[i] );
3394                 }
3395         
3396                 var div = $('<div><label/></div>').addClass( classes.sLength );
3397                 if ( ! settings.aanFeatures.l ) {
3398                         div[0].id = tableId+'_length';
3399                 }
3400         
3401                 div.children().append(
3402                         settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
3403                 );
3404         
3405                 // Can't use `select` variable as user might provide their own and the
3406                 // reference is broken by the use of outerHTML
3407                 $('select', div)
3408                         .val( settings._iDisplayLength )
3409                         .bind( 'change.DT', function(e) {
3410                                 _fnLengthChange( settings, $(this).val() );
3411                                 _fnDraw( settings );
3412                         } );
3413         
3414                 // Update node value whenever anything changes the table's length
3415                 $(settings.nTable).bind( 'length.dt.DT', function (e, s, len) {
3416                         if ( settings === s ) {
3417                                 $('select', div).val( len );
3418                         }
3419                 } );
3420         
3421                 return div[0];
3422         }
3423         
3424         
3425         
3426         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3427          * Note that most of the paging logic is done in
3428          * DataTable.ext.pager
3429          */
3430         
3431         /**
3432          * Generate the node required for default pagination
3433          *  @param {object} oSettings dataTables settings object
3434          *  @returns {node} Pagination feature node
3435          *  @memberof DataTable#oApi
3436          */
3437         function _fnFeatureHtmlPaginate ( settings )
3438         {
3439                 var
3440                         type   = settings.sPaginationType,
3441                         plugin = DataTable.ext.pager[ type ],
3442                         modern = typeof plugin === 'function',
3443                         redraw = function( settings ) {
3444                                 _fnDraw( settings );
3445                         },
3446                         node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
3447                         features = settings.aanFeatures;
3448         
3449                 if ( ! modern ) {
3450                         plugin.fnInit( settings, node, redraw );
3451                 }
3452         
3453                 /* Add a draw callback for the pagination on first instance, to update the paging display */
3454                 if ( ! features.p )
3455                 {
3456                         node.id = settings.sTableId+'_paginate';
3457         
3458                         settings.aoDrawCallback.push( {
3459                                 "fn": function( settings ) {
3460                                         if ( modern ) {
3461                                                 var
3462                                                         start      = settings._iDisplayStart,
3463                                                         len        = settings._iDisplayLength,
3464                                                         visRecords = settings.fnRecordsDisplay(),
3465                                                         all        = len === -1,
3466                                                         page = all ? 0 : Math.ceil( start / len ),
3467                                                         pages = all ? 1 : Math.ceil( visRecords / len ),
3468                                                         buttons = plugin(page, pages),
3469                                                         i, ien;
3470         
3471                                                 for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
3472                                                         _fnRenderer( settings, 'pageButton' )(
3473                                                                 settings, features.p[i], i, buttons, page, pages
3474                                                         );
3475                                                 }
3476                                         }
3477                                         else {
3478                                                 plugin.fnUpdate( settings, redraw );
3479                                         }
3480                                 },
3481                                 "sName": "pagination"
3482                         } );
3483                 }
3484         
3485                 return node;
3486         }
3487         
3488         
3489         /**
3490          * Alter the display settings to change the page
3491          *  @param {object} settings DataTables settings object
3492          *  @param {string|int} action Paging action to take: "first", "previous",
3493          *    "next" or "last" or page number to jump to (integer)
3494          *  @param [bool] redraw Automatically draw the update or not
3495          *  @returns {bool} true page has changed, false - no change
3496          *  @memberof DataTable#oApi
3497          */
3498         function _fnPageChange ( settings, action, redraw )
3499         {
3500                 var
3501                         start     = settings._iDisplayStart,
3502                         len       = settings._iDisplayLength,
3503                         records   = settings.fnRecordsDisplay();
3504         
3505                 if ( records === 0 || len === -1 )
3506                 {
3507                         start = 0;
3508                 }
3509                 else if ( typeof action === "number" )
3510                 {
3511                         start = action * len;
3512         
3513                         if ( start > records )
3514                         {
3515                                 start = 0;
3516                         }
3517                 }
3518                 else if ( action == "first" )
3519                 {
3520                         start = 0;
3521                 }
3522                 else if ( action == "previous" )
3523                 {
3524                         start = len >= 0 ?
3525                                 start - len :
3526                                 0;
3527         
3528                         if ( start < 0 )
3529                         {
3530                           start = 0;
3531                         }
3532                 }
3533                 else if ( action == "next" )
3534                 {
3535                         if ( start + len < records )
3536                         {
3537                                 start += len;
3538                         }
3539                 }
3540                 else if ( action == "last" )
3541                 {
3542                         start = Math.floor( (records-1) / len) * len;
3543                 }
3544                 else
3545                 {
3546                         _fnLog( settings, 0, "Unknown paging action: "+action, 5 );
3547                 }
3548         
3549                 var changed = settings._iDisplayStart !== start;
3550                 settings._iDisplayStart = start;
3551         
3552                 if ( changed ) {
3553                         _fnCallbackFire( settings, null, 'page', [settings] );
3554         
3555                         if ( redraw ) {
3556                                 _fnDraw( settings );
3557                         }
3558                 }
3559         
3560                 return changed;
3561         }
3562         
3563         
3564         
3565         /**
3566          * Generate the node required for the processing node
3567          *  @param {object} settings dataTables settings object
3568          *  @returns {node} Processing element
3569          *  @memberof DataTable#oApi
3570          */
3571         function _fnFeatureHtmlProcessing ( settings )
3572         {
3573                 return $('<div/>', {
3574                                 'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
3575                                 'class': settings.oClasses.sProcessing
3576                         } )
3577                         .html( settings.oLanguage.sProcessing )
3578                         .insertBefore( settings.nTable )[0];
3579         }
3580         
3581         
3582         /**
3583          * Display or hide the processing indicator
3584          *  @param {object} settings dataTables settings object
3585          *  @param {bool} show Show the processing indicator (true) or not (false)
3586          *  @memberof DataTable#oApi
3587          */
3588         function _fnProcessingDisplay ( settings, show )
3589         {
3590                 if ( settings.oFeatures.bProcessing ) {
3591                         $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
3592                 }
3593         
3594                 _fnCallbackFire( settings, null, 'processing', [settings, show] );
3595         }
3596         
3597         /**
3598          * Add any control elements for the table - specifically scrolling
3599          *  @param {object} settings dataTables settings object
3600          *  @returns {node} Node to add to the DOM
3601          *  @memberof DataTable#oApi
3602          */
3603         function _fnFeatureHtmlTable ( settings )
3604         {
3605                 var table = $(settings.nTable);
3606         
3607                 // Add the ARIA grid role to the table
3608                 table.attr( 'role', 'grid' );
3609         
3610                 // Scrolling from here on in
3611                 var scroll = settings.oScroll;
3612         
3613                 if ( scroll.sX === '' && scroll.sY === '' ) {
3614                         return settings.nTable;
3615                 }
3616         
3617                 var scrollX = scroll.sX;
3618                 var scrollY = scroll.sY;
3619                 var classes = settings.oClasses;
3620                 var caption = table.children('caption');
3621                 var captionSide = caption.length ? caption[0]._captionSide : null;
3622                 var headerClone = $( table[0].cloneNode(false) );
3623                 var footerClone = $( table[0].cloneNode(false) );
3624                 var footer = table.children('tfoot');
3625                 var _div = '<div/>';
3626                 var size = function ( s ) {
3627                         return !s ? null : _fnStringToCss( s );
3628                 };
3629         
3630                 // This is fairly messy, but with x scrolling enabled, if the table has a
3631                 // width attribute, regardless of any width applied using the column width
3632                 // options, the browser will shrink or grow the table as needed to fit into
3633                 // that 100%. That would make the width options useless. So we remove it.
3634                 // This is okay, under the assumption that width:100% is applied to the
3635                 // table in CSS (it is in the default stylesheet) which will set the table
3636                 // width as appropriate (the attribute and css behave differently...)
3637                 if ( scroll.sX && table.attr('width') === '100%' ) {
3638                         table.removeAttr('width');
3639                 }
3640         
3641                 if ( ! footer.length ) {
3642                         footer = null;
3643                 }
3644         
3645                 /*
3646                  * The HTML structure that we want to generate in this function is:
3647                  *  div - scroller
3648                  *    div - scroll head
3649                  *      div - scroll head inner
3650                  *        table - scroll head table
3651                  *          thead - thead
3652                  *    div - scroll body
3653                  *      table - table (master table)
3654                  *        thead - thead clone for sizing
3655                  *        tbody - tbody
3656                  *    div - scroll foot
3657                  *      div - scroll foot inner
3658                  *        table - scroll foot table
3659                  *          tfoot - tfoot
3660                  */
3661                 var scroller = $( _div, { 'class': classes.sScrollWrapper } )
3662                         .append(
3663                                 $(_div, { 'class': classes.sScrollHead } )
3664                                         .css( {
3665                                                 overflow: 'hidden',
3666                                                 position: 'relative',
3667                                                 border: 0,
3668                                                 width: scrollX ? size(scrollX) : '100%'
3669                                         } )
3670                                         .append(
3671                                                 $(_div, { 'class': classes.sScrollHeadInner } )
3672                                                         .css( {
3673                                                                 'box-sizing': 'content-box',
3674                                                                 width: scroll.sXInner || '100%'
3675                                                         } )
3676                                                         .append(
3677                                                                 headerClone
3678                                                                         .removeAttr('id')
3679                                                                         .css( 'margin-left', 0 )
3680                                                                         .append( captionSide === 'top' ? caption : null )
3681                                                                         .append(
3682                                                                                 table.children('thead')
3683                                                                         )
3684                                                         )
3685                                         )
3686                         )
3687                         .append(
3688                                 $(_div, { 'class': classes.sScrollBody } )
3689                                         .css( {
3690                                                 overflow: 'auto',
3691                                                 height: size( scrollY ),
3692                                                 width: size( scrollX )
3693                                         } )
3694                                         .append( table )
3695                         );
3696         
3697                 if ( footer ) {
3698                         scroller.append(
3699                                 $(_div, { 'class': classes.sScrollFoot } )
3700                                         .css( {
3701                                                 overflow: 'hidden',
3702                                                 border: 0,
3703                                                 width: scrollX ? size(scrollX) : '100%'
3704                                         } )
3705                                         .append(
3706                                                 $(_div, { 'class': classes.sScrollFootInner } )
3707                                                         .append(
3708                                                                 footerClone
3709                                                                         .removeAttr('id')
3710                                                                         .css( 'margin-left', 0 )
3711                                                                         .append( captionSide === 'bottom' ? caption : null )
3712                                                                         .append(
3713                                                                                 table.children('tfoot')
3714                                                                         )
3715                                                         )
3716                                         )
3717                         );
3718                 }
3719         
3720                 var children = scroller.children();
3721                 var scrollHead = children[0];
3722                 var scrollBody = children[1];
3723                 var scrollFoot = footer ? children[2] : null;
3724         
3725                 // When the body is scrolled, then we also want to scroll the headers
3726                 if ( scrollX ) {
3727                         $(scrollBody).on( 'scroll.DT', function (e) {
3728                                 var scrollLeft = this.scrollLeft;
3729         
3730                                 scrollHead.scrollLeft = scrollLeft;
3731         
3732                                 if ( footer ) {
3733                                         scrollFoot.scrollLeft = scrollLeft;
3734                                 }
3735                         } );
3736                 }
3737         
3738                 settings.nScrollHead = scrollHead;
3739                 settings.nScrollBody = scrollBody;
3740                 settings.nScrollFoot = scrollFoot;
3741         
3742                 // On redraw - align columns
3743                 settings.aoDrawCallback.push( {
3744                         "fn": _fnScrollDraw,
3745                         "sName": "scrolling"
3746                 } );
3747         
3748                 return scroller[0];
3749         }
3750         
3751         
3752         
3753         /**
3754          * Update the header, footer and body tables for resizing - i.e. column
3755          * alignment.
3756          *
3757          * Welcome to the most horrible function DataTables. The process that this
3758          * function follows is basically:
3759          *   1. Re-create the table inside the scrolling div
3760          *   2. Take live measurements from the DOM
3761          *   3. Apply the measurements to align the columns
3762          *   4. Clean up
3763          *
3764          *  @param {object} settings dataTables settings object
3765          *  @memberof DataTable#oApi
3766          */
3767         function _fnScrollDraw ( settings )
3768         {
3769                 // Given that this is such a monster function, a lot of variables are use
3770                 // to try and keep the minimised size as small as possible
3771                 var
3772                         scroll         = settings.oScroll,
3773                         scrollX        = scroll.sX,
3774                         scrollXInner   = scroll.sXInner,
3775                         scrollY        = scroll.sY,
3776                         barWidth       = scroll.iBarWidth,
3777                         divHeader      = $(settings.nScrollHead),
3778                         divHeaderStyle = divHeader[0].style,
3779                         divHeaderInner = divHeader.children('div'),
3780                         divHeaderInnerStyle = divHeaderInner[0].style,
3781                         divHeaderTable = divHeaderInner.children('table'),
3782                         divBodyEl      = settings.nScrollBody,
3783                         divBody        = $(divBodyEl),
3784                         divBodyStyle   = divBodyEl.style,
3785                         divFooter      = $(settings.nScrollFoot),
3786                         divFooterInner = divFooter.children('div'),
3787                         divFooterTable = divFooterInner.children('table'),
3788                         header         = $(settings.nTHead),
3789                         table          = $(settings.nTable),
3790                         tableEl        = table[0],
3791                         tableStyle     = tableEl.style,
3792                         footer         = settings.nTFoot ? $(settings.nTFoot) : null,
3793                         browser        = settings.oBrowser,
3794                         ie67           = browser.bScrollOversize,
3795                         headerTrgEls, footerTrgEls,
3796                         headerSrcEls, footerSrcEls,
3797                         headerCopy, footerCopy,
3798                         headerWidths=[], footerWidths=[],
3799                         headerContent=[],
3800                         idx, correction, sanityWidth,
3801                         zeroOut = function(nSizer) {
3802                                 var style = nSizer.style;
3803                                 style.paddingTop = "0";
3804                                 style.paddingBottom = "0";
3805                                 style.borderTopWidth = "0";
3806                                 style.borderBottomWidth = "0";
3807                                 style.height = 0;
3808                         };
3809         
3810                 /*
3811                  * 1. Re-create the table inside the scrolling div
3812                  */
3813         
3814                 // Remove the old minimised thead and tfoot elements in the inner table
3815                 table.children('thead, tfoot').remove();
3816         
3817                 // Clone the current header and footer elements and then place it into the inner table
3818                 headerCopy = header.clone().prependTo( table );
3819                 headerTrgEls = header.find('tr'); // original header is in its own table
3820                 headerSrcEls = headerCopy.find('tr');
3821                 headerCopy.find('th, td').removeAttr('tabindex');
3822         
3823                 if ( footer ) {
3824                         footerCopy = footer.clone().prependTo( table );
3825                         footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
3826                         footerSrcEls = footerCopy.find('tr');
3827                 }
3828         
3829         
3830                 /*
3831                  * 2. Take live measurements from the DOM - do not alter the DOM itself!
3832                  */
3833         
3834                 // Remove old sizing and apply the calculated column widths
3835                 // Get the unique column headers in the newly created (cloned) header. We want to apply the
3836                 // calculated sizes to this header
3837                 if ( ! scrollX )
3838                 {
3839                         divBodyStyle.width = '100%';
3840                         divHeader[0].style.width = '100%';
3841                 }
3842         
3843                 $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
3844                         idx = _fnVisibleToColumnIndex( settings, i );
3845                         el.style.width = settings.aoColumns[idx].sWidth;
3846                 } );
3847         
3848                 if ( footer ) {
3849                         _fnApplyToChildren( function(n) {
3850                                 n.style.width = "";
3851                         }, footerSrcEls );
3852                 }
3853         
3854                 // If scroll collapse is enabled, when we put the headers back into the body for sizing, we
3855                 // will end up forcing the scrollbar to appear, making our measurements wrong for when we
3856                 // then hide it (end of this function), so add the header height to the body scroller.
3857                 if ( scroll.bCollapse && scrollY !== "" ) {
3858                         divBodyStyle.height = (divBody[0].offsetHeight + header[0].offsetHeight)+"px";
3859                 }
3860         
3861                 // Size the table as a whole
3862                 sanityWidth = table.outerWidth();
3863                 if ( scrollX === "" ) {
3864                         // No x scrolling
3865                         tableStyle.width = "100%";
3866         
3867                         // IE7 will make the width of the table when 100% include the scrollbar
3868                         // - which is shouldn't. When there is a scrollbar we need to take this
3869                         // into account.
3870                         if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
3871                                 divBody.css('overflow-y') == "scroll")
3872                         ) {
3873                                 tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
3874                         }
3875                 }
3876                 else
3877                 {
3878                         // x scrolling
3879                         if ( scrollXInner !== "" ) {
3880                                 // x scroll inner has been given - use it
3881                                 tableStyle.width = _fnStringToCss(scrollXInner);
3882                         }
3883                         else if ( sanityWidth == divBody.width() && divBody.height() < table.height() ) {
3884                                 // There is y-scrolling - try to take account of the y scroll bar
3885                                 tableStyle.width = _fnStringToCss( sanityWidth-barWidth );
3886                                 if ( table.outerWidth() > sanityWidth-barWidth ) {
3887                                         // Not possible to take account of it
3888                                         tableStyle.width = _fnStringToCss( sanityWidth );
3889                                 }
3890                         }
3891                         else {
3892                                 // When all else fails
3893                                 tableStyle.width = _fnStringToCss( sanityWidth );
3894                         }
3895                 }
3896         
3897                 // Recalculate the sanity width - now that we've applied the required width,
3898                 // before it was a temporary variable. This is required because the column
3899                 // width calculation is done before this table DOM is created.
3900                 sanityWidth = table.outerWidth();
3901         
3902                 // Hidden header should have zero height, so remove padding and borders. Then
3903                 // set the width based on the real headers
3904         
3905                 // Apply all styles in one pass
3906                 _fnApplyToChildren( zeroOut, headerSrcEls );
3907         
3908                 // Read all widths in next pass
3909                 _fnApplyToChildren( function(nSizer) {
3910                         headerContent.push( nSizer.innerHTML );
3911                         headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
3912                 }, headerSrcEls );
3913         
3914                 // Apply all widths in final pass
3915                 _fnApplyToChildren( function(nToSize, i) {
3916                         nToSize.style.width = headerWidths[i];
3917                 }, headerTrgEls );
3918         
3919                 $(headerSrcEls).height(0);
3920         
3921                 /* Same again with the footer if we have one */
3922                 if ( footer )
3923                 {
3924                         _fnApplyToChildren( zeroOut, footerSrcEls );
3925         
3926                         _fnApplyToChildren( function(nSizer) {
3927                                 footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
3928                         }, footerSrcEls );
3929         
3930                         _fnApplyToChildren( function(nToSize, i) {
3931                                 nToSize.style.width = footerWidths[i];
3932                         }, footerTrgEls );
3933         
3934                         $(footerSrcEls).height(0);
3935                 }
3936         
3937         
3938                 /*
3939                  * 3. Apply the measurements
3940                  */
3941         
3942                 // "Hide" the header and footer that we used for the sizing. We need to keep
3943                 // the content of the cell so that the width applied to the header and body
3944                 // both match, but we want to hide it completely. We want to also fix their
3945                 // width to what they currently are
3946                 _fnApplyToChildren( function(nSizer, i) {
3947                         nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
3948                         nSizer.style.width = headerWidths[i];
3949                 }, headerSrcEls );
3950         
3951                 if ( footer )
3952                 {
3953                         _fnApplyToChildren( function(nSizer, i) {
3954                                 nSizer.innerHTML = "";
3955                                 nSizer.style.width = footerWidths[i];
3956                         }, footerSrcEls );
3957                 }
3958         
3959                 // Sanity check that the table is of a sensible width. If not then we are going to get
3960                 // misalignment - try to prevent this by not allowing the table to shrink below its min width
3961                 if ( table.outerWidth() < sanityWidth )
3962                 {
3963                         // The min width depends upon if we have a vertical scrollbar visible or not */
3964                         correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
3965                                 divBody.css('overflow-y') == "scroll")) ?
3966                                         sanityWidth+barWidth :
3967                                         sanityWidth;
3968         
3969                         // IE6/7 are a law unto themselves...
3970                         if ( ie67 && (divBodyEl.scrollHeight >
3971                                 divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
3972                         ) {
3973                                 tableStyle.width = _fnStringToCss( correction-barWidth );
3974                         }
3975         
3976                         // And give the user a warning that we've stopped the table getting too small
3977                         if ( scrollX === "" || scrollXInner !== "" ) {
3978                                 _fnLog( settings, 1, 'Possible column misalignment', 6 );
3979                         }
3980                 }
3981                 else
3982                 {
3983                         correction = '100%';
3984                 }
3985         
3986                 // Apply to the container elements
3987                 divBodyStyle.width = _fnStringToCss( correction );
3988                 divHeaderStyle.width = _fnStringToCss( correction );
3989         
3990                 if ( footer ) {
3991                         settings.nScrollFoot.style.width = _fnStringToCss( correction );
3992                 }
3993         
3994         
3995                 /*
3996                  * 4. Clean up
3997                  */
3998                 if ( ! scrollY ) {
3999                         /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
4000                          * the scrollbar height from the visible display, rather than adding it on. We need to
4001                          * set the height in order to sort this. Don't want to do it in any other browsers.
4002                          */
4003                         if ( ie67 ) {
4004                                 divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
4005                         }
4006                 }
4007         
4008                 if ( scrollY && scroll.bCollapse ) {
4009                         divBodyStyle.height = _fnStringToCss( scrollY );
4010         
4011                         var iExtra = (scrollX && tableEl.offsetWidth > divBodyEl.offsetWidth) ?
4012                                 barWidth :
4013                                 0;
4014         
4015                         if ( tableEl.offsetHeight < divBodyEl.offsetHeight ) {
4016                                 divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+iExtra );
4017                         }
4018                 }
4019         
4020                 /* Finally set the width's of the header and footer tables */
4021                 var iOuterWidth = table.outerWidth();
4022                 divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
4023                 divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
4024         
4025                 // Figure out if there are scrollbar present - if so then we need a the header and footer to
4026                 // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
4027                 var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
4028                 var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
4029                 divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
4030         
4031                 if ( footer ) {
4032                         divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
4033                         divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
4034                         divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
4035                 }
4036         
4037                 /* Adjust the position of the header in case we loose the y-scrollbar */
4038                 divBody.scroll();
4039         
4040                 // If sorting or filtering has occurred, jump the scrolling back to the top
4041                 // only if we aren't holding the position
4042                 if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
4043                         divBodyEl.scrollTop = 0;
4044                 }
4045         }
4046         
4047         
4048         
4049         /**
4050          * Apply a given function to the display child nodes of an element array (typically
4051          * TD children of TR rows
4052          *  @param {function} fn Method to apply to the objects
4053          *  @param array {nodes} an1 List of elements to look through for display children
4054          *  @param array {nodes} an2 Another list (identical structure to the first) - optional
4055          *  @memberof DataTable#oApi
4056          */
4057         function _fnApplyToChildren( fn, an1, an2 )
4058         {
4059                 var index=0, i=0, iLen=an1.length;
4060                 var nNode1, nNode2;
4061         
4062                 while ( i < iLen ) {
4063                         nNode1 = an1[i].firstChild;
4064                         nNode2 = an2 ? an2[i].firstChild : null;
4065         
4066                         while ( nNode1 ) {
4067                                 if ( nNode1.nodeType === 1 ) {
4068                                         if ( an2 ) {
4069                                                 fn( nNode1, nNode2, index );
4070                                         }
4071                                         else {
4072                                                 fn( nNode1, index );
4073                                         }
4074         
4075                                         index++;
4076                                 }
4077         
4078                                 nNode1 = nNode1.nextSibling;
4079                                 nNode2 = an2 ? nNode2.nextSibling : null;
4080                         }
4081         
4082                         i++;
4083                 }
4084         }
4085         
4086         
4087         
4088         var __re_html_remove = /<.*?>/g;
4089         
4090         
4091         /**
4092          * Calculate the width of columns for the table
4093          *  @param {object} oSettings dataTables settings object
4094          *  @memberof DataTable#oApi
4095          */
4096         function _fnCalculateColumnWidths ( oSettings )
4097         {
4098                 var
4099                         table = oSettings.nTable,
4100                         columns = oSettings.aoColumns,
4101                         scroll = oSettings.oScroll,
4102                         scrollY = scroll.sY,
4103                         scrollX = scroll.sX,
4104                         scrollXInner = scroll.sXInner,
4105                         columnCount = columns.length,
4106                         visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
4107                         headerCells = $('th', oSettings.nTHead),
4108                         tableWidthAttr = table.getAttribute('width'), // from DOM element
4109                         tableContainer = table.parentNode,
4110                         userInputs = false,
4111                         i, column, columnIdx, width, outerWidth;
4112         
4113                 var styleWidth = table.style.width;
4114                 if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
4115                         tableWidthAttr = styleWidth;
4116                 }
4117         
4118                 /* Convert any user input sizes into pixel sizes */
4119                 for ( i=0 ; i<visibleColumns.length ; i++ ) {
4120                         column = columns[ visibleColumns[i] ];
4121         
4122                         if ( column.sWidth !== null ) {
4123                                 column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
4124         
4125                                 userInputs = true;
4126                         }
4127                 }
4128         
4129                 /* If the number of columns in the DOM equals the number that we have to
4130                  * process in DataTables, then we can use the offsets that are created by
4131                  * the web- browser. No custom sizes can be set in order for this to happen,
4132                  * nor scrolling used
4133                  */
4134                 if ( ! userInputs && ! scrollX && ! scrollY &&
4135                     columnCount == _fnVisbleColumns( oSettings ) &&
4136                         columnCount == headerCells.length
4137                 ) {
4138                         for ( i=0 ; i<columnCount ; i++ ) {
4139                                 columns[i].sWidth = _fnStringToCss( headerCells.eq(i).width() );
4140                         }
4141                 }
4142                 else
4143                 {
4144                         // Otherwise construct a single row, worst case, table with the widest
4145                         // node in the data, assign any user defined widths, then insert it into
4146                         // the DOM and allow the browser to do all the hard work of calculating
4147                         // table widths
4148                         var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
4149                                 .css( 'visibility', 'hidden' )
4150                                 .removeAttr( 'id' );
4151         
4152                         // Clean up the table body
4153                         tmpTable.find('tbody tr').remove();
4154                         var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
4155         
4156                         // Remove any assigned widths from the footer (from scrolling)
4157                         tmpTable.find('tfoot th, tfoot td').css('width', '');
4158         
4159                         // Apply custom sizing to the cloned header
4160                         headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
4161         
4162                         for ( i=0 ; i<visibleColumns.length ; i++ ) {
4163                                 column = columns[ visibleColumns[i] ];
4164         
4165                                 headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
4166                                         _fnStringToCss( column.sWidthOrig ) :
4167                                         '';
4168                         }
4169         
4170                         // Find the widest cell for each column and put it into the table
4171                         if ( oSettings.aoData.length ) {
4172                                 for ( i=0 ; i<visibleColumns.length ; i++ ) {
4173                                         columnIdx = visibleColumns[i];
4174                                         column = columns[ columnIdx ];
4175         
4176                                         $( _fnGetWidestNode( oSettings, columnIdx ) )
4177                                                 .clone( false )
4178                                                 .append( column.sContentPadding )
4179                                                 .appendTo( tr );
4180                                 }
4181                         }
4182         
4183                         // Table has been built, attach to the document so we can work with it
4184                         tmpTable.appendTo( tableContainer );
4185         
4186                         // When scrolling (X or Y) we want to set the width of the table as 
4187                         // appropriate. However, when not scrolling leave the table width as it
4188                         // is. This results in slightly different, but I think correct behaviour
4189                         if ( scrollX && scrollXInner ) {
4190                                 tmpTable.width( scrollXInner );
4191                         }
4192                         else if ( scrollX ) {
4193                                 tmpTable.css( 'width', 'auto' );
4194         
4195                                 if ( tmpTable.width() < tableContainer.offsetWidth ) {
4196                                         tmpTable.width( tableContainer.offsetWidth );
4197                                 }
4198                         }
4199                         else if ( scrollY ) {
4200                                 tmpTable.width( tableContainer.offsetWidth );
4201                         }
4202                         else if ( tableWidthAttr ) {
4203                                 tmpTable.width( tableWidthAttr );
4204                         }
4205         
4206                         // Take into account the y scrollbar
4207                         _fnScrollingWidthAdjust( oSettings, tmpTable[0] );
4208         
4209                         // Browsers need a bit of a hand when a width is assigned to any columns
4210                         // when x-scrolling as they tend to collapse the table to the min-width,
4211                         // even if we sent the column widths. So we need to keep track of what
4212                         // the table width should be by summing the user given values, and the
4213                         // automatic values
4214                         if ( scrollX )
4215                         {
4216                                 var total = 0;
4217         
4218                                 for ( i=0 ; i<visibleColumns.length ; i++ ) {
4219                                         column = columns[ visibleColumns[i] ];
4220                                         outerWidth = $(headerCells[i]).outerWidth();
4221         
4222                                         total += column.sWidthOrig === null ?
4223                                                 outerWidth :
4224                                                 parseInt( column.sWidth, 10 ) + outerWidth - $(headerCells[i]).width();
4225                                 }
4226         
4227                                 tmpTable.width( _fnStringToCss( total ) );
4228                                 table.style.width = _fnStringToCss( total );
4229                         }
4230         
4231                         // Get the width of each column in the constructed table
4232                         for ( i=0 ; i<visibleColumns.length ; i++ ) {
4233                                 column = columns[ visibleColumns[i] ];
4234                                 width = $(headerCells[i]).width();
4235         
4236                                 if ( width ) {
4237                                         column.sWidth = _fnStringToCss( width );
4238                                 }
4239                         }
4240         
4241                         table.style.width = _fnStringToCss( tmpTable.css('width') );
4242         
4243                         // Finished with the table - ditch it
4244                         tmpTable.remove();
4245                 }
4246         
4247                 // If there is a width attr, we want to attach an event listener which
4248                 // allows the table sizing to automatically adjust when the window is
4249                 // resized. Use the width attr rather than CSS, since we can't know if the
4250                 // CSS is a relative value or absolute - DOM read is always px.
4251                 if ( tableWidthAttr ) {
4252                         table.style.width = _fnStringToCss( tableWidthAttr );
4253                 }
4254         
4255                 if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
4256                         var bindResize = function () {
4257                                 $(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
4258                                         _fnAdjustColumnSizing( oSettings );
4259                                 } ) );
4260                         };
4261         
4262                         // IE6/7 will crash if we bind a resize event handler on page load.
4263                         // To be removed in 1.11 which drops IE6/7 support
4264                         if ( oSettings.oBrowser.bScrollOversize ) {
4265                                 setTimeout( bindResize, 1000 );
4266                         }
4267                         else {
4268                                 bindResize();
4269                         }
4270         
4271                         oSettings._reszEvt = true;
4272                 }
4273         }
4274         
4275         
4276         /**
4277          * Throttle the calls to a function. Arguments and context are maintained for
4278          * the throttled function
4279          *  @param {function} fn Function to be called
4280          *  @param {int} [freq=200] call frequency in mS
4281          *  @returns {function} wrapped function
4282          *  @memberof DataTable#oApi
4283          */
4284         function _fnThrottle( fn, freq ) {
4285                 var
4286                         frequency = freq !== undefined ? freq : 200,
4287                         last,
4288                         timer;
4289         
4290                 return function () {
4291                         var
4292                                 that = this,
4293                                 now  = +new Date(),
4294                                 args = arguments;
4295         
4296                         if ( last && now < last + frequency ) {
4297                                 clearTimeout( timer );
4298         
4299                                 timer = setTimeout( function () {
4300                                         last = undefined;
4301                                         fn.apply( that, args );
4302                                 }, frequency );
4303                         }
4304                         else {
4305                                 last = now;
4306                                 fn.apply( that, args );
4307                         }
4308                 };
4309         }
4310         
4311         
4312         /**
4313          * Convert a CSS unit width to pixels (e.g. 2em)
4314          *  @param {string} width width to be converted
4315          *  @param {node} parent parent to get the with for (required for relative widths) - optional
4316          *  @returns {int} width in pixels
4317          *  @memberof DataTable#oApi
4318          */
4319         function _fnConvertToWidth ( width, parent )
4320         {
4321                 if ( ! width ) {
4322                         return 0;
4323                 }
4324         
4325                 var n = $('<div/>')
4326                         .css( 'width', _fnStringToCss( width ) )
4327                         .appendTo( parent || document.body );
4328         
4329                 var val = n[0].offsetWidth;
4330                 n.remove();
4331         
4332                 return val;
4333         }
4334         
4335         
4336         /**
4337          * Adjust a table's width to take account of vertical scroll bar
4338          *  @param {object} oSettings dataTables settings object
4339          *  @param {node} n table node
4340          *  @memberof DataTable#oApi
4341          */
4342         
4343         function _fnScrollingWidthAdjust ( settings, n )
4344         {
4345                 var scroll = settings.oScroll;
4346         
4347                 if ( scroll.sX || scroll.sY ) {
4348                         // When y-scrolling only, we want to remove the width of the scroll bar
4349                         // so the table + scroll bar will fit into the area available, otherwise
4350                         // we fix the table at its current size with no adjustment
4351                         var correction = ! scroll.sX ? scroll.iBarWidth : 0;
4352                         n.style.width = _fnStringToCss( $(n).outerWidth() - correction );
4353                 }
4354         }
4355         
4356         
4357         /**
4358          * Get the widest node
4359          *  @param {object} settings dataTables settings object
4360          *  @param {int} colIdx column of interest
4361          *  @returns {node} widest table node
4362          *  @memberof DataTable#oApi
4363          */
4364         function _fnGetWidestNode( settings, colIdx )
4365         {
4366                 var idx = _fnGetMaxLenString( settings, colIdx );
4367                 if ( idx < 0 ) {
4368                         return null;
4369                 }
4370         
4371                 var data = settings.aoData[ idx ];
4372                 return ! data.nTr ? // Might not have been created when deferred rendering
4373                         $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
4374                         data.anCells[ colIdx ];
4375         }
4376         
4377         
4378         /**
4379          * Get the maximum strlen for each data column
4380          *  @param {object} settings dataTables settings object
4381          *  @param {int} colIdx column of interest
4382          *  @returns {string} max string length for each column
4383          *  @memberof DataTable#oApi
4384          */
4385         function _fnGetMaxLenString( settings, colIdx )
4386         {
4387                 var s, max=-1, maxIdx = -1;
4388         
4389                 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4390                         s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
4391                         s = s.replace( __re_html_remove, '' );
4392         
4393                         if ( s.length > max ) {
4394                                 max = s.length;
4395                                 maxIdx = i;
4396                         }
4397                 }
4398         
4399                 return maxIdx;
4400         }
4401         
4402         
4403         /**
4404          * Append a CSS unit (only if required) to a string
4405          *  @param {string} value to css-ify
4406          *  @returns {string} value with css unit
4407          *  @memberof DataTable#oApi
4408          */
4409         function _fnStringToCss( s )
4410         {
4411                 if ( s === null ) {
4412                         return '0px';
4413                 }
4414         
4415                 if ( typeof s == 'number' ) {
4416                         return s < 0 ?
4417                                 '0px' :
4418                                 s+'px';
4419                 }
4420         
4421                 // Check it has a unit character already
4422                 return s.match(/\d$/) ?
4423                         s+'px' :
4424                         s;
4425         }
4426         
4427         
4428         /**
4429          * Get the width of a scroll bar in this browser being used
4430          *  @returns {int} width in pixels
4431          *  @memberof DataTable#oApi
4432          */
4433         function _fnScrollBarWidth ()
4434         {
4435                 // On first run a static variable is set, since this is only needed once.
4436                 // Subsequent runs will just use the previously calculated value
4437                 var width = DataTable.__scrollbarWidth;
4438         
4439                 if ( width === undefined ) {
4440                         var sizer = $('<p/>').css( {
4441                                         position: 'absolute',
4442                                         top: 0,
4443                                         left: 0,
4444                                         width: '100%',
4445                                         height: 150,
4446                                         padding: 0,
4447                                         overflow: 'scroll',
4448                                         visibility: 'hidden'
4449                                 } )
4450                                 .appendTo('body');
4451         
4452                         width = sizer[0].offsetWidth - sizer[0].clientWidth;
4453                         DataTable.__scrollbarWidth = width;
4454         
4455                         sizer.remove();
4456                 }
4457         
4458                 return width;
4459         }
4460         
4461         
4462         
4463         function _fnSortFlatten ( settings )
4464         {
4465                 var
4466                         i, iLen, k, kLen,
4467                         aSort = [],
4468                         aiOrig = [],
4469                         aoColumns = settings.aoColumns,
4470                         aDataSort, iCol, sType, srcCol,
4471                         fixed = settings.aaSortingFixed,
4472                         fixedObj = $.isPlainObject( fixed ),
4473                         nestedSort = [],
4474                         add = function ( a ) {
4475                                 if ( a.length && ! $.isArray( a[0] ) ) {
4476                                         // 1D array
4477                                         nestedSort.push( a );
4478                                 }
4479                                 else {
4480                                         // 2D array
4481                                         nestedSort.push.apply( nestedSort, a );
4482                                 }
4483                         };
4484         
4485                 // Build the sort array, with pre-fix and post-fix options if they have been
4486                 // specified
4487                 if ( $.isArray( fixed ) ) {
4488                         add( fixed );
4489                 }
4490         
4491                 if ( fixedObj && fixed.pre ) {
4492                         add( fixed.pre );
4493                 }
4494         
4495                 add( settings.aaSorting );
4496         
4497                 if (fixedObj && fixed.post ) {
4498                         add( fixed.post );
4499                 }
4500         
4501                 for ( i=0 ; i<nestedSort.length ; i++ )
4502                 {
4503                         srcCol = nestedSort[i][0];
4504                         aDataSort = aoColumns[ srcCol ].aDataSort;
4505         
4506                         for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
4507                         {
4508                                 iCol = aDataSort[k];
4509                                 sType = aoColumns[ iCol ].sType || 'string';
4510         
4511                                 if ( nestedSort[i]._idx === undefined ) {
4512                                         nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
4513                                 }
4514         
4515                                 aSort.push( {
4516                                         src:       srcCol,
4517                                         col:       iCol,
4518                                         dir:       nestedSort[i][1],
4519                                         index:     nestedSort[i]._idx,
4520                                         type:      sType,
4521                                         formatter: DataTable.ext.type.order[ sType+"-pre" ]
4522                                 } );
4523                         }
4524                 }
4525         
4526                 return aSort;
4527         }
4528         
4529         /**
4530          * Change the order of the table
4531          *  @param {object} oSettings dataTables settings object
4532          *  @memberof DataTable#oApi
4533          *  @todo This really needs split up!
4534          */
4535         function _fnSort ( oSettings )
4536         {
4537                 var
4538                         i, ien, iLen, j, jLen, k, kLen,
4539                         sDataType, nTh,
4540                         aiOrig = [],
4541                         oExtSort = DataTable.ext.type.order,
4542                         aoData = oSettings.aoData,
4543                         aoColumns = oSettings.aoColumns,
4544                         aDataSort, data, iCol, sType, oSort,
4545                         formatters = 0,
4546                         sortCol,
4547                         displayMaster = oSettings.aiDisplayMaster,
4548                         aSort;
4549         
4550                 // Resolve any column types that are unknown due to addition or invalidation
4551                 // @todo Can this be moved into a 'data-ready' handler which is called when
4552                 //   data is going to be used in the table?
4553                 _fnColumnTypes( oSettings );
4554         
4555                 aSort = _fnSortFlatten( oSettings );
4556         
4557                 for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
4558                         sortCol = aSort[i];
4559         
4560                         // Track if we can use the fast sort algorithm
4561                         if ( sortCol.formatter ) {
4562                                 formatters++;
4563                         }
4564         
4565                         // Load the data needed for the sort, for each cell
4566                         _fnSortData( oSettings, sortCol.col );
4567                 }
4568         
4569                 /* No sorting required if server-side or no sorting array */
4570                 if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
4571                 {
4572                         // Create a value - key array of the current row positions such that we can use their
4573                         // current position during the sort, if values match, in order to perform stable sorting
4574                         for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
4575                                 aiOrig[ displayMaster[i] ] = i;
4576                         }
4577         
4578                         /* Do the sort - here we want multi-column sorting based on a given data source (column)
4579                          * and sorting function (from oSort) in a certain direction. It's reasonably complex to
4580                          * follow on it's own, but this is what we want (example two column sorting):
4581                          *  fnLocalSorting = function(a,b){
4582                          *    var iTest;
4583                          *    iTest = oSort['string-asc']('data11', 'data12');
4584                          *      if (iTest !== 0)
4585                          *        return iTest;
4586                          *    iTest = oSort['numeric-desc']('data21', 'data22');
4587                          *    if (iTest !== 0)
4588                          *      return iTest;
4589                          *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
4590                          *  }
4591                          * Basically we have a test for each sorting column, if the data in that column is equal,
4592                          * test the next column. If all columns match, then we use a numeric sort on the row
4593                          * positions in the original data array to provide a stable sort.
4594                          *
4595                          * Note - I know it seems excessive to have two sorting methods, but the first is around
4596                          * 15% faster, so the second is only maintained for backwards compatibility with sorting
4597                          * methods which do not have a pre-sort formatting function.
4598                          */
4599                         if ( formatters === aSort.length ) {
4600                                 // All sort types have formatting functions
4601                                 displayMaster.sort( function ( a, b ) {
4602                                         var
4603                                                 x, y, k, test, sort,
4604                                                 len=aSort.length,
4605                                                 dataA = aoData[a]._aSortData,
4606                                                 dataB = aoData[b]._aSortData;
4607         
4608                                         for ( k=0 ; k<len ; k++ ) {
4609                                                 sort = aSort[k];
4610         
4611                                                 x = dataA[ sort.col ];
4612                                                 y = dataB[ sort.col ];
4613         
4614                                                 test = x<y ? -1 : x>y ? 1 : 0;
4615                                                 if ( test !== 0 ) {
4616                                                         return sort.dir === 'asc' ? test : -test;
4617                                                 }
4618                                         }
4619         
4620                                         x = aiOrig[a];
4621                                         y = aiOrig[b];
4622                                         return x<y ? -1 : x>y ? 1 : 0;
4623                                 } );
4624                         }
4625                         else {
4626                                 // Depreciated - remove in 1.11 (providing a plug-in option)
4627                                 // Not all sort types have formatting methods, so we have to call their sorting
4628                                 // methods.
4629                                 displayMaster.sort( function ( a, b ) {
4630                                         var
4631                                                 x, y, k, l, test, sort, fn,
4632                                                 len=aSort.length,
4633                                                 dataA = aoData[a]._aSortData,
4634                                                 dataB = aoData[b]._aSortData;
4635         
4636                                         for ( k=0 ; k<len ; k++ ) {
4637                                                 sort = aSort[k];
4638         
4639                                                 x = dataA[ sort.col ];
4640                                                 y = dataB[ sort.col ];
4641         
4642                                                 fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
4643                                                 test = fn( x, y );
4644                                                 if ( test !== 0 ) {
4645                                                         return test;
4646                                                 }
4647                                         }
4648         
4649                                         x = aiOrig[a];
4650                                         y = aiOrig[b];
4651                                         return x<y ? -1 : x>y ? 1 : 0;
4652                                 } );
4653                         }
4654                 }
4655         
4656                 /* Tell the draw function that we have sorted the data */
4657                 oSettings.bSorted = true;
4658         }
4659         
4660         
4661         function _fnSortAria ( settings )
4662         {
4663                 var label;
4664                 var nextSort;
4665                 var columns = settings.aoColumns;
4666                 var aSort = _fnSortFlatten( settings );
4667                 var oAria = settings.oLanguage.oAria;
4668         
4669                 // ARIA attributes - need to loop all columns, to update all (removing old
4670                 // attributes as needed)
4671                 for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
4672                 {
4673                         var col = columns[i];
4674                         var asSorting = col.asSorting;
4675                         var sTitle = col.sTitle.replace( /<.*?>/g, "" );
4676                         var th = col.nTh;
4677         
4678                         // IE7 is throwing an error when setting these properties with jQuery's
4679                         // attr() and removeAttr() methods...
4680                         th.removeAttribute('aria-sort');
4681         
4682                         /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
4683                         if ( col.bSortable ) {
4684                                 if ( aSort.length > 0 && aSort[0].col == i ) {
4685                                         th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
4686                                         nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
4687                                 }
4688                                 else {
4689                                         nextSort = asSorting[0];
4690                                 }
4691         
4692                                 label = sTitle + ( nextSort === "asc" ?
4693                                         oAria.sSortAscending :
4694                                         oAria.sSortDescending
4695                                 );
4696                         }
4697                         else {
4698                                 label = sTitle;
4699                         }
4700         
4701                         th.setAttribute('aria-label', label);
4702                 }
4703         }
4704         
4705         
4706         /**
4707          * Function to run on user sort request
4708          *  @param {object} settings dataTables settings object
4709          *  @param {node} attachTo node to attach the handler to
4710          *  @param {int} colIdx column sorting index
4711          *  @param {boolean} [append=false] Append the requested sort to the existing
4712          *    sort if true (i.e. multi-column sort)
4713          *  @param {function} [callback] callback function
4714          *  @memberof DataTable#oApi
4715          */
4716         function _fnSortListener ( settings, colIdx, append, callback )
4717         {
4718                 var col = settings.aoColumns[ colIdx ];
4719                 var sorting = settings.aaSorting;
4720                 var asSorting = col.asSorting;
4721                 var nextSortIdx;
4722                 var next = function ( a, overflow ) {
4723                         var idx = a._idx;
4724                         if ( idx === undefined ) {
4725                                 idx = $.inArray( a[1], asSorting );
4726                         }
4727         
4728                         return idx+1 < asSorting.length ?
4729                                 idx+1 :
4730                                 overflow ?
4731                                         null :
4732                                         0;
4733                 };
4734         
4735                 // Convert to 2D array if needed
4736                 if ( typeof sorting[0] === 'number' ) {
4737                         sorting = settings.aaSorting = [ sorting ];
4738                 }
4739         
4740                 // If appending the sort then we are multi-column sorting
4741                 if ( append && settings.oFeatures.bSortMulti ) {
4742                         // Are we already doing some kind of sort on this column?
4743                         var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
4744         
4745                         if ( sortIdx !== -1 ) {
4746                                 // Yes, modify the sort
4747                                 nextSortIdx = next( sorting[sortIdx], true );
4748         
4749                                 if ( nextSortIdx === null && sorting.length === 1 ) {
4750                                         nextSortIdx = 0; // can't remove sorting completely
4751                                 }
4752         
4753                                 if ( nextSortIdx === null ) {
4754                                         sorting.splice( sortIdx, 1 );
4755                                 }
4756                                 else {
4757                                         sorting[sortIdx][1] = asSorting[ nextSortIdx ];
4758                                         sorting[sortIdx]._idx = nextSortIdx;
4759                                 }
4760                         }
4761                         else {
4762                                 // No sort on this column yet
4763                                 sorting.push( [ colIdx, asSorting[0], 0 ] );
4764                                 sorting[sorting.length-1]._idx = 0;
4765                         }
4766                 }
4767                 else if ( sorting.length && sorting[0][0] == colIdx ) {
4768                         // Single column - already sorting on this column, modify the sort
4769                         nextSortIdx = next( sorting[0] );
4770         
4771                         sorting.length = 1;
4772                         sorting[0][1] = asSorting[ nextSortIdx ];
4773                         sorting[0]._idx = nextSortIdx;
4774                 }
4775                 else {
4776                         // Single column - sort only on this column
4777                         sorting.length = 0;
4778                         sorting.push( [ colIdx, asSorting[0] ] );
4779                         sorting[0]._idx = 0;
4780                 }
4781         
4782                 // Run the sort by calling a full redraw
4783                 _fnReDraw( settings );
4784         
4785                 // callback used for async user interaction
4786                 if ( typeof callback == 'function' ) {
4787                         callback( settings );
4788                 }
4789         }
4790         
4791         
4792         /**
4793          * Attach a sort handler (click) to a node
4794          *  @param {object} settings dataTables settings object
4795          *  @param {node} attachTo node to attach the handler to
4796          *  @param {int} colIdx column sorting index
4797          *  @param {function} [callback] callback function
4798          *  @memberof DataTable#oApi
4799          */
4800         function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
4801         {
4802                 var col = settings.aoColumns[ colIdx ];
4803         
4804                 _fnBindAction( attachTo, {}, function (e) {
4805                         /* If the column is not sortable - don't to anything */
4806                         if ( col.bSortable === false ) {
4807                                 return;
4808                         }
4809         
4810                         // If processing is enabled use a timeout to allow the processing
4811                         // display to be shown - otherwise to it synchronously
4812                         if ( settings.oFeatures.bProcessing ) {
4813                                 _fnProcessingDisplay( settings, true );
4814         
4815                                 setTimeout( function() {
4816                                         _fnSortListener( settings, colIdx, e.shiftKey, callback );
4817         
4818                                         // In server-side processing, the draw callback will remove the
4819                                         // processing display
4820                                         if ( _fnDataSource( settings ) !== 'ssp' ) {
4821                                                 _fnProcessingDisplay( settings, false );
4822                                         }
4823                                 }, 0 );
4824                         }
4825                         else {
4826                                 _fnSortListener( settings, colIdx, e.shiftKey, callback );
4827                         }
4828                 } );
4829         }
4830         
4831         
4832         /**
4833          * Set the sorting classes on table's body, Note: it is safe to call this function
4834          * when bSort and bSortClasses are false
4835          *  @param {object} oSettings dataTables settings object
4836          *  @memberof DataTable#oApi
4837          */
4838         function _fnSortingClasses( settings )
4839         {
4840                 var oldSort = settings.aLastSort;
4841                 var sortClass = settings.oClasses.sSortColumn;
4842                 var sort = _fnSortFlatten( settings );
4843                 var features = settings.oFeatures;
4844                 var i, ien, colIdx;
4845         
4846                 if ( features.bSort && features.bSortClasses ) {
4847                         // Remove old sorting classes
4848                         for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
4849                                 colIdx = oldSort[i].src;
4850         
4851                                 // Remove column sorting
4852                                 $( _pluck( settings.aoData, 'anCells', colIdx ) )
4853                                         .removeClass( sortClass + (i<2 ? i+1 : 3) );
4854                         }
4855         
4856                         // Add new column sorting
4857                         for ( i=0, ien=sort.length ; i<ien ; i++ ) {
4858                                 colIdx = sort[i].src;
4859         
4860                                 $( _pluck( settings.aoData, 'anCells', colIdx ) )
4861                                         .addClass( sortClass + (i<2 ? i+1 : 3) );
4862                         }
4863                 }
4864         
4865                 settings.aLastSort = sort;
4866         }
4867         
4868         
4869         // Get the data to sort a column, be it from cache, fresh (populating the
4870         // cache), or from a sort formatter
4871         function _fnSortData( settings, idx )
4872         {
4873                 // Custom sorting function - provided by the sort data type
4874                 var column = settings.aoColumns[ idx ];
4875                 var customSort = DataTable.ext.order[ column.sSortDataType ];
4876                 var customData;
4877         
4878                 if ( customSort ) {
4879                         customData = customSort.call( settings.oInstance, settings, idx,
4880                                 _fnColumnIndexToVisible( settings, idx )
4881                         );
4882                 }
4883         
4884                 // Use / populate cache
4885                 var row, cellData;
4886                 var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
4887         
4888                 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4889                         row = settings.aoData[i];
4890         
4891                         if ( ! row._aSortData ) {
4892                                 row._aSortData = [];
4893                         }
4894         
4895                         if ( ! row._aSortData[idx] || customSort ) {
4896                                 cellData = customSort ?
4897                                         customData[i] : // If there was a custom sort function, use data from there
4898                                         _fnGetCellData( settings, i, idx, 'sort' );
4899         
4900                                 row._aSortData[ idx ] = formatter ?
4901                                         formatter( cellData ) :
4902                                         cellData;
4903                         }
4904                 }
4905         }
4906         
4907         
4908         
4909         /**
4910          * Save the state of a table
4911          *  @param {object} oSettings dataTables settings object
4912          *  @memberof DataTable#oApi
4913          */
4914         function _fnSaveState ( settings )
4915         {
4916                 if ( !settings.oFeatures.bStateSave || settings.bDestroying )
4917                 {
4918                         return;
4919                 }
4920         
4921                 /* Store the interesting variables */
4922                 var state = {
4923                         time:    +new Date(),
4924                         start:   settings._iDisplayStart,
4925                         length:  settings._iDisplayLength,
4926                         order:   $.extend( true, [], settings.aaSorting ),
4927                         search:  _fnSearchToCamel( settings.oPreviousSearch ),
4928                         columns: $.map( settings.aoColumns, function ( col, i ) {
4929                                 return {
4930                                         visible: col.bVisible,
4931                                         search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
4932                                 };
4933                         } )
4934                 };
4935         
4936                 _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
4937         
4938                 settings.oSavedState = state;
4939                 settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
4940         }
4941         
4942         
4943         /**
4944          * Attempt to load a saved table state
4945          *  @param {object} oSettings dataTables settings object
4946          *  @param {object} oInit DataTables init object so we can override settings
4947          *  @memberof DataTable#oApi
4948          */
4949         function _fnLoadState ( settings, oInit )
4950         {
4951                 var i, ien;
4952                 var columns = settings.aoColumns;
4953         
4954                 if ( ! settings.oFeatures.bStateSave ) {
4955                         return;
4956                 }
4957         
4958                 var state = settings.fnStateLoadCallback.call( settings.oInstance, settings );
4959                 if ( ! state || ! state.time ) {
4960                         return;
4961                 }
4962         
4963                 /* Allow custom and plug-in manipulation functions to alter the saved data set and
4964                  * cancelling of loading by returning false
4965                  */
4966                 var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, state] );
4967                 if ( $.inArray( false, abStateLoad ) !== -1 ) {
4968                         return;
4969                 }
4970         
4971                 /* Reject old data */
4972                 var duration = settings.iStateDuration;
4973                 if ( duration > 0 && state.time < +new Date() - (duration*1000) ) {
4974                         return;
4975                 }
4976         
4977                 // Number of columns have changed - all bets are off, no restore of settings
4978                 if ( columns.length !== state.columns.length ) {
4979                         return;
4980                 }
4981         
4982                 // Store the saved state so it might be accessed at any time
4983                 settings.oLoadedState = $.extend( true, {}, state );
4984         
4985                 // Restore key features - todo - for 1.11 this needs to be done by
4986                 // subscribed events
4987                 if ( state.start !== undefined ) {
4988                         settings._iDisplayStart    = state.start;
4989                         settings.iInitDisplayStart = state.start;
4990                 }
4991                 if ( state.length !== undefined ) {
4992                         settings._iDisplayLength   = state.length;
4993                 }
4994         
4995                 // Order
4996                 if ( state.order !== undefined ) {
4997                         settings.aaSorting = [];
4998                         $.each( state.order, function ( i, col ) {
4999                                 settings.aaSorting.push( col[0] >= columns.length ?
5000                                         [ 0, col[1] ] :
5001                                         col
5002                                 );
5003                         } );
5004                 }
5005         
5006                 // Search
5007                 if ( state.search !== undefined ) {
5008                         $.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );
5009                 }
5010         
5011                 // Columns
5012                 for ( i=0, ien=state.columns.length ; i<ien ; i++ ) {
5013                         var col = state.columns[i];
5014         
5015                         // Visibility
5016                         if ( col.visible !== undefined ) {
5017                                 columns[i].bVisible = col.visible;
5018                         }
5019         
5020                         // Search
5021                         if ( col.search !== undefined ) {
5022                                 $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
5023                         }
5024                 }
5025         
5026                 _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] );
5027         }
5028         
5029         
5030         /**
5031          * Return the settings object for a particular table
5032          *  @param {node} table table we are using as a dataTable
5033          *  @returns {object} Settings object - or null if not found
5034          *  @memberof DataTable#oApi
5035          */
5036         function _fnSettingsFromNode ( table )
5037         {
5038                 var settings = DataTable.settings;
5039                 var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
5040         
5041                 return idx !== -1 ?
5042                         settings[ idx ] :
5043                         null;
5044         }
5045         
5046         
5047         /**
5048          * Log an error message
5049          *  @param {object} settings dataTables settings object
5050          *  @param {int} level log error messages, or display them to the user
5051          *  @param {string} msg error message
5052          *  @param {int} tn Technical note id to get more information about the error.
5053          *  @memberof DataTable#oApi
5054          */
5055         function _fnLog( settings, level, msg, tn )
5056         {
5057                 msg = 'DataTables warning: '+
5058                         (settings!==null ? 'table id='+settings.sTableId+' - ' : '')+msg;
5059         
5060                 if ( tn ) {
5061                         msg += '. For more information about this error, please see '+
5062                         'http://datatables.net/tn/'+tn;
5063                 }
5064         
5065                 if ( ! level  ) {
5066                         // Backwards compatibility pre 1.10
5067                         var ext = DataTable.ext;
5068                         var type = ext.sErrMode || ext.errMode;
5069         
5070                         _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
5071         
5072                         if ( type == 'alert' ) {
5073                                 alert( msg );
5074                         }
5075                         else if ( type == 'throw' ) {
5076                                 throw new Error(msg);
5077                         }
5078                         else if ( typeof type == 'function' ) {
5079                                 type( settings, tn, msg );
5080                         }
5081                 }
5082                 else if ( window.console && console.log ) {
5083                         console.log( msg );
5084                 }
5085         }
5086         
5087         
5088         /**
5089          * See if a property is defined on one object, if so assign it to the other object
5090          *  @param {object} ret target object
5091          *  @param {object} src source object
5092          *  @param {string} name property
5093          *  @param {string} [mappedName] name to map too - optional, name used if not given
5094          *  @memberof DataTable#oApi
5095          */
5096         function _fnMap( ret, src, name, mappedName )
5097         {
5098                 if ( $.isArray( name ) ) {
5099                         $.each( name, function (i, val) {
5100                                 if ( $.isArray( val ) ) {
5101                                         _fnMap( ret, src, val[0], val[1] );
5102                                 }
5103                                 else {
5104                                         _fnMap( ret, src, val );
5105                                 }
5106                         } );
5107         
5108                         return;
5109                 }
5110         
5111                 if ( mappedName === undefined ) {
5112                         mappedName = name;
5113                 }
5114         
5115                 if ( src[name] !== undefined ) {
5116                         ret[mappedName] = src[name];
5117                 }
5118         }
5119         
5120         
5121         /**
5122          * Extend objects - very similar to jQuery.extend, but deep copy objects, and
5123          * shallow copy arrays. The reason we need to do this, is that we don't want to
5124          * deep copy array init values (such as aaSorting) since the dev wouldn't be
5125          * able to override them, but we do want to deep copy arrays.
5126          *  @param {object} out Object to extend
5127          *  @param {object} extender Object from which the properties will be applied to
5128          *      out
5129          *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
5130          *      independent copy with the exception of the `data` or `aaData` parameters
5131          *      if they are present. This is so you can pass in a collection to
5132          *      DataTables and have that used as your data source without breaking the
5133          *      references
5134          *  @returns {object} out Reference, just for convenience - out === the return.
5135          *  @memberof DataTable#oApi
5136          *  @todo This doesn't take account of arrays inside the deep copied objects.
5137          */
5138         function _fnExtend( out, extender, breakRefs )
5139         {
5140                 var val;
5141         
5142                 for ( var prop in extender ) {
5143                         if ( extender.hasOwnProperty(prop) ) {
5144                                 val = extender[prop];
5145         
5146                                 if ( $.isPlainObject( val ) ) {
5147                                         if ( ! $.isPlainObject( out[prop] ) ) {
5148                                                 out[prop] = {};
5149                                         }
5150                                         $.extend( true, out[prop], val );
5151                                 }
5152                                 else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
5153                                         out[prop] = val.slice();
5154                                 }
5155                                 else {
5156                                         out[prop] = val;
5157                                 }
5158                         }
5159                 }
5160         
5161                 return out;
5162         }
5163         
5164         
5165         /**
5166          * Bind an event handers to allow a click or return key to activate the callback.
5167          * This is good for accessibility since a return on the keyboard will have the
5168          * same effect as a click, if the element has focus.
5169          *  @param {element} n Element to bind the action to
5170          *  @param {object} oData Data object to pass to the triggered function
5171          *  @param {function} fn Callback function for when the event is triggered
5172          *  @memberof DataTable#oApi
5173          */
5174         function _fnBindAction( n, oData, fn )
5175         {
5176                 $(n)
5177                         .bind( 'click.DT', oData, function (e) {
5178                                         n.blur(); // Remove focus outline for mouse users
5179                                         fn(e);
5180                                 } )
5181                         .bind( 'keypress.DT', oData, function (e){
5182                                         if ( e.which === 13 ) {
5183                                                 e.preventDefault();
5184                                                 fn(e);
5185                                         }
5186                                 } )
5187                         .bind( 'selectstart.DT', function () {
5188                                         /* Take the brutal approach to cancelling text selection */
5189                                         return false;
5190                                 } );
5191         }
5192         
5193         
5194         /**
5195          * Register a callback function. Easily allows a callback function to be added to
5196          * an array store of callback functions that can then all be called together.
5197          *  @param {object} oSettings dataTables settings object
5198          *  @param {string} sStore Name of the array storage for the callbacks in oSettings
5199          *  @param {function} fn Function to be called back
5200          *  @param {string} sName Identifying name for the callback (i.e. a label)
5201          *  @memberof DataTable#oApi
5202          */
5203         function _fnCallbackReg( oSettings, sStore, fn, sName )
5204         {
5205                 if ( fn )
5206                 {
5207                         oSettings[sStore].push( {
5208                                 "fn": fn,
5209                                 "sName": sName
5210                         } );
5211                 }
5212         }
5213         
5214         
5215         /**
5216          * Fire callback functions and trigger events. Note that the loop over the
5217          * callback array store is done backwards! Further note that you do not want to
5218          * fire off triggers in time sensitive applications (for example cell creation)
5219          * as its slow.
5220          *  @param {object} settings dataTables settings object
5221          *  @param {string} callbackArr Name of the array storage for the callbacks in
5222          *      oSettings
5223          *  @param {string} eventName Name of the jQuery custom event to trigger. If
5224          *      null no trigger is fired
5225          *  @param {array} args Array of arguments to pass to the callback function /
5226          *      trigger
5227          *  @memberof DataTable#oApi
5228          */
5229         function _fnCallbackFire( settings, callbackArr, eventName, args )
5230         {
5231                 var ret = [];
5232         
5233                 if ( callbackArr ) {
5234                         ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
5235                                 return val.fn.apply( settings.oInstance, args );
5236                         } );
5237                 }
5238         
5239                 if ( eventName !== null ) {
5240                         var e = $.Event( eventName+'.dt' );
5241         
5242                         $(settings.nTable).trigger( e, args );
5243         
5244                         ret.push( e.result );
5245                 }
5246         
5247                 return ret;
5248         }
5249         
5250         
5251         function _fnLengthOverflow ( settings )
5252         {
5253                 var
5254                         start = settings._iDisplayStart,
5255                         end = settings.fnDisplayEnd(),
5256                         len = settings._iDisplayLength;
5257         
5258                 /* If we have space to show extra rows (backing up from the end point - then do so */
5259                 if ( start >= end )
5260                 {
5261                         start = end - len;
5262                 }
5263         
5264                 // Keep the start record on the current page
5265                 start -= (start % len);
5266         
5267                 if ( len === -1 || start < 0 )
5268                 {
5269                         start = 0;
5270                 }
5271         
5272                 settings._iDisplayStart = start;
5273         }
5274         
5275         
5276         function _fnRenderer( settings, type )
5277         {
5278                 var renderer = settings.renderer;
5279                 var host = DataTable.ext.renderer[type];
5280         
5281                 if ( $.isPlainObject( renderer ) && renderer[type] ) {
5282                         // Specific renderer for this type. If available use it, otherwise use
5283                         // the default.
5284                         return host[renderer[type]] || host._;
5285                 }
5286                 else if ( typeof renderer === 'string' ) {
5287                         // Common renderer - if there is one available for this type use it,
5288                         // otherwise use the default
5289                         return host[renderer] || host._;
5290                 }
5291         
5292                 // Use the default
5293                 return host._;
5294         }
5295         
5296         
5297         /**
5298          * Detect the data source being used for the table. Used to simplify the code
5299          * a little (ajax) and to make it compress a little smaller.
5300          *
5301          *  @param {object} settings dataTables settings object
5302          *  @returns {string} Data source
5303          *  @memberof DataTable#oApi
5304          */
5305         function _fnDataSource ( settings )
5306         {
5307                 if ( settings.oFeatures.bServerSide ) {
5308                         return 'ssp';
5309                 }
5310                 else if ( settings.ajax || settings.sAjaxSource ) {
5311                         return 'ajax';
5312                 }
5313                 return 'dom';
5314         }
5315         
5316
5317         DataTable = function( options )
5318         {
5319                 /**
5320                  * Perform a jQuery selector action on the table's TR elements (from the tbody) and
5321                  * return the resulting jQuery object.
5322                  *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
5323                  *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
5324                  *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
5325                  *    criterion ("applied") or all TR elements (i.e. no filter).
5326                  *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
5327                  *    Can be either 'current', whereby the current sorting of the table is used, or
5328                  *    'original' whereby the original order the data was read into the table is used.
5329                  *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
5330                  *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
5331                  *    'current' and filter is 'applied', regardless of what they might be given as.
5332                  *  @returns {object} jQuery object, filtered by the given selector.
5333                  *  @dtopt API
5334                  *  @deprecated Since v1.10
5335                  *
5336                  *  @example
5337                  *    $(document).ready(function() {
5338                  *      var oTable = $('#example').dataTable();
5339                  *
5340                  *      // Highlight every second row
5341                  *      oTable.$('tr:odd').css('backgroundColor', 'blue');
5342                  *    } );
5343                  *
5344                  *  @example
5345                  *    $(document).ready(function() {
5346                  *      var oTable = $('#example').dataTable();
5347                  *
5348                  *      // Filter to rows with 'Webkit' in them, add a background colour and then
5349                  *      // remove the filter, thus highlighting the 'Webkit' rows only.
5350                  *      oTable.fnFilter('Webkit');
5351                  *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
5352                  *      oTable.fnFilter('');
5353                  *    } );
5354                  */
5355                 this.$ = function ( sSelector, oOpts )
5356                 {
5357                         return this.api(true).$( sSelector, oOpts );
5358                 };
5359                 
5360                 
5361                 /**
5362                  * Almost identical to $ in operation, but in this case returns the data for the matched
5363                  * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
5364                  * rather than any descendants, so the data can be obtained for the row/cell. If matching
5365                  * rows are found, the data returned is the original data array/object that was used to
5366                  * create the row (or a generated array if from a DOM source).
5367                  *
5368                  * This method is often useful in-combination with $ where both functions are given the
5369                  * same parameters and the array indexes will match identically.
5370                  *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
5371                  *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
5372                  *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
5373                  *    criterion ("applied") or all elements (i.e. no filter).
5374                  *  @param {string} [oOpts.order=current] Order of the data in the processed array.
5375                  *    Can be either 'current', whereby the current sorting of the table is used, or
5376                  *    'original' whereby the original order the data was read into the table is used.
5377                  *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
5378                  *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
5379                  *    'current' and filter is 'applied', regardless of what they might be given as.
5380                  *  @returns {array} Data for the matched elements. If any elements, as a result of the
5381                  *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
5382                  *    entry in the array.
5383                  *  @dtopt API
5384                  *  @deprecated Since v1.10
5385                  *
5386                  *  @example
5387                  *    $(document).ready(function() {
5388                  *      var oTable = $('#example').dataTable();
5389                  *
5390                  *      // Get the data from the first row in the table
5391                  *      var data = oTable._('tr:first');
5392                  *
5393                  *      // Do something useful with the data
5394                  *      alert( "First cell is: "+data[0] );
5395                  *    } );
5396                  *
5397                  *  @example
5398                  *    $(document).ready(function() {
5399                  *      var oTable = $('#example').dataTable();
5400                  *
5401                  *      // Filter to 'Webkit' and get all data for
5402                  *      oTable.fnFilter('Webkit');
5403                  *      var data = oTable._('tr', {"search": "applied"});
5404                  *
5405                  *      // Do something with the data
5406                  *      alert( data.length+" rows matched the search" );
5407                  *    } );
5408                  */
5409                 this._ = function ( sSelector, oOpts )
5410                 {
5411                         return this.api(true).rows( sSelector, oOpts ).data();
5412                 };
5413                 
5414                 
5415                 /**
5416                  * Create a DataTables Api instance, with the currently selected tables for
5417                  * the Api's context.
5418                  * @param {boolean} [traditional=false] Set the API instance's context to be
5419                  *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
5420                  *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
5421                  *   or if all tables captured in the jQuery object should be used.
5422                  * @return {DataTables.Api}
5423                  */
5424                 this.api = function ( traditional )
5425                 {
5426                         return traditional ?
5427                                 new _Api(
5428                                         _fnSettingsFromNode( this[ _ext.iApiIndex ] )
5429                                 ) :
5430                                 new _Api( this );
5431                 };
5432                 
5433                 
5434                 /**
5435                  * Add a single new row or multiple rows of data to the table. Please note
5436                  * that this is suitable for client-side processing only - if you are using
5437                  * server-side processing (i.e. "bServerSide": true), then to add data, you
5438                  * must add it to the data source, i.e. the server-side, through an Ajax call.
5439                  *  @param {array|object} data The data to be added to the table. This can be:
5440                  *    <ul>
5441                  *      <li>1D array of data - add a single row with the data provided</li>
5442                  *      <li>2D array of arrays - add multiple rows in a single call</li>
5443                  *      <li>object - data object when using <i>mData</i></li>
5444                  *      <li>array of objects - multiple data objects when using <i>mData</i></li>
5445                  *    </ul>
5446                  *  @param {bool} [redraw=true] redraw the table or not
5447                  *  @returns {array} An array of integers, representing the list of indexes in
5448                  *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
5449                  *    the table.
5450                  *  @dtopt API
5451                  *  @deprecated Since v1.10
5452                  *
5453                  *  @example
5454                  *    // Global var for counter
5455                  *    var giCount = 2;
5456                  *
5457                  *    $(document).ready(function() {
5458                  *      $('#example').dataTable();
5459                  *    } );
5460                  *
5461                  *    function fnClickAddRow() {
5462                  *      $('#example').dataTable().fnAddData( [
5463                  *        giCount+".1",
5464                  *        giCount+".2",
5465                  *        giCount+".3",
5466                  *        giCount+".4" ]
5467                  *      );
5468                  *
5469                  *      giCount++;
5470                  *    }
5471                  */
5472                 this.fnAddData = function( data, redraw )
5473                 {
5474                         var api = this.api( true );
5475                 
5476                         /* Check if we want to add multiple rows or not */
5477                         var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
5478                                 api.rows.add( data ) :
5479                                 api.row.add( data );
5480                 
5481                         if ( redraw === undefined || redraw ) {
5482                                 api.draw();
5483                         }
5484                 
5485                         return rows.flatten().toArray();
5486                 };
5487                 
5488                 
5489                 /**
5490                  * This function will make DataTables recalculate the column sizes, based on the data
5491                  * contained in the table and the sizes applied to the columns (in the DOM, CSS or
5492                  * through the sWidth parameter). This can be useful when the width of the table's
5493                  * parent element changes (for example a window resize).
5494                  *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
5495                  *  @dtopt API
5496                  *  @deprecated Since v1.10
5497                  *
5498                  *  @example
5499                  *    $(document).ready(function() {
5500                  *      var oTable = $('#example').dataTable( {
5501                  *        "sScrollY": "200px",
5502                  *        "bPaginate": false
5503                  *      } );
5504                  *
5505                  *      $(window).bind('resize', function () {
5506                  *        oTable.fnAdjustColumnSizing();
5507                  *      } );
5508                  *    } );
5509                  */
5510                 this.fnAdjustColumnSizing = function ( bRedraw )
5511                 {
5512                         var api = this.api( true ).columns.adjust();
5513                         var settings = api.settings()[0];
5514                         var scroll = settings.oScroll;
5515                 
5516                         if ( bRedraw === undefined || bRedraw ) {
5517                                 api.draw( false );
5518                         }
5519                         else if ( scroll.sX !== "" || scroll.sY !== "" ) {
5520                                 /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
5521                                 _fnScrollDraw( settings );
5522                         }
5523                 };
5524                 
5525                 
5526                 /**
5527                  * Quickly and simply clear a table
5528                  *  @param {bool} [bRedraw=true] redraw the table or not
5529                  *  @dtopt API
5530                  *  @deprecated Since v1.10
5531                  *
5532                  *  @example
5533                  *    $(document).ready(function() {
5534                  *      var oTable = $('#example').dataTable();
5535                  *
5536                  *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
5537                  *      oTable.fnClearTable();
5538                  *    } );
5539                  */
5540                 this.fnClearTable = function( bRedraw )
5541                 {
5542                         var api = this.api( true ).clear();
5543                 
5544                         if ( bRedraw === undefined || bRedraw ) {
5545                                 api.draw();
5546                         }
5547                 };
5548                 
5549                 
5550                 /**
5551                  * The exact opposite of 'opening' a row, this function will close any rows which
5552                  * are currently 'open'.
5553                  *  @param {node} nTr the table row to 'close'
5554                  *  @returns {int} 0 on success, or 1 if failed (can't find the row)
5555                  *  @dtopt API
5556                  *  @deprecated Since v1.10
5557                  *
5558                  *  @example
5559                  *    $(document).ready(function() {
5560                  *      var oTable;
5561                  *
5562                  *      // 'open' an information row when a row is clicked on
5563                  *      $('#example tbody tr').click( function () {
5564                  *        if ( oTable.fnIsOpen(this) ) {
5565                  *          oTable.fnClose( this );
5566                  *        } else {
5567                  *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5568                  *        }
5569                  *      } );
5570                  *
5571                  *      oTable = $('#example').dataTable();
5572                  *    } );
5573                  */
5574                 this.fnClose = function( nTr )
5575                 {
5576                         this.api( true ).row( nTr ).child.hide();
5577                 };
5578                 
5579                 
5580                 /**
5581                  * Remove a row for the table
5582                  *  @param {mixed} target The index of the row from aoData to be deleted, or
5583                  *    the TR element you want to delete
5584                  *  @param {function|null} [callBack] Callback function
5585                  *  @param {bool} [redraw=true] Redraw the table or not
5586                  *  @returns {array} The row that was deleted
5587                  *  @dtopt API
5588                  *  @deprecated Since v1.10
5589                  *
5590                  *  @example
5591                  *    $(document).ready(function() {
5592                  *      var oTable = $('#example').dataTable();
5593                  *
5594                  *      // Immediately remove the first row
5595                  *      oTable.fnDeleteRow( 0 );
5596                  *    } );
5597                  */
5598                 this.fnDeleteRow = function( target, callback, redraw )
5599                 {
5600                         var api = this.api( true );
5601                         var rows = api.rows( target );
5602                         var settings = rows.settings()[0];
5603                         var data = settings.aoData[ rows[0][0] ];
5604                 
5605                         rows.remove();
5606                 
5607                         if ( callback ) {
5608                                 callback.call( this, settings, data );
5609                         }
5610                 
5611                         if ( redraw === undefined || redraw ) {
5612                                 api.draw();
5613                         }
5614                 
5615                         return data;
5616                 };
5617                 
5618                 
5619                 /**
5620                  * Restore the table to it's original state in the DOM by removing all of DataTables
5621                  * enhancements, alterations to the DOM structure of the table and event listeners.
5622                  *  @param {boolean} [remove=false] Completely remove the table from the DOM
5623                  *  @dtopt API
5624                  *  @deprecated Since v1.10
5625                  *
5626                  *  @example
5627                  *    $(document).ready(function() {
5628                  *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
5629                  *      var oTable = $('#example').dataTable();
5630                  *      oTable.fnDestroy();
5631                  *    } );
5632                  */
5633                 this.fnDestroy = function ( remove )
5634                 {
5635                         this.api( true ).destroy( remove );
5636                 };
5637                 
5638                 
5639                 /**
5640                  * Redraw the table
5641                  *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
5642                  *  @dtopt API
5643                  *  @deprecated Since v1.10
5644                  *
5645                  *  @example
5646                  *    $(document).ready(function() {
5647                  *      var oTable = $('#example').dataTable();
5648                  *
5649                  *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
5650                  *      oTable.fnDraw();
5651                  *    } );
5652                  */
5653                 this.fnDraw = function( complete )
5654                 {
5655                         // Note that this isn't an exact match to the old call to _fnDraw - it takes
5656                         // into account the new data, but can hold position.
5657                         this.api( true ).draw( complete );
5658                 };
5659                 
5660                 
5661                 /**
5662                  * Filter the input based on data
5663                  *  @param {string} sInput String to filter the table on
5664                  *  @param {int|null} [iColumn] Column to limit filtering to
5665                  *  @param {bool} [bRegex=false] Treat as regular expression or not
5666                  *  @param {bool} [bSmart=true] Perform smart filtering or not
5667                  *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
5668                  *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
5669                  *  @dtopt API
5670                  *  @deprecated Since v1.10
5671                  *
5672                  *  @example
5673                  *    $(document).ready(function() {
5674                  *      var oTable = $('#example').dataTable();
5675                  *
5676                  *      // Sometime later - filter...
5677                  *      oTable.fnFilter( 'test string' );
5678                  *    } );
5679                  */
5680                 this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
5681                 {
5682                         var api = this.api( true );
5683                 
5684                         if ( iColumn === null || iColumn === undefined ) {
5685                                 api.search( sInput, bRegex, bSmart, bCaseInsensitive );
5686                         }
5687                         else {
5688                                 api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
5689                         }
5690                 
5691                         api.draw();
5692                 };
5693                 
5694                 
5695                 /**
5696                  * Get the data for the whole table, an individual row or an individual cell based on the
5697                  * provided parameters.
5698                  *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
5699                  *    a TR node then the data source for the whole row will be returned. If given as a
5700                  *    TD/TH cell node then iCol will be automatically calculated and the data for the
5701                  *    cell returned. If given as an integer, then this is treated as the aoData internal
5702                  *    data index for the row (see fnGetPosition) and the data for that row used.
5703                  *  @param {int} [col] Optional column index that you want the data of.
5704                  *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
5705                  *    returned. If mRow is defined, just data for that row, and is iCol is
5706                  *    defined, only data for the designated cell is returned.
5707                  *  @dtopt API
5708                  *  @deprecated Since v1.10
5709                  *
5710                  *  @example
5711                  *    // Row data
5712                  *    $(document).ready(function() {
5713                  *      oTable = $('#example').dataTable();
5714                  *
5715                  *      oTable.$('tr').click( function () {
5716                  *        var data = oTable.fnGetData( this );
5717                  *        // ... do something with the array / object of data for the row
5718                  *      } );
5719                  *    } );
5720                  *
5721                  *  @example
5722                  *    // Individual cell data
5723                  *    $(document).ready(function() {
5724                  *      oTable = $('#example').dataTable();
5725                  *
5726                  *      oTable.$('td').click( function () {
5727                  *        var sData = oTable.fnGetData( this );
5728                  *        alert( 'The cell clicked on had the value of '+sData );
5729                  *      } );
5730                  *    } );
5731                  */
5732                 this.fnGetData = function( src, col )
5733                 {
5734                         var api = this.api( true );
5735                 
5736                         if ( src !== undefined ) {
5737                                 var type = src.nodeName ? src.nodeName.toLowerCase() : '';
5738                 
5739                                 return col !== undefined || type == 'td' || type == 'th' ?
5740                                         api.cell( src, col ).data() :
5741                                         api.row( src ).data() || null;
5742                         }
5743                 
5744                         return api.data().toArray();
5745                 };
5746                 
5747                 
5748                 /**
5749                  * Get an array of the TR nodes that are used in the table's body. Note that you will
5750                  * typically want to use the '$' API method in preference to this as it is more
5751                  * flexible.
5752                  *  @param {int} [iRow] Optional row index for the TR element you want
5753                  *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
5754                  *    in the table's body, or iRow is defined, just the TR element requested.
5755                  *  @dtopt API
5756                  *  @deprecated Since v1.10
5757                  *
5758                  *  @example
5759                  *    $(document).ready(function() {
5760                  *      var oTable = $('#example').dataTable();
5761                  *
5762                  *      // Get the nodes from the table
5763                  *      var nNodes = oTable.fnGetNodes( );
5764                  *    } );
5765                  */
5766                 this.fnGetNodes = function( iRow )
5767                 {
5768                         var api = this.api( true );
5769                 
5770                         return iRow !== undefined ?
5771                                 api.row( iRow ).node() :
5772                                 api.rows().nodes().flatten().toArray();
5773                 };
5774                 
5775                 
5776                 /**
5777                  * Get the array indexes of a particular cell from it's DOM element
5778                  * and column index including hidden columns
5779                  *  @param {node} node this can either be a TR, TD or TH in the table's body
5780                  *  @returns {int} If nNode is given as a TR, then a single index is returned, or
5781                  *    if given as a cell, an array of [row index, column index (visible),
5782                  *    column index (all)] is given.
5783                  *  @dtopt API
5784                  *  @deprecated Since v1.10
5785                  *
5786                  *  @example
5787                  *    $(document).ready(function() {
5788                  *      $('#example tbody td').click( function () {
5789                  *        // Get the position of the current data from the node
5790                  *        var aPos = oTable.fnGetPosition( this );
5791                  *
5792                  *        // Get the data array for this row
5793                  *        var aData = oTable.fnGetData( aPos[0] );
5794                  *
5795                  *        // Update the data array and return the value
5796                  *        aData[ aPos[1] ] = 'clicked';
5797                  *        this.innerHTML = 'clicked';
5798                  *      } );
5799                  *
5800                  *      // Init DataTables
5801                  *      oTable = $('#example').dataTable();
5802                  *    } );
5803                  */
5804                 this.fnGetPosition = function( node )
5805                 {
5806                         var api = this.api( true );
5807                         var nodeName = node.nodeName.toUpperCase();
5808                 
5809                         if ( nodeName == 'TR' ) {
5810                                 return api.row( node ).index();
5811                         }
5812                         else if ( nodeName == 'TD' || nodeName == 'TH' ) {
5813                                 var cell = api.cell( node ).index();
5814                 
5815                                 return [
5816                                         cell.row,
5817                                         cell.columnVisible,
5818                                         cell.column
5819                                 ];
5820                         }
5821                         return null;
5822                 };
5823                 
5824                 
5825                 /**
5826                  * Check to see if a row is 'open' or not.
5827                  *  @param {node} nTr the table row to check
5828                  *  @returns {boolean} true if the row is currently open, false otherwise
5829                  *  @dtopt API
5830                  *  @deprecated Since v1.10
5831                  *
5832                  *  @example
5833                  *    $(document).ready(function() {
5834                  *      var oTable;
5835                  *
5836                  *      // 'open' an information row when a row is clicked on
5837                  *      $('#example tbody tr').click( function () {
5838                  *        if ( oTable.fnIsOpen(this) ) {
5839                  *          oTable.fnClose( this );
5840                  *        } else {
5841                  *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5842                  *        }
5843                  *      } );
5844                  *
5845                  *      oTable = $('#example').dataTable();
5846                  *    } );
5847                  */
5848                 this.fnIsOpen = function( nTr )
5849                 {
5850                         return this.api( true ).row( nTr ).child.isShown();
5851                 };
5852                 
5853                 
5854                 /**
5855                  * This function will place a new row directly after a row which is currently
5856                  * on display on the page, with the HTML contents that is passed into the
5857                  * function. This can be used, for example, to ask for confirmation that a
5858                  * particular record should be deleted.
5859                  *  @param {node} nTr The table row to 'open'
5860                  *  @param {string|node|jQuery} mHtml The HTML to put into the row
5861                  *  @param {string} sClass Class to give the new TD cell
5862                  *  @returns {node} The row opened. Note that if the table row passed in as the
5863                  *    first parameter, is not found in the table, this method will silently
5864                  *    return.
5865                  *  @dtopt API
5866                  *  @deprecated Since v1.10
5867                  *
5868                  *  @example
5869                  *    $(document).ready(function() {
5870                  *      var oTable;
5871                  *
5872                  *      // 'open' an information row when a row is clicked on
5873                  *      $('#example tbody tr').click( function () {
5874                  *        if ( oTable.fnIsOpen(this) ) {
5875                  *          oTable.fnClose( this );
5876                  *        } else {
5877                  *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5878                  *        }
5879                  *      } );
5880                  *
5881                  *      oTable = $('#example').dataTable();
5882                  *    } );
5883                  */
5884                 this.fnOpen = function( nTr, mHtml, sClass )
5885                 {
5886                         return this.api( true )
5887                                 .row( nTr )
5888                                 .child( mHtml, sClass )
5889                                 .show()
5890                                 .child()[0];
5891                 };
5892                 
5893                 
5894                 /**
5895                  * Change the pagination - provides the internal logic for pagination in a simple API
5896                  * function. With this function you can have a DataTables table go to the next,
5897                  * previous, first or last pages.
5898                  *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
5899                  *    or page number to jump to (integer), note that page 0 is the first page.
5900                  *  @param {bool} [bRedraw=true] Redraw the table or not
5901                  *  @dtopt API
5902                  *  @deprecated Since v1.10
5903                  *
5904                  *  @example
5905                  *    $(document).ready(function() {
5906                  *      var oTable = $('#example').dataTable();
5907                  *      oTable.fnPageChange( 'next' );
5908                  *    } );
5909                  */
5910                 this.fnPageChange = function ( mAction, bRedraw )
5911                 {
5912                         var api = this.api( true ).page( mAction );
5913                 
5914                         if ( bRedraw === undefined || bRedraw ) {
5915                                 api.draw(false);
5916                         }
5917                 };
5918                 
5919                 
5920                 /**
5921                  * Show a particular column
5922                  *  @param {int} iCol The column whose display should be changed
5923                  *  @param {bool} bShow Show (true) or hide (false) the column
5924                  *  @param {bool} [bRedraw=true] Redraw the table or not
5925                  *  @dtopt API
5926                  *  @deprecated Since v1.10
5927                  *
5928                  *  @example
5929                  *    $(document).ready(function() {
5930                  *      var oTable = $('#example').dataTable();
5931                  *
5932                  *      // Hide the second column after initialisation
5933                  *      oTable.fnSetColumnVis( 1, false );
5934                  *    } );
5935                  */
5936                 this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
5937                 {
5938                         var api = this.api( true ).column( iCol ).visible( bShow );
5939                 
5940                         if ( bRedraw === undefined || bRedraw ) {
5941                                 api.columns.adjust().draw();
5942                         }
5943                 };
5944                 
5945                 
5946                 /**
5947                  * Get the settings for a particular table for external manipulation
5948                  *  @returns {object} DataTables settings object. See
5949                  *    {@link DataTable.models.oSettings}
5950                  *  @dtopt API
5951                  *  @deprecated Since v1.10
5952                  *
5953                  *  @example
5954                  *    $(document).ready(function() {
5955                  *      var oTable = $('#example').dataTable();
5956                  *      var oSettings = oTable.fnSettings();
5957                  *
5958                  *      // Show an example parameter from the settings
5959                  *      alert( oSettings._iDisplayStart );
5960                  *    } );
5961                  */
5962                 this.fnSettings = function()
5963                 {
5964                         return _fnSettingsFromNode( this[_ext.iApiIndex] );
5965                 };
5966                 
5967                 
5968                 /**
5969                  * Sort the table by a particular column
5970                  *  @param {int} iCol the data index to sort on. Note that this will not match the
5971                  *    'display index' if you have hidden data entries
5972                  *  @dtopt API
5973                  *  @deprecated Since v1.10
5974                  *
5975                  *  @example
5976                  *    $(document).ready(function() {
5977                  *      var oTable = $('#example').dataTable();
5978                  *
5979                  *      // Sort immediately with columns 0 and 1
5980                  *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
5981                  *    } );
5982                  */
5983                 this.fnSort = function( aaSort )
5984                 {
5985                         this.api( true ).order( aaSort ).draw();
5986                 };
5987                 
5988                 
5989                 /**
5990                  * Attach a sort listener to an element for a given column
5991                  *  @param {node} nNode the element to attach the sort listener to
5992                  *  @param {int} iColumn the column that a click on this node will sort on
5993                  *  @param {function} [fnCallback] callback function when sort is run
5994                  *  @dtopt API
5995                  *  @deprecated Since v1.10
5996                  *
5997                  *  @example
5998                  *    $(document).ready(function() {
5999                  *      var oTable = $('#example').dataTable();
6000                  *
6001                  *      // Sort on column 1, when 'sorter' is clicked on
6002                  *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
6003                  *    } );
6004                  */
6005                 this.fnSortListener = function( nNode, iColumn, fnCallback )
6006                 {
6007                         this.api( true ).order.listener( nNode, iColumn, fnCallback );
6008                 };
6009                 
6010                 
6011                 /**
6012                  * Update a table cell or row - this method will accept either a single value to
6013                  * update the cell with, an array of values with one element for each column or
6014                  * an object in the same format as the original data source. The function is
6015                  * self-referencing in order to make the multi column updates easier.
6016                  *  @param {object|array|string} mData Data to update the cell/row with
6017                  *  @param {node|int} mRow TR element you want to update or the aoData index
6018                  *  @param {int} [iColumn] The column to update, give as null or undefined to
6019                  *    update a whole row.
6020                  *  @param {bool} [bRedraw=true] Redraw the table or not
6021                  *  @param {bool} [bAction=true] Perform pre-draw actions or not
6022                  *  @returns {int} 0 on success, 1 on error
6023                  *  @dtopt API
6024                  *  @deprecated Since v1.10
6025                  *
6026                  *  @example
6027                  *    $(document).ready(function() {
6028                  *      var oTable = $('#example').dataTable();
6029                  *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
6030                  *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
6031                  *    } );
6032                  */
6033                 this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
6034                 {
6035                         var api = this.api( true );
6036                 
6037                         if ( iColumn === undefined || iColumn === null ) {
6038                                 api.row( mRow ).data( mData );
6039                         }
6040                         else {
6041                                 api.cell( mRow, iColumn ).data( mData );
6042                         }
6043                 
6044                         if ( bAction === undefined || bAction ) {
6045                                 api.columns.adjust();
6046                         }
6047                 
6048                         if ( bRedraw === undefined || bRedraw ) {
6049                                 api.draw();
6050                         }
6051                         return 0;
6052                 };
6053                 
6054                 
6055                 /**
6056                  * Provide a common method for plug-ins to check the version of DataTables being used, in order
6057                  * to ensure compatibility.
6058                  *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
6059                  *    formats "X" and "X.Y" are also acceptable.
6060                  *  @returns {boolean} true if this version of DataTables is greater or equal to the required
6061                  *    version, or false if this version of DataTales is not suitable
6062                  *  @method
6063                  *  @dtopt API
6064                  *  @deprecated Since v1.10
6065                  *
6066                  *  @example
6067                  *    $(document).ready(function() {
6068                  *      var oTable = $('#example').dataTable();
6069                  *      alert( oTable.fnVersionCheck( '1.9.0' ) );
6070                  *    } );
6071                  */
6072                 this.fnVersionCheck = _ext.fnVersionCheck;
6073                 
6074
6075                 var _that = this;
6076                 var emptyInit = options === undefined;
6077                 var len = this.length;
6078
6079                 if ( emptyInit ) {
6080                         options = {};
6081                 }
6082
6083                 this.oApi = this.internal = _ext.internal;
6084
6085                 // Extend with old style plug-in API methods
6086                 for ( var fn in DataTable.ext.internal ) {
6087                         if ( fn ) {
6088                                 this[fn] = _fnExternApiFunc(fn);
6089                         }
6090                 }
6091
6092                 this.each(function() {
6093                         // For each initialisation we want to give it a clean initialisation
6094                         // object that can be bashed around
6095                         var o = {};
6096                         var oInit = len > 1 ? // optimisation for single table case
6097                                 _fnExtend( o, options, true ) :
6098                                 options;
6099
6100                         /*global oInit,_that,emptyInit*/
6101                         var i=0, iLen, j, jLen, k, kLen;
6102                         var sId = this.getAttribute( 'id' );
6103                         var bInitHandedOff = false;
6104                         var defaults = DataTable.defaults;
6105                         var $this = $(this);
6106                         
6107                         
6108                         /* Sanity check */
6109                         if ( this.nodeName.toLowerCase() != 'table' )
6110                         {
6111                                 _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
6112                                 return;
6113                         }
6114                         
6115                         /* Backwards compatibility for the defaults */
6116                         _fnCompatOpts( defaults );
6117                         _fnCompatCols( defaults.column );
6118                         
6119                         /* Convert the camel-case defaults to Hungarian */
6120                         _fnCamelToHungarian( defaults, defaults, true );
6121                         _fnCamelToHungarian( defaults.column, defaults.column, true );
6122                         
6123                         /* Setting up the initialisation object */
6124                         _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );
6125                         
6126                         
6127                         
6128                         /* Check to see if we are re-initialising a table */
6129                         var allSettings = DataTable.settings;
6130                         for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
6131                         {
6132                                 var s = allSettings[i];
6133                         
6134                                 /* Base check on table node */
6135                                 if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) )
6136                                 {
6137                                         var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
6138                                         var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
6139                         
6140                                         if ( emptyInit || bRetrieve )
6141                                         {
6142                                                 return s.oInstance;
6143                                         }
6144                                         else if ( bDestroy )
6145                                         {
6146                                                 s.oInstance.fnDestroy();
6147                                                 break;
6148                                         }
6149                                         else
6150                                         {
6151                                                 _fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
6152                                                 return;
6153                                         }
6154                                 }
6155                         
6156                                 /* If the element we are initialising has the same ID as a table which was previously
6157                                  * initialised, but the table nodes don't match (from before) then we destroy the old
6158                                  * instance by simply deleting it. This is under the assumption that the table has been
6159                                  * destroyed by other methods. Anyone using non-id selectors will need to do this manually
6160                                  */
6161                                 if ( s.sTableId == this.id )
6162                                 {
6163                                         allSettings.splice( i, 1 );
6164                                         break;
6165                                 }
6166                         }
6167                         
6168                         /* Ensure the table has an ID - required for accessibility */
6169                         if ( sId === null || sId === "" )
6170                         {
6171                                 sId = "DataTables_Table_"+(DataTable.ext._unique++);
6172                                 this.id = sId;
6173                         }
6174                         
6175                         /* Create the settings object for this table and set some of the default parameters */
6176                         var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
6177                                 "sDestroyWidth": $this[0].style.width,
6178                                 "sInstance":     sId,
6179                                 "sTableId":      sId
6180                         } );
6181                         oSettings.nTable = this;
6182                         oSettings.oApi   = _that.internal;
6183                         oSettings.oInit  = oInit;
6184                         
6185                         allSettings.push( oSettings );
6186                         
6187                         // Need to add the instance after the instance after the settings object has been added
6188                         // to the settings array, so we can self reference the table instance if more than one
6189                         oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
6190                         
6191                         // Backwards compatibility, before we apply all the defaults
6192                         _fnCompatOpts( oInit );
6193                         
6194                         if ( oInit.oLanguage )
6195                         {
6196                                 _fnLanguageCompat( oInit.oLanguage );
6197                         }
6198                         
6199                         // If the length menu is given, but the init display length is not, use the length menu
6200                         if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
6201                         {
6202                                 oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
6203                                         oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
6204                         }
6205                         
6206                         // Apply the defaults and init options to make a single init object will all
6207                         // options defined from defaults and instance options.
6208                         oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
6209                         
6210                         
6211                         // Map the initialisation options onto the settings object
6212                         _fnMap( oSettings.oFeatures, oInit, [
6213                                 "bPaginate",
6214                                 "bLengthChange",
6215                                 "bFilter",
6216                                 "bSort",
6217                                 "bSortMulti",
6218                                 "bInfo",
6219                                 "bProcessing",
6220                                 "bAutoWidth",
6221                                 "bSortClasses",
6222                                 "bServerSide",
6223                                 "bDeferRender"
6224                         ] );
6225                         _fnMap( oSettings, oInit, [
6226                                 "asStripeClasses",
6227                                 "ajax",
6228                                 "fnServerData",
6229                                 "fnFormatNumber",
6230                                 "sServerMethod",
6231                                 "aaSorting",
6232                                 "aaSortingFixed",
6233                                 "aLengthMenu",
6234                                 "sPaginationType",
6235                                 "sAjaxSource",
6236                                 "sAjaxDataProp",
6237                                 "iStateDuration",
6238                                 "sDom",
6239                                 "bSortCellsTop",
6240                                 "iTabIndex",
6241                                 "fnStateLoadCallback",
6242                                 "fnStateSaveCallback",
6243                                 "renderer",
6244                                 "searchDelay",
6245                                 [ "iCookieDuration", "iStateDuration" ], // backwards compat
6246                                 [ "oSearch", "oPreviousSearch" ],
6247                                 [ "aoSearchCols", "aoPreSearchCols" ],
6248                                 [ "iDisplayLength", "_iDisplayLength" ],
6249                                 [ "bJQueryUI", "bJUI" ]
6250                         ] );
6251                         _fnMap( oSettings.oScroll, oInit, [
6252                                 [ "sScrollX", "sX" ],
6253                                 [ "sScrollXInner", "sXInner" ],
6254                                 [ "sScrollY", "sY" ],
6255                                 [ "bScrollCollapse", "bCollapse" ]
6256                         ] );
6257                         _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
6258                         
6259                         /* Callback functions which are array driven */
6260                         _fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
6261                         _fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
6262                         _fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
6263                         _fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
6264                         _fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
6265                         _fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
6266                         _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
6267                         _fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
6268                         _fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
6269                         _fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
6270                         _fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
6271                         
6272                         var oClasses = oSettings.oClasses;
6273                         
6274                         // @todo Remove in 1.11
6275                         if ( oInit.bJQueryUI )
6276                         {
6277                                 /* Use the JUI classes object for display. You could clone the oStdClasses object if
6278                                  * you want to have multiple tables with multiple independent classes
6279                                  */
6280                                 $.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses );
6281                         
6282                                 if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" )
6283                                 {
6284                                         /* Set the DOM to use a layout suitable for jQuery UI's theming */
6285                                         oSettings.sDom = '<"H"lfr>t<"F"ip>';
6286                                 }
6287                         
6288                                 if ( ! oSettings.renderer ) {
6289                                         oSettings.renderer = 'jqueryui';
6290                                 }
6291                                 else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) {
6292                                         oSettings.renderer.header = 'jqueryui';
6293                                 }
6294                         }
6295                         else
6296                         {
6297                                 $.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
6298                         }
6299                         $this.addClass( oClasses.sTable );
6300                         
6301                         /* Calculate the scroll bar width and cache it for use later on */
6302                         if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
6303                         {
6304                                 oSettings.oScroll.iBarWidth = _fnScrollBarWidth();
6305                         }
6306                         if ( oSettings.oScroll.sX === true ) { // Easy initialisation of x-scrolling
6307                                 oSettings.oScroll.sX = '100%';
6308                         }
6309                         
6310                         if ( oSettings.iInitDisplayStart === undefined )
6311                         {
6312                                 /* Display start point, taking into account the save saving */
6313                                 oSettings.iInitDisplayStart = oInit.iDisplayStart;
6314                                 oSettings._iDisplayStart = oInit.iDisplayStart;
6315                         }
6316                         
6317                         if ( oInit.iDeferLoading !== null )
6318                         {
6319                                 oSettings.bDeferLoading = true;
6320                                 var tmp = $.isArray( oInit.iDeferLoading );
6321                                 oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
6322                                 oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
6323                         }
6324                         
6325                         /* Language definitions */
6326                         var oLanguage = oSettings.oLanguage;
6327                         $.extend( true, oLanguage, oInit.oLanguage );
6328                         
6329                         if ( oLanguage.sUrl !== "" )
6330                         {
6331                                 /* Get the language definitions from a file - because this Ajax call makes the language
6332                                  * get async to the remainder of this function we use bInitHandedOff to indicate that
6333                                  * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
6334                                  */
6335                                 $.ajax( {
6336                                         dataType: 'json',
6337                                         url: oLanguage.sUrl,
6338                                         success: function ( json ) {
6339                                                 _fnLanguageCompat( json );
6340                                                 _fnCamelToHungarian( defaults.oLanguage, json );
6341                                                 $.extend( true, oLanguage, json );
6342                                                 _fnInitialise( oSettings );
6343                                         },
6344                                         error: function () {
6345                                                 // Error occurred loading language file, continue on as best we can
6346                                                 _fnInitialise( oSettings );
6347                                         }
6348                                 } );
6349                                 bInitHandedOff = true;
6350                         }
6351                         
6352                         /*
6353                          * Stripes
6354                          */
6355                         if ( oInit.asStripeClasses === null )
6356                         {
6357                                 oSettings.asStripeClasses =[
6358                                         oClasses.sStripeOdd,
6359                                         oClasses.sStripeEven
6360                                 ];
6361                         }
6362                         
6363                         /* Remove row stripe classes if they are already on the table row */
6364                         var stripeClasses = oSettings.asStripeClasses;
6365                         var rowOne = $this.children('tbody').find('tr').eq(0);
6366                         if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
6367                                 return rowOne.hasClass(el);
6368                         } ) ) !== -1 ) {
6369                                 $('tbody tr', this).removeClass( stripeClasses.join(' ') );
6370                                 oSettings.asDestroyStripes = stripeClasses.slice();
6371                         }
6372                         
6373                         /*
6374                          * Columns
6375                          * See if we should load columns automatically or use defined ones
6376                          */
6377                         var anThs = [];
6378                         var aoColumnsInit;
6379                         var nThead = this.getElementsByTagName('thead');
6380                         if ( nThead.length !== 0 )
6381                         {
6382                                 _fnDetectHeader( oSettings.aoHeader, nThead[0] );
6383                                 anThs = _fnGetUniqueThs( oSettings );
6384                         }
6385                         
6386                         /* If not given a column array, generate one with nulls */
6387                         if ( oInit.aoColumns === null )
6388                         {
6389                                 aoColumnsInit = [];
6390                                 for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
6391                                 {
6392                                         aoColumnsInit.push( null );
6393                                 }
6394                         }
6395                         else
6396                         {
6397                                 aoColumnsInit = oInit.aoColumns;
6398                         }
6399                         
6400                         /* Add the columns */
6401                         for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
6402                         {
6403                                 _fnAddColumn( oSettings, anThs ? anThs[i] : null );
6404                         }
6405                         
6406                         /* Apply the column definitions */
6407                         _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
6408                                 _fnColumnOptions( oSettings, iCol, oDef );
6409                         } );
6410                         
6411                         /* HTML5 attribute detection - build an mData object automatically if the
6412                          * attributes are found
6413                          */
6414                         if ( rowOne.length ) {
6415                                 var a = function ( cell, name ) {
6416                                         return cell.getAttribute( 'data-'+name ) !== null ? name : null;
6417                                 };
6418                         
6419                                 $.each( _fnGetRowElements( oSettings, rowOne[0] ).cells, function (i, cell) {
6420                                         var col = oSettings.aoColumns[i];
6421                         
6422                                         if ( col.mData === i ) {
6423                                                 var sort = a( cell, 'sort' ) || a( cell, 'order' );
6424                                                 var filter = a( cell, 'filter' ) || a( cell, 'search' );
6425                         
6426                                                 if ( sort !== null || filter !== null ) {
6427                                                         col.mData = {
6428                                                                 _:      i+'.display',
6429                                                                 sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
6430                                                                 type:   sort !== null   ? i+'.@data-'+sort   : undefined,
6431                                                                 filter: filter !== null ? i+'.@data-'+filter : undefined
6432                                                         };
6433                         
6434                                                         _fnColumnOptions( oSettings, i );
6435                                                 }
6436                                         }
6437                                 } );
6438                         }
6439                         
6440                         var features = oSettings.oFeatures;
6441                         
6442                         /* Must be done after everything which can be overridden by the state saving! */
6443                         if ( oInit.bStateSave )
6444                         {
6445                                 features.bStateSave = true;
6446                                 _fnLoadState( oSettings, oInit );
6447                                 _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
6448                         }
6449                         
6450                         
6451                         /*
6452                          * Sorting
6453                          * @todo For modularisation (1.11) this needs to do into a sort start up handler
6454                          */
6455                         
6456                         // If aaSorting is not defined, then we use the first indicator in asSorting
6457                         // in case that has been altered, so the default sort reflects that option
6458                         if ( oInit.aaSorting === undefined )
6459                         {
6460                                 var sorting = oSettings.aaSorting;
6461                                 for ( i=0, iLen=sorting.length ; i<iLen ; i++ )
6462                                 {
6463                                         sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
6464                                 }
6465                         }
6466                         
6467                         /* Do a first pass on the sorting classes (allows any size changes to be taken into
6468                          * account, and also will apply sorting disabled classes if disabled
6469                          */
6470                         _fnSortingClasses( oSettings );
6471                         
6472                         if ( features.bSort )
6473                         {
6474                                 _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
6475                                         if ( oSettings.bSorted ) {
6476                                                 var aSort = _fnSortFlatten( oSettings );
6477                                                 var sortedColumns = {};
6478                         
6479                                                 $.each( aSort, function (i, val) {
6480                                                         sortedColumns[ val.src ] = val.dir;
6481                                                 } );
6482                         
6483                                                 _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
6484                                                 _fnSortAria( oSettings );
6485                                         }
6486                                 } );
6487                         }
6488                         
6489                         _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
6490                                 if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
6491                                         _fnSortingClasses( oSettings );
6492                                 }
6493                         }, 'sc' );
6494                         
6495                         
6496                         /*
6497                          * Final init
6498                          * Cache the header, body and footer as required, creating them if needed
6499                          */
6500                         
6501                         /* Browser support detection */
6502                         _fnBrowserDetect( oSettings );
6503                         
6504                         // Work around for Webkit bug 83867 - store the caption-side before removing from doc
6505                         var captions = $this.children('caption').each( function () {
6506                                 this._captionSide = $this.css('caption-side');
6507                         } );
6508                         
6509                         var thead = $this.children('thead');
6510                         if ( thead.length === 0 )
6511                         {
6512                                 thead = $('<thead/>').appendTo(this);
6513                         }
6514                         oSettings.nTHead = thead[0];
6515                         
6516                         var tbody = $this.children('tbody');
6517                         if ( tbody.length === 0 )
6518                         {
6519                                 tbody = $('<tbody/>').appendTo(this);
6520                         }
6521                         oSettings.nTBody = tbody[0];
6522                         
6523                         var tfoot = $this.children('tfoot');
6524                         if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
6525                         {
6526                                 // If we are a scrolling table, and no footer has been given, then we need to create
6527                                 // a tfoot element for the caption element to be appended to
6528                                 tfoot = $('<tfoot/>').appendTo(this);
6529                         }
6530                         
6531                         if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
6532                                 $this.addClass( oClasses.sNoFooter );
6533                         }
6534                         else if ( tfoot.length > 0 ) {
6535                                 oSettings.nTFoot = tfoot[0];
6536                                 _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
6537                         }
6538                         
6539                         /* Check if there is data passing into the constructor */
6540                         if ( oInit.aaData )
6541                         {
6542                                 for ( i=0 ; i<oInit.aaData.length ; i++ )
6543                                 {
6544                                         _fnAddData( oSettings, oInit.aaData[ i ] );
6545                                 }
6546                         }
6547                         else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' )
6548                         {
6549                                 /* Grab the data from the page - only do this when deferred loading or no Ajax
6550                                  * source since there is no point in reading the DOM data if we are then going
6551                                  * to replace it with Ajax data
6552                                  */
6553                                 _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
6554                         }
6555                         
6556                         /* Copy the data index array */
6557                         oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
6558                         
6559                         /* Initialisation complete - table can be drawn */
6560                         oSettings.bInitialised = true;
6561                         
6562                         /* Check if we need to initialise the table (it might not have been handed off to the
6563                          * language processor)
6564                          */
6565                         if ( bInitHandedOff === false )
6566                         {
6567                                 _fnInitialise( oSettings );
6568                         }
6569                 } );
6570                 _that = null;
6571                 return this;
6572         };
6573
6574         
6575         
6576         /**
6577          * Computed structure of the DataTables API, defined by the options passed to
6578          * `DataTable.Api.register()` when building the API.
6579          *
6580          * The structure is built in order to speed creation and extension of the Api
6581          * objects since the extensions are effectively pre-parsed.
6582          *
6583          * The array is an array of objects with the following structure, where this
6584          * base array represents the Api prototype base:
6585          *
6586          *     [
6587          *       {
6588          *         name:      'data'                -- string   - Property name
6589          *         val:       function () {},       -- function - Api method (or undefined if just an object
6590          *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6591          *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6592          *       },
6593          *       {
6594          *         name:     'row'
6595          *         val:       {},
6596          *         methodExt: [ ... ],
6597          *         propExt:   [
6598          *           {
6599          *             name:      'data'
6600          *             val:       function () {},
6601          *             methodExt: [ ... ],
6602          *             propExt:   [ ... ]
6603          *           },
6604          *           ...
6605          *         ]
6606          *       }
6607          *     ]
6608          *
6609          * @type {Array}
6610          * @ignore
6611          */
6612         var __apiStruct = [];
6613         
6614         
6615         /**
6616          * `Array.prototype` reference.
6617          *
6618          * @type object
6619          * @ignore
6620          */
6621         var __arrayProto = Array.prototype;
6622         
6623         
6624         /**
6625          * Abstraction for `context` parameter of the `Api` constructor to allow it to
6626          * take several different forms for ease of use.
6627          *
6628          * Each of the input parameter types will be converted to a DataTables settings
6629          * object where possible.
6630          *
6631          * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6632          *   of:
6633          *
6634          *   * `string` - jQuery selector. Any DataTables' matching the given selector
6635          *     with be found and used.
6636          *   * `node` - `TABLE` node which has already been formed into a DataTable.
6637          *   * `jQuery` - A jQuery object of `TABLE` nodes.
6638          *   * `object` - DataTables settings object
6639          *   * `DataTables.Api` - API instance
6640          * @return {array|null} Matching DataTables settings objects. `null` or
6641          *   `undefined` is returned if no matching DataTable is found.
6642          * @ignore
6643          */
6644         var _toSettings = function ( mixed )
6645         {
6646                 var idx, jq;
6647                 var settings = DataTable.settings;
6648                 var tables = $.map( settings, function (el, i) {
6649                         return el.nTable;
6650                 } );
6651         
6652                 if ( ! mixed ) {
6653                         return [];
6654                 }
6655                 else if ( mixed.nTable && mixed.oApi ) {
6656                         // DataTables settings object
6657                         return [ mixed ];
6658                 }
6659                 else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6660                         // Table node
6661                         idx = $.inArray( mixed, tables );
6662                         return idx !== -1 ? [ settings[idx] ] : null;
6663                 }
6664                 else if ( mixed && typeof mixed.settings === 'function' ) {
6665                         return mixed.settings().toArray();
6666                 }
6667                 else if ( typeof mixed === 'string' ) {
6668                         // jQuery selector
6669                         jq = $(mixed);
6670                 }
6671                 else if ( mixed instanceof $ ) {
6672                         // jQuery object (also DataTables instance)
6673                         jq = mixed;
6674                 }
6675         
6676                 if ( jq ) {
6677                         return jq.map( function(i) {
6678                                 idx = $.inArray( this, tables );
6679                                 return idx !== -1 ? settings[idx] : null;
6680                         } ).toArray();
6681                 }
6682         };
6683         
6684         
6685         /**
6686          * DataTables API class - used to control and interface with  one or more
6687          * DataTables enhanced tables.
6688          *
6689          * The API class is heavily based on jQuery, presenting a chainable interface
6690          * that you can use to interact with tables. Each instance of the API class has
6691          * a "context" - i.e. the tables that it will operate on. This could be a single
6692          * table, all tables on a page or a sub-set thereof.
6693          *
6694          * Additionally the API is designed to allow you to easily work with the data in
6695          * the tables, retrieving and manipulating it as required. This is done by
6696          * presenting the API class as an array like interface. The contents of the
6697          * array depend upon the actions requested by each method (for example
6698          * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6699          * return an array of objects or arrays depending upon your table's
6700          * configuration). The API object has a number of array like methods (`push`,
6701          * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6702          * `unique` etc) to assist your working with the data held in a table.
6703          *
6704          * Most methods (those which return an Api instance) are chainable, which means
6705          * the return from a method call also has all of the methods available that the
6706          * top level object had. For example, these two calls are equivalent:
6707          *
6708          *     // Not chained
6709          *     api.row.add( {...} );
6710          *     api.draw();
6711          *
6712          *     // Chained
6713          *     api.row.add( {...} ).draw();
6714          *
6715          * @class DataTable.Api
6716          * @param {array|object|string|jQuery} context DataTable identifier. This is
6717          *   used to define which DataTables enhanced tables this API will operate on.
6718          *   Can be one of:
6719          *
6720          *   * `string` - jQuery selector. Any DataTables' matching the given selector
6721          *     with be found and used.
6722          *   * `node` - `TABLE` node which has already been formed into a DataTable.
6723          *   * `jQuery` - A jQuery object of `TABLE` nodes.
6724          *   * `object` - DataTables settings object
6725          * @param {array} [data] Data to initialise the Api instance with.
6726          *
6727          * @example
6728          *   // Direct initialisation during DataTables construction
6729          *   var api = $('#example').DataTable();
6730          *
6731          * @example
6732          *   // Initialisation using a DataTables jQuery object
6733          *   var api = $('#example').dataTable().api();
6734          *
6735          * @example
6736          *   // Initialisation as a constructor
6737          *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6738          */
6739         _Api = function ( context, data )
6740         {
6741                 if ( ! (this instanceof _Api) ) {
6742                         return new _Api( context, data );
6743                 }
6744         
6745                 var settings = [];
6746                 var ctxSettings = function ( o ) {
6747                         var a = _toSettings( o );
6748                         if ( a ) {
6749                                 settings.push.apply( settings, a );
6750                         }
6751                 };
6752         
6753                 if ( $.isArray( context ) ) {
6754                         for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6755                                 ctxSettings( context[i] );
6756                         }
6757                 }
6758                 else {
6759                         ctxSettings( context );
6760                 }
6761         
6762                 // Remove duplicates
6763                 this.context = _unique( settings );
6764         
6765                 // Initial data
6766                 if ( data ) {
6767                         this.push.apply( this, data.toArray ? data.toArray() : data );
6768                 }
6769         
6770                 // selector
6771                 this.selector = {
6772                         rows: null,
6773                         cols: null,
6774                         opts: null
6775                 };
6776         
6777                 _Api.extend( this, this, __apiStruct );
6778         };
6779         
6780         DataTable.Api = _Api;
6781         
6782         _Api.prototype = /** @lends DataTables.Api */{
6783                 any: function ()
6784                 {
6785                         return this.flatten().length !== 0;
6786                 },
6787         
6788         
6789                 concat:  __arrayProto.concat,
6790         
6791         
6792                 context: [], // array of table settings objects
6793         
6794         
6795                 each: function ( fn )
6796                 {
6797                         for ( var i=0, ien=this.length ; i<ien; i++ ) {
6798                                 fn.call( this, this[i], i, this );
6799                         }
6800         
6801                         return this;
6802                 },
6803         
6804         
6805                 eq: function ( idx )
6806                 {
6807                         var ctx = this.context;
6808         
6809                         return ctx.length > idx ?
6810                                 new _Api( ctx[idx], this[idx] ) :
6811                                 null;
6812                 },
6813         
6814         
6815                 filter: function ( fn )
6816                 {
6817                         var a = [];
6818         
6819                         if ( __arrayProto.filter ) {
6820                                 a = __arrayProto.filter.call( this, fn, this );
6821                         }
6822                         else {
6823                                 // Compatibility for browsers without EMCA-252-5 (JS 1.6)
6824                                 for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6825                                         if ( fn.call( this, this[i], i, this ) ) {
6826                                                 a.push( this[i] );
6827                                         }
6828                                 }
6829                         }
6830         
6831                         return new _Api( this.context, a );
6832                 },
6833         
6834         
6835                 flatten: function ()
6836                 {
6837                         var a = [];
6838                         return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
6839                 },
6840         
6841         
6842                 join:    __arrayProto.join,
6843         
6844         
6845                 indexOf: __arrayProto.indexOf || function (obj, start)
6846                 {
6847                         for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
6848                                 if ( this[i] === obj ) {
6849                                         return i;
6850                                 }
6851                         }
6852                         return -1;
6853                 },
6854         
6855                 iterator: function ( flatten, type, fn, alwaysNew ) {
6856                         var
6857                                 a = [], ret,
6858                                 i, ien, j, jen,
6859                                 context = this.context,
6860                                 rows, items, item,
6861                                 selector = this.selector;
6862         
6863                         // Argument shifting
6864                         if ( typeof flatten === 'string' ) {
6865                                 alwaysNew = fn;
6866                                 fn = type;
6867                                 type = flatten;
6868                                 flatten = false;
6869                         }
6870         
6871                         for ( i=0, ien=context.length ; i<ien ; i++ ) {
6872                                 var apiInst = new _Api( context[i] );
6873         
6874                                 if ( type === 'table' ) {
6875                                         ret = fn.call( apiInst, context[i], i );
6876         
6877                                         if ( ret !== undefined ) {
6878                                                 a.push( ret );
6879                                         }
6880                                 }
6881                                 else if ( type === 'columns' || type === 'rows' ) {
6882                                         // this has same length as context - one entry for each table
6883                                         ret = fn.call( apiInst, context[i], this[i], i );
6884         
6885                                         if ( ret !== undefined ) {
6886                                                 a.push( ret );
6887                                         }
6888                                 }
6889                                 else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
6890                                         // columns and rows share the same structure.
6891                                         // 'this' is an array of column indexes for each context
6892                                         items = this[i];
6893         
6894                                         if ( type === 'column-rows' ) {
6895                                                 rows = _selector_row_indexes( context[i], selector.opts );
6896                                         }
6897         
6898                                         for ( j=0, jen=items.length ; j<jen ; j++ ) {
6899                                                 item = items[j];
6900         
6901                                                 if ( type === 'cell' ) {
6902                                                         ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
6903                                                 }
6904                                                 else {
6905                                                         ret = fn.call( apiInst, context[i], item, i, j, rows );
6906                                                 }
6907         
6908                                                 if ( ret !== undefined ) {
6909                                                         a.push( ret );
6910                                                 }
6911                                         }
6912                                 }
6913                         }
6914         
6915                         if ( a.length || alwaysNew ) {
6916                                 var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
6917                                 var apiSelector = api.selector;
6918                                 apiSelector.rows = selector.rows;
6919                                 apiSelector.cols = selector.cols;
6920                                 apiSelector.opts = selector.opts;
6921                                 return api;
6922                         }
6923                         return this;
6924                 },
6925         
6926         
6927                 lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
6928                 {
6929                         // Bit cheeky...
6930                         return this.indexOf.apply( this.toArray.reverse(), arguments );
6931                 },
6932         
6933         
6934                 length:  0,
6935         
6936         
6937                 map: function ( fn )
6938                 {
6939                         var a = [];
6940         
6941                         if ( __arrayProto.map ) {
6942                                 a = __arrayProto.map.call( this, fn, this );
6943                         }
6944                         else {
6945                                 // Compatibility for browsers without EMCA-252-5 (JS 1.6)
6946                                 for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6947                                         a.push( fn.call( this, this[i], i ) );
6948                                 }
6949                         }
6950         
6951                         return new _Api( this.context, a );
6952                 },
6953         
6954         
6955                 pluck: function ( prop )
6956                 {
6957                         return this.map( function ( el ) {
6958                                 return el[ prop ];
6959                         } );
6960                 },
6961         
6962                 pop:     __arrayProto.pop,
6963         
6964         
6965                 push:    __arrayProto.push,
6966         
6967         
6968                 // Does not return an API instance
6969                 reduce: __arrayProto.reduce || function ( fn, init )
6970                 {
6971                         return _fnReduce( this, fn, init, 0, this.length, 1 );
6972                 },
6973         
6974         
6975                 reduceRight: __arrayProto.reduceRight || function ( fn, init )
6976                 {
6977                         return _fnReduce( this, fn, init, this.length-1, -1, -1 );
6978                 },
6979         
6980         
6981                 reverse: __arrayProto.reverse,
6982         
6983         
6984                 // Object with rows, columns and opts
6985                 selector: null,
6986         
6987         
6988                 shift:   __arrayProto.shift,
6989         
6990         
6991                 sort:    __arrayProto.sort, // ? name - order?
6992         
6993         
6994                 splice:  __arrayProto.splice,
6995         
6996         
6997                 toArray: function ()
6998                 {
6999                         return __arrayProto.slice.call( this );
7000                 },
7001         
7002         
7003                 to$: function ()
7004                 {
7005                         return $( this );
7006                 },
7007         
7008         
7009                 toJQuery: function ()
7010                 {
7011                         return $( this );
7012                 },
7013         
7014         
7015                 unique: function ()
7016                 {
7017                         return new _Api( this.context, _unique(this) );
7018                 },
7019         
7020         
7021                 unshift: __arrayProto.unshift
7022         };
7023         
7024         
7025         _Api.extend = function ( scope, obj, ext )
7026         {
7027                 // Only extend API instances and static properties of the API
7028                 if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7029                         return;
7030                 }
7031         
7032                 var
7033                         i, ien,
7034                         j, jen,
7035                         struct, inner,
7036                         methodScoping = function ( scope, fn, struc ) {
7037                                 return function () {
7038                                         var ret = fn.apply( scope, arguments );
7039         
7040                                         // Method extension
7041                                         _Api.extend( ret, ret, struc.methodExt );
7042                                         return ret;
7043                                 };
7044                         };
7045         
7046                 for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7047                         struct = ext[i];
7048         
7049                         // Value
7050                         obj[ struct.name ] = typeof struct.val === 'function' ?
7051                                 methodScoping( scope, struct.val, struct ) :
7052                                 $.isPlainObject( struct.val ) ?
7053                                         {} :
7054                                         struct.val;
7055         
7056                         obj[ struct.name ].__dt_wrapper = true;
7057         
7058                         // Property extension
7059                         _Api.extend( scope, obj[ struct.name ], struct.propExt );
7060                 }
7061         };
7062         
7063         
7064         // @todo - Is there need for an augment function?
7065         // _Api.augment = function ( inst, name )
7066         // {
7067         //      // Find src object in the structure from the name
7068         //      var parts = name.split('.');
7069         
7070         //      _Api.extend( inst, obj );
7071         // };
7072         
7073         
7074         //     [
7075         //       {
7076         //         name:      'data'                -- string   - Property name
7077         //         val:       function () {},       -- function - Api method (or undefined if just an object
7078         //         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7079         //         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7080         //       },
7081         //       {
7082         //         name:     'row'
7083         //         val:       {},
7084         //         methodExt: [ ... ],
7085         //         propExt:   [
7086         //           {
7087         //             name:      'data'
7088         //             val:       function () {},
7089         //             methodExt: [ ... ],
7090         //             propExt:   [ ... ]
7091         //           },
7092         //           ...
7093         //         ]
7094         //       }
7095         //     ]
7096         
7097         _Api.register = _api_register = function ( name, val )
7098         {
7099                 if ( $.isArray( name ) ) {
7100                         for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7101                                 _Api.register( name[j], val );
7102                         }
7103                         return;
7104                 }
7105         
7106                 var
7107                         i, ien,
7108                         heir = name.split('.'),
7109                         struct = __apiStruct,
7110                         key, method;
7111         
7112                 var find = function ( src, name ) {
7113                         for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7114                                 if ( src[i].name === name ) {
7115                                         return src[i];
7116                                 }
7117                         }
7118                         return null;
7119                 };
7120         
7121                 for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7122                         method = heir[i].indexOf('()') !== -1;
7123                         key = method ?
7124                                 heir[i].replace('()', '') :
7125                                 heir[i];
7126         
7127                         var src = find( struct, key );
7128                         if ( ! src ) {
7129                                 src = {
7130                                         name:      key,
7131                                         val:       {},
7132                                         methodExt: [],
7133                                         propExt:   []
7134                                 };
7135                                 struct.push( src );
7136                         }
7137         
7138                         if ( i === ien-1 ) {
7139                                 src.val = val;
7140                         }
7141                         else {
7142                                 struct = method ?
7143                                         src.methodExt :
7144                                         src.propExt;
7145                         }
7146                 }
7147         };
7148         
7149         
7150         _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7151                 _Api.register( pluralName, val );
7152         
7153                 _Api.register( singularName, function () {
7154                         var ret = val.apply( this, arguments );
7155         
7156                         if ( ret === this ) {
7157                                 // Returned item is the API instance that was passed in, return it
7158                                 return this;
7159                         }
7160                         else if ( ret instanceof _Api ) {
7161                                 // New API instance returned, want the value from the first item
7162                                 // in the returned array for the singular result.
7163                                 return ret.length ?
7164                                         $.isArray( ret[0] ) ?
7165                                                 new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7166                                                 ret[0] :
7167                                         undefined;
7168                         }
7169         
7170                         // Non-API return - just fire it back
7171                         return ret;
7172                 } );
7173         };
7174         
7175         
7176         /**
7177          * Selector for HTML tables. Apply the given selector to the give array of
7178          * DataTables settings objects.
7179          *
7180          * @param {string|integer} [selector] jQuery selector string or integer
7181          * @param  {array} Array of DataTables settings objects to be filtered
7182          * @return {array}
7183          * @ignore
7184          */
7185         var __table_selector = function ( selector, a )
7186         {
7187                 // Integer is used to pick out a table by index
7188                 if ( typeof selector === 'number' ) {
7189                         return [ a[ selector ] ];
7190                 }
7191         
7192                 // Perform a jQuery selector on the table nodes
7193                 var nodes = $.map( a, function (el, i) {
7194                         return el.nTable;
7195                 } );
7196         
7197                 return $(nodes)
7198                         .filter( selector )
7199                         .map( function (i) {
7200                                 // Need to translate back from the table node to the settings
7201                                 var idx = $.inArray( this, nodes );
7202                                 return a[ idx ];
7203                         } )
7204                         .toArray();
7205         };
7206         
7207         
7208         
7209         /**
7210          * Context selector for the API's context (i.e. the tables the API instance
7211          * refers to.
7212          *
7213          * @name    DataTable.Api#tables
7214          * @param {string|integer} [selector] Selector to pick which tables the iterator
7215          *   should operate on. If not given, all tables in the current context are
7216          *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7217          *   select multiple tables or as an integer to select a single table.
7218          * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7219          */
7220         _api_register( 'tables()', function ( selector ) {
7221                 // A new instance is created if there was a selector specified
7222                 return selector ?
7223                         new _Api( __table_selector( selector, this.context ) ) :
7224                         this;
7225         } );
7226         
7227         
7228         _api_register( 'table()', function ( selector ) {
7229                 var tables = this.tables( selector );
7230                 var ctx = tables.context;
7231         
7232                 // Truncate to the first matched table
7233                 return ctx.length ?
7234                         new _Api( ctx[0] ) :
7235                         tables;
7236         } );
7237         
7238         
7239         _api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7240                 return this.iterator( 'table', function ( ctx ) {
7241                         return ctx.nTable;
7242                 }, 1 );
7243         } );
7244         
7245         
7246         _api_registerPlural( 'tables().body()', 'table().body()' , function () {
7247                 return this.iterator( 'table', function ( ctx ) {
7248                         return ctx.nTBody;
7249                 }, 1 );
7250         } );
7251         
7252         
7253         _api_registerPlural( 'tables().header()', 'table().header()' , function () {
7254                 return this.iterator( 'table', function ( ctx ) {
7255                         return ctx.nTHead;
7256                 }, 1 );
7257         } );
7258         
7259         
7260         _api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7261                 return this.iterator( 'table', function ( ctx ) {
7262                         return ctx.nTFoot;
7263                 }, 1 );
7264         } );
7265         
7266         
7267         _api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7268                 return this.iterator( 'table', function ( ctx ) {
7269                         return ctx.nTableWrapper;
7270                 }, 1 );
7271         } );
7272         
7273         
7274         
7275         /**
7276          * Redraw the tables in the current context.
7277          *
7278          * @param {boolean} [reset=true] Reset (default) or hold the current paging
7279          *   position. A full re-sort and re-filter is performed when this method is
7280          *   called, which is why the pagination reset is the default action.
7281          * @returns {DataTables.Api} this
7282          */
7283         _api_register( 'draw()', function ( resetPaging ) {
7284                 return this.iterator( 'table', function ( settings ) {
7285                         _fnReDraw( settings, resetPaging===false );
7286                 } );
7287         } );
7288         
7289         
7290         
7291         /**
7292          * Get the current page index.
7293          *
7294          * @return {integer} Current page index (zero based)
7295          *//**
7296          * Set the current page.
7297          *
7298          * Note that if you attempt to show a page which does not exist, DataTables will
7299          * not throw an error, but rather reset the paging.
7300          *
7301          * @param {integer|string} action The paging action to take. This can be one of:
7302          *  * `integer` - The page index to jump to
7303          *  * `string` - An action to take:
7304          *    * `first` - Jump to first page.
7305          *    * `next` - Jump to the next page
7306          *    * `previous` - Jump to previous page
7307          *    * `last` - Jump to the last page.
7308          * @returns {DataTables.Api} this
7309          */
7310         _api_register( 'page()', function ( action ) {
7311                 if ( action === undefined ) {
7312                         return this.page.info().page; // not an expensive call
7313                 }
7314         
7315                 // else, have an action to take on all tables
7316                 return this.iterator( 'table', function ( settings ) {
7317                         _fnPageChange( settings, action );
7318                 } );
7319         } );
7320         
7321         
7322         /**
7323          * Paging information for the first table in the current context.
7324          *
7325          * If you require paging information for another table, use the `table()` method
7326          * with a suitable selector.
7327          *
7328          * @return {object} Object with the following properties set:
7329          *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7330          *  * `pages` - Total number of pages
7331          *  * `start` - Display index for the first record shown on the current page
7332          *  * `end` - Display index for the last record shown on the current page
7333          *  * `length` - Display length (number of records). Note that generally `start
7334          *    + length = end`, but this is not always true, for example if there are
7335          *    only 2 records to show on the final page, with a length of 10.
7336          *  * `recordsTotal` - Full data set length
7337          *  * `recordsDisplay` - Data set length once the current filtering criterion
7338          *    are applied.
7339          */
7340         _api_register( 'page.info()', function ( action ) {
7341                 if ( this.context.length === 0 ) {
7342                         return undefined;
7343                 }
7344         
7345                 var
7346                         settings   = this.context[0],
7347                         start      = settings._iDisplayStart,
7348                         len        = settings._iDisplayLength,
7349                         visRecords = settings.fnRecordsDisplay(),
7350                         all        = len === -1;
7351         
7352                 return {
7353                         "page":           all ? 0 : Math.floor( start / len ),
7354                         "pages":          all ? 1 : Math.ceil( visRecords / len ),
7355                         "start":          start,
7356                         "end":            settings.fnDisplayEnd(),
7357                         "length":         len,
7358                         "recordsTotal":   settings.fnRecordsTotal(),
7359                         "recordsDisplay": visRecords
7360                 };
7361         } );
7362         
7363         
7364         /**
7365          * Get the current page length.
7366          *
7367          * @return {integer} Current page length. Note `-1` indicates that all records
7368          *   are to be shown.
7369          *//**
7370          * Set the current page length.
7371          *
7372          * @param {integer} Page length to set. Use `-1` to show all records.
7373          * @returns {DataTables.Api} this
7374          */
7375         _api_register( 'page.len()', function ( len ) {
7376                 // Note that we can't call this function 'length()' because `length`
7377                 // is a Javascript property of functions which defines how many arguments
7378                 // the function expects.
7379                 if ( len === undefined ) {
7380                         return this.context.length !== 0 ?
7381                                 this.context[0]._iDisplayLength :
7382                                 undefined;
7383                 }
7384         
7385                 // else, set the page length
7386                 return this.iterator( 'table', function ( settings ) {
7387                         _fnLengthChange( settings, len );
7388                 } );
7389         } );
7390         
7391         
7392         
7393         var __reload = function ( settings, holdPosition, callback ) {
7394                 // Use the draw event to trigger a callback
7395                 if ( callback ) {
7396                         var api = new _Api( settings );
7397         
7398                         api.one( 'draw', function () {
7399                                 callback( api.ajax.json() );
7400                         } );
7401                 }
7402         
7403                 if ( _fnDataSource( settings ) == 'ssp' ) {
7404                         _fnReDraw( settings, holdPosition );
7405                 }
7406                 else {
7407                         // Trigger xhr
7408                         _fnProcessingDisplay( settings, true );
7409         
7410                         _fnBuildAjax( settings, [], function( json ) {
7411                                 _fnClearTable( settings );
7412         
7413                                 var data = _fnAjaxDataSrc( settings, json );
7414                                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7415                                         _fnAddData( settings, data[i] );
7416                                 }
7417         
7418                                 _fnReDraw( settings, holdPosition );
7419                                 _fnProcessingDisplay( settings, false );
7420                         } );
7421                 }
7422         };
7423         
7424         
7425         /**
7426          * Get the JSON response from the last Ajax request that DataTables made to the
7427          * server. Note that this returns the JSON from the first table in the current
7428          * context.
7429          *
7430          * @return {object} JSON received from the server.
7431          */
7432         _api_register( 'ajax.json()', function () {
7433                 var ctx = this.context;
7434         
7435                 if ( ctx.length > 0 ) {
7436                         return ctx[0].json;
7437                 }
7438         
7439                 // else return undefined;
7440         } );
7441         
7442         
7443         /**
7444          * Get the data submitted in the last Ajax request
7445          */
7446         _api_register( 'ajax.params()', function () {
7447                 var ctx = this.context;
7448         
7449                 if ( ctx.length > 0 ) {
7450                         return ctx[0].oAjaxData;
7451                 }
7452         
7453                 // else return undefined;
7454         } );
7455         
7456         
7457         /**
7458          * Reload tables from the Ajax data source. Note that this function will
7459          * automatically re-draw the table when the remote data has been loaded.
7460          *
7461          * @param {boolean} [reset=true] Reset (default) or hold the current paging
7462          *   position. A full re-sort and re-filter is performed when this method is
7463          *   called, which is why the pagination reset is the default action.
7464          * @returns {DataTables.Api} this
7465          */
7466         _api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7467                 return this.iterator( 'table', function (settings) {
7468                         __reload( settings, resetPaging===false, callback );
7469                 } );
7470         } );
7471         
7472         
7473         /**
7474          * Get the current Ajax URL. Note that this returns the URL from the first
7475          * table in the current context.
7476          *
7477          * @return {string} Current Ajax source URL
7478          *//**
7479          * Set the Ajax URL. Note that this will set the URL for all tables in the
7480          * current context.
7481          *
7482          * @param {string} url URL to set.
7483          * @returns {DataTables.Api} this
7484          */
7485         _api_register( 'ajax.url()', function ( url ) {
7486                 var ctx = this.context;
7487         
7488                 if ( url === undefined ) {
7489                         // get
7490                         if ( ctx.length === 0 ) {
7491                                 return undefined;
7492                         }
7493                         ctx = ctx[0];
7494         
7495                         return ctx.ajax ?
7496                                 $.isPlainObject( ctx.ajax ) ?
7497                                         ctx.ajax.url :
7498                                         ctx.ajax :
7499                                 ctx.sAjaxSource;
7500                 }
7501         
7502                 // set
7503                 return this.iterator( 'table', function ( settings ) {
7504                         if ( $.isPlainObject( settings.ajax ) ) {
7505                                 settings.ajax.url = url;
7506                         }
7507                         else {
7508                                 settings.ajax = url;
7509                         }
7510                         // No need to consider sAjaxSource here since DataTables gives priority
7511                         // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7512                         // value of `sAjaxSource` redundant.
7513                 } );
7514         } );
7515         
7516         
7517         /**
7518          * Load data from the newly set Ajax URL. Note that this method is only
7519          * available when `ajax.url()` is used to set a URL. Additionally, this method
7520          * has the same effect as calling `ajax.reload()` but is provided for
7521          * convenience when setting a new URL. Like `ajax.reload()` it will
7522          * automatically redraw the table once the remote data has been loaded.
7523          *
7524          * @returns {DataTables.Api} this
7525          */
7526         _api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7527                 // Same as a reload, but makes sense to present it for easy access after a
7528                 // url change
7529                 return this.iterator( 'table', function ( ctx ) {
7530                         __reload( ctx, resetPaging===false, callback );
7531                 } );
7532         } );
7533         
7534         
7535         
7536         
7537         var _selector_run = function ( type, selector, selectFn, settings, opts )
7538         {
7539                 var
7540                         out = [], res,
7541                         a, i, ien, j, jen,
7542                         selectorType = typeof selector;
7543         
7544                 // Can't just check for isArray here, as an API or jQuery instance might be
7545                 // given with their array like look
7546                 if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7547                         selector = [ selector ];
7548                 }
7549         
7550                 for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7551                         a = selector[i] && selector[i].split ?
7552                                 selector[i].split(',') :
7553                                 [ selector[i] ];
7554         
7555                         for ( j=0, jen=a.length ; j<jen ; j++ ) {
7556                                 res = selectFn( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
7557         
7558                                 if ( res && res.length ) {
7559                                         out.push.apply( out, res );
7560                                 }
7561                         }
7562                 }
7563         
7564                 // selector extensions
7565                 var ext = _ext.selector[ type ];
7566                 if ( ext.length ) {
7567                         for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7568                                 out = ext[i]( settings, opts, out );
7569                         }
7570                 }
7571         
7572                 return out;
7573         };
7574         
7575         
7576         var _selector_opts = function ( opts )
7577         {
7578                 if ( ! opts ) {
7579                         opts = {};
7580                 }
7581         
7582                 // Backwards compatibility for 1.9- which used the terminology filter rather
7583                 // than search
7584                 if ( opts.filter && opts.search === undefined ) {
7585                         opts.search = opts.filter;
7586                 }
7587         
7588                 return $.extend( {
7589                         search: 'none',
7590                         order: 'current',
7591                         page: 'all'
7592                 }, opts );
7593         };
7594         
7595         
7596         var _selector_first = function ( inst )
7597         {
7598                 // Reduce the API instance to the first item found
7599                 for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7600                         if ( inst[i].length > 0 ) {
7601                                 // Assign the first element to the first item in the instance
7602                                 // and truncate the instance and context
7603                                 inst[0] = inst[i];
7604                                 inst[0].length = 1;
7605                                 inst.length = 1;
7606                                 inst.context = [ inst.context[i] ];
7607         
7608                                 return inst;
7609                         }
7610                 }
7611         
7612                 // Not found - return an empty instance
7613                 inst.length = 0;
7614                 return inst;
7615         };
7616         
7617         
7618         var _selector_row_indexes = function ( settings, opts )
7619         {
7620                 var
7621                         i, ien, tmp, a=[],
7622                         displayFiltered = settings.aiDisplay,
7623                         displayMaster = settings.aiDisplayMaster;
7624         
7625                 var
7626                         search = opts.search,  // none, applied, removed
7627                         order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7628                         page   = opts.page;    // all, current
7629         
7630                 if ( _fnDataSource( settings ) == 'ssp' ) {
7631                         // In server-side processing mode, most options are irrelevant since
7632                         // rows not shown don't exist and the index order is the applied order
7633                         // Removed is a special case - for consistency just return an empty
7634                         // array
7635                         return search === 'removed' ?
7636                                 [] :
7637                                 _range( 0, displayMaster.length );
7638                 }
7639                 else if ( page == 'current' ) {
7640                         // Current page implies that order=current and fitler=applied, since it is
7641                         // fairly senseless otherwise, regardless of what order and search actually
7642                         // are
7643                         for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7644                                 a.push( displayFiltered[i] );
7645                         }
7646                 }
7647                 else if ( order == 'current' || order == 'applied' ) {
7648                         a = search == 'none' ?
7649                                 displayMaster.slice() :                      // no search
7650                                 search == 'applied' ?
7651                                         displayFiltered.slice() :                // applied search
7652                                         $.map( displayMaster, function (el, i) { // removed search
7653                                                 return $.inArray( el, displayFiltered ) === -1 ? el : null;
7654                                         } );
7655                 }
7656                 else if ( order == 'index' || order == 'original' ) {
7657                         for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7658                                 if ( search == 'none' ) {
7659                                         a.push( i );
7660                                 }
7661                                 else { // applied | removed
7662                                         tmp = $.inArray( i, displayFiltered );
7663         
7664                                         if ((tmp === -1 && search == 'removed') ||
7665                                                 (tmp >= 0   && search == 'applied') )
7666                                         {
7667                                                 a.push( i );
7668                                         }
7669                                 }
7670                         }
7671                 }
7672         
7673                 return a;
7674         };
7675         
7676         
7677         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7678          * Rows
7679          *
7680          * {}          - no selector - use all available rows
7681          * {integer}   - row aoData index
7682          * {node}      - TR node
7683          * {string}    - jQuery selector to apply to the TR elements
7684          * {array}     - jQuery array of nodes, or simply an array of TR nodes
7685          *
7686          */
7687         
7688         
7689         var __row_selector = function ( settings, selector, opts )
7690         {
7691                 var run = function ( sel ) {
7692                         var selInt = _intVal( sel );
7693                         var i, ien;
7694         
7695                         // Short cut - selector is a number and no options provided (default is
7696                         // all records, so no need to check if the index is in there, since it
7697                         // must be - dev error if the index doesn't exist).
7698                         if ( selInt !== null && ! opts ) {
7699                                 return [ selInt ];
7700                         }
7701         
7702                         var rows = _selector_row_indexes( settings, opts );
7703         
7704                         if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7705                                 // Selector - integer
7706                                 return [ selInt ];
7707                         }
7708                         else if ( ! sel ) {
7709                                 // Selector - none
7710                                 return rows;
7711                         }
7712         
7713                         // Selector - function
7714                         if ( typeof sel === 'function' ) {
7715                                 return $.map( rows, function (idx) {
7716                                         var row = settings.aoData[ idx ];
7717                                         return sel( idx, row._aData, row.nTr ) ? idx : null;
7718                                 } );
7719                         }
7720         
7721                         // Get nodes in the order from the `rows` array with null values removed
7722                         var nodes = _removeEmpty(
7723                                 _pluck_order( settings.aoData, rows, 'nTr' )
7724                         );
7725         
7726                         // Selector - node
7727                         if ( sel.nodeName ) {
7728                                 if ( $.inArray( sel, nodes ) !== -1 ) {
7729                                         return [ sel._DT_RowIndex ]; // sel is a TR node that is in the table
7730                                                                      // and DataTables adds a prop for fast lookup
7731                                 }
7732                         }
7733         
7734                         // Selector - jQuery selector string, array of nodes or jQuery object/
7735                         // As jQuery's .filter() allows jQuery objects to be passed in filter,
7736                         // it also allows arrays, so this will cope with all three options
7737                         return $(nodes)
7738                                 .filter( sel )
7739                                 .map( function () {
7740                                         return this._DT_RowIndex;
7741                                 } )
7742                                 .toArray();
7743                 };
7744         
7745                 return _selector_run( 'row', selector, run, settings, opts );
7746         };
7747         
7748         
7749         _api_register( 'rows()', function ( selector, opts ) {
7750                 // argument shifting
7751                 if ( selector === undefined ) {
7752                         selector = '';
7753                 }
7754                 else if ( $.isPlainObject( selector ) ) {
7755                         opts = selector;
7756                         selector = '';
7757                 }
7758         
7759                 opts = _selector_opts( opts );
7760         
7761                 var inst = this.iterator( 'table', function ( settings ) {
7762                         return __row_selector( settings, selector, opts );
7763                 }, 1 );
7764         
7765                 // Want argument shifting here and in __row_selector?
7766                 inst.selector.rows = selector;
7767                 inst.selector.opts = opts;
7768         
7769                 return inst;
7770         } );
7771         
7772         _api_register( 'rows().nodes()', function () {
7773                 return this.iterator( 'row', function ( settings, row ) {
7774                         return settings.aoData[ row ].nTr || undefined;
7775                 }, 1 );
7776         } );
7777         
7778         _api_register( 'rows().data()', function () {
7779                 return this.iterator( true, 'rows', function ( settings, rows ) {
7780                         return _pluck_order( settings.aoData, rows, '_aData' );
7781                 }, 1 );
7782         } );
7783         
7784         _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
7785                 return this.iterator( 'row', function ( settings, row ) {
7786                         var r = settings.aoData[ row ];
7787                         return type === 'search' ? r._aFilterData : r._aSortData;
7788                 }, 1 );
7789         } );
7790         
7791         _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
7792                 return this.iterator( 'row', function ( settings, row ) {
7793                         _fnInvalidate( settings, row, src );
7794                 } );
7795         } );
7796         
7797         _api_registerPlural( 'rows().indexes()', 'row().index()', function () {
7798                 return this.iterator( 'row', function ( settings, row ) {
7799                         return row;
7800                 }, 1 );
7801         } );
7802         
7803         _api_registerPlural( 'rows().remove()', 'row().remove()', function () {
7804                 var that = this;
7805         
7806                 return this.iterator( 'row', function ( settings, row, thatIdx ) {
7807                         var data = settings.aoData;
7808         
7809                         data.splice( row, 1 );
7810         
7811                         // Update the _DT_RowIndex parameter on all rows in the table
7812                         for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7813                                 if ( data[i].nTr !== null ) {
7814                                         data[i].nTr._DT_RowIndex = i;
7815                                 }
7816                         }
7817         
7818                         // Remove the target row from the search array
7819                         var displayIndex = $.inArray( row, settings.aiDisplay );
7820         
7821                         // Delete from the display arrays
7822                         _fnDeleteIndex( settings.aiDisplayMaster, row );
7823                         _fnDeleteIndex( settings.aiDisplay, row );
7824                         _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
7825         
7826                         // Check for an 'overflow' they case for displaying the table
7827                         _fnLengthOverflow( settings );
7828                 } );
7829         } );
7830         
7831         
7832         _api_register( 'rows.add()', function ( rows ) {
7833                 var newRows = this.iterator( 'table', function ( settings ) {
7834                                 var row, i, ien;
7835                                 var out = [];
7836         
7837                                 for ( i=0, ien=rows.length ; i<ien ; i++ ) {
7838                                         row = rows[i];
7839         
7840                                         if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
7841                                                 out.push( _fnAddTr( settings, row )[0] );
7842                                         }
7843                                         else {
7844                                                 out.push( _fnAddData( settings, row ) );
7845                                         }
7846                                 }
7847         
7848                                 return out;
7849                         }, 1 );
7850         
7851                 // Return an Api.rows() extended instance, so rows().nodes() etc can be used
7852                 var modRows = this.rows( -1 );
7853                 modRows.pop();
7854                 modRows.push.apply( modRows, newRows.toArray() );
7855         
7856                 return modRows;
7857         } );
7858         
7859         
7860         
7861         
7862         
7863         /**
7864          *
7865          */
7866         _api_register( 'row()', function ( selector, opts ) {
7867                 return _selector_first( this.rows( selector, opts ) );
7868         } );
7869         
7870         
7871         _api_register( 'row().data()', function ( data ) {
7872                 var ctx = this.context;
7873         
7874                 if ( data === undefined ) {
7875                         // Get
7876                         return ctx.length && this.length ?
7877                                 ctx[0].aoData[ this[0] ]._aData :
7878                                 undefined;
7879                 }
7880         
7881                 // Set
7882                 ctx[0].aoData[ this[0] ]._aData = data;
7883         
7884                 // Automatically invalidate
7885                 _fnInvalidate( ctx[0], this[0], 'data' );
7886         
7887                 return this;
7888         } );
7889         
7890         
7891         _api_register( 'row().node()', function () {
7892                 var ctx = this.context;
7893         
7894                 return ctx.length && this.length ?
7895                         ctx[0].aoData[ this[0] ].nTr || null :
7896                         null;
7897         } );
7898         
7899         
7900         _api_register( 'row.add()', function ( row ) {
7901                 // Allow a jQuery object to be passed in - only a single row is added from
7902                 // it though - the first element in the set
7903                 if ( row instanceof $ && row.length ) {
7904                         row = row[0];
7905                 }
7906         
7907                 var rows = this.iterator( 'table', function ( settings ) {
7908                         if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
7909                                 return _fnAddTr( settings, row )[0];
7910                         }
7911                         return _fnAddData( settings, row );
7912                 } );
7913         
7914                 // Return an Api.rows() extended instance, with the newly added row selected
7915                 return this.row( rows[0] );
7916         } );
7917         
7918         
7919         
7920         var __details_add = function ( ctx, row, data, klass )
7921         {
7922                 // Convert to array of TR elements
7923                 var rows = [];
7924                 var addRow = function ( r, k ) {
7925                         // Recursion to allow for arrays of jQuery objects
7926                         if ( $.isArray( r ) || r instanceof $ ) {
7927                                 for ( var i=0, ien=r.length ; i<ien ; i++ ) {
7928                                         addRow( r[i], k );
7929                                 }
7930                                 return;
7931                         }
7932         
7933                         // If we get a TR element, then just add it directly - up to the dev
7934                         // to add the correct number of columns etc
7935                         if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
7936                                 rows.push( r );
7937                         }
7938                         else {
7939                                 // Otherwise create a row with a wrapper
7940                                 var created = $('<tr><td/></tr>').addClass( k );
7941                                 $('td', created)
7942                                         .addClass( k )
7943                                         .html( r )
7944                                         [0].colSpan = _fnVisbleColumns( ctx );
7945         
7946                                 rows.push( created[0] );
7947                         }
7948                 };
7949         
7950                 addRow( data, klass );
7951         
7952                 if ( row._details ) {
7953                         row._details.remove();
7954                 }
7955         
7956                 row._details = $(rows);
7957         
7958                 // If the children were already shown, that state should be retained
7959                 if ( row._detailsShow ) {
7960                         row._details.insertAfter( row.nTr );
7961                 }
7962         };
7963         
7964         
7965         var __details_remove = function ( api, idx )
7966         {
7967                 var ctx = api.context;
7968         
7969                 if ( ctx.length ) {
7970                         var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
7971         
7972                         if ( row._details ) {
7973                                 row._details.remove();
7974         
7975                                 row._detailsShow = undefined;
7976                                 row._details = undefined;
7977                         }
7978                 }
7979         };
7980         
7981         
7982         var __details_display = function ( api, show ) {
7983                 var ctx = api.context;
7984         
7985                 if ( ctx.length && api.length ) {
7986                         var row = ctx[0].aoData[ api[0] ];
7987         
7988                         if ( row._details ) {
7989                                 row._detailsShow = show;
7990         
7991                                 if ( show ) {
7992                                         row._details.insertAfter( row.nTr );
7993                                 }
7994                                 else {
7995                                         row._details.detach();
7996                                 }
7997         
7998                                 __details_events( ctx[0] );
7999                         }
8000                 }
8001         };
8002         
8003         
8004         var __details_events = function ( settings )
8005         {
8006                 var api = new _Api( settings );
8007                 var namespace = '.dt.DT_details';
8008                 var drawEvent = 'draw'+namespace;
8009                 var colvisEvent = 'column-visibility'+namespace;
8010                 var destroyEvent = 'destroy'+namespace;
8011                 var data = settings.aoData;
8012         
8013                 api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8014         
8015                 if ( _pluck( data, '_details' ).length > 0 ) {
8016                         // On each draw, insert the required elements into the document
8017                         api.on( drawEvent, function ( e, ctx ) {
8018                                 if ( settings !== ctx ) {
8019                                         return;
8020                                 }
8021         
8022                                 api.rows( {page:'current'} ).eq(0).each( function (idx) {
8023                                         // Internal data grab
8024                                         var row = data[ idx ];
8025         
8026                                         if ( row._detailsShow ) {
8027                                                 row._details.insertAfter( row.nTr );
8028                                         }
8029                                 } );
8030                         } );
8031         
8032                         // Column visibility change - update the colspan
8033                         api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8034                                 if ( settings !== ctx ) {
8035                                         return;
8036                                 }
8037         
8038                                 // Update the colspan for the details rows (note, only if it already has
8039                                 // a colspan)
8040                                 var row, visible = _fnVisbleColumns( ctx );
8041         
8042                                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8043                                         row = data[i];
8044         
8045                                         if ( row._details ) {
8046                                                 row._details.children('td[colspan]').attr('colspan', visible );
8047                                         }
8048                                 }
8049                         } );
8050         
8051                         // Table destroyed - nuke any child rows
8052                         api.on( destroyEvent, function ( e, ctx ) {
8053                                 if ( settings !== ctx ) {
8054                                         return;
8055                                 }
8056         
8057                                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8058                                         if ( data[i]._details ) {
8059                                                 __details_remove( api, i );
8060                                         }
8061                                 }
8062                         } );
8063                 }
8064         };
8065         
8066         // Strings for the method names to help minification
8067         var _emp = '';
8068         var _child_obj = _emp+'row().child';
8069         var _child_mth = _child_obj+'()';
8070         
8071         // data can be:
8072         //  tr
8073         //  string
8074         //  jQuery or array of any of the above
8075         _api_register( _child_mth, function ( data, klass ) {
8076                 var ctx = this.context;
8077         
8078                 if ( data === undefined ) {
8079                         // get
8080                         return ctx.length && this.length ?
8081                                 ctx[0].aoData[ this[0] ]._details :
8082                                 undefined;
8083                 }
8084                 else if ( data === true ) {
8085                         // show
8086                         this.child.show();
8087                 }
8088                 else if ( data === false ) {
8089                         // remove
8090                         __details_remove( this );
8091                 }
8092                 else if ( ctx.length && this.length ) {
8093                         // set
8094                         __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8095                 }
8096         
8097                 return this;
8098         } );
8099         
8100         
8101         _api_register( [
8102                 _child_obj+'.show()',
8103                 _child_mth+'.show()' // only when `child()` was called with parameters (without
8104         ], function ( show ) {   // it returns an object and this method is not executed)
8105                 __details_display( this, true );
8106                 return this;
8107         } );
8108         
8109         
8110         _api_register( [
8111                 _child_obj+'.hide()',
8112                 _child_mth+'.hide()' // only when `child()` was called with parameters (without
8113         ], function () {         // it returns an object and this method is not executed)
8114                 __details_display( this, false );
8115                 return this;
8116         } );
8117         
8118         
8119         _api_register( [
8120                 _child_obj+'.remove()',
8121                 _child_mth+'.remove()' // only when `child()` was called with parameters (without
8122         ], function () {           // it returns an object and this method is not executed)
8123                 __details_remove( this );
8124                 return this;
8125         } );
8126         
8127         
8128         _api_register( _child_obj+'.isShown()', function () {
8129                 var ctx = this.context;
8130         
8131                 if ( ctx.length && this.length ) {
8132                         // _detailsShown as false or undefined will fall through to return false
8133                         return ctx[0].aoData[ this[0] ]._detailsShow || false;
8134                 }
8135                 return false;
8136         } );
8137         
8138         
8139         
8140         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8141          * Columns
8142          *
8143          * {integer}           - column index (>=0 count from left, <0 count from right)
8144          * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8145          * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8146          * "{string}:name"     - column name
8147          * "{string}"          - jQuery selector on column header nodes
8148          *
8149          */
8150         
8151         // can be an array of these items, comma separated list, or an array of comma
8152         // separated lists
8153         
8154         var __re_column_selector = /^(.+):(name|visIdx|visible)$/;
8155         
8156         
8157         // r1 and r2 are redundant - but it means that the parameters match for the
8158         // iterator callback in columns().data()
8159         var __columnData = function ( settings, column, r1, r2, rows ) {
8160                 var a = [];
8161                 for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8162                         a.push( _fnGetCellData( settings, rows[row], column ) );
8163                 }
8164                 return a;
8165         };
8166         
8167         
8168         var __column_selector = function ( settings, selector, opts )
8169         {
8170                 var
8171                         columns = settings.aoColumns,
8172                         names = _pluck( columns, 'sName' ),
8173                         nodes = _pluck( columns, 'nTh' );
8174         
8175                 var run = function ( s ) {
8176                         var selInt = _intVal( s );
8177         
8178                         // Selector - all
8179                         if ( s === '' ) {
8180                                 return _range( columns.length );
8181                         }
8182                         
8183                         // Selector - index
8184                         if ( selInt !== null ) {
8185                                 return [ selInt >= 0 ?
8186                                         selInt : // Count from left
8187                                         columns.length + selInt // Count from right (+ because its a negative value)
8188                                 ];
8189                         }
8190                         
8191                         // Selector = function
8192                         if ( typeof s === 'function' ) {
8193                                 var rows = _selector_row_indexes( settings, opts );
8194         
8195                                 return $.map( columns, function (col, idx) {
8196                                         return s(
8197                                                         idx,
8198                                                         __columnData( settings, idx, 0, 0, rows ),
8199                                                         nodes[ idx ]
8200                                                 ) ? idx : null;
8201                                 } );
8202                         }
8203         
8204                         // jQuery or string selector
8205                         var match = typeof s === 'string' ?
8206                                 s.match( __re_column_selector ) :
8207                                 '';
8208         
8209                         if ( match ) {
8210                                 switch( match[2] ) {
8211                                         case 'visIdx':
8212                                         case 'visible':
8213                                                 var idx = parseInt( match[1], 10 );
8214                                                 // Visible index given, convert to column index
8215                                                 if ( idx < 0 ) {
8216                                                         // Counting from the right
8217                                                         var visColumns = $.map( columns, function (col,i) {
8218                                                                 return col.bVisible ? i : null;
8219                                                         } );
8220                                                         return [ visColumns[ visColumns.length + idx ] ];
8221                                                 }
8222                                                 // Counting from the left
8223                                                 return [ _fnVisibleToColumnIndex( settings, idx ) ];
8224         
8225                                         case 'name':
8226                                                 // match by name. `names` is column index complete and in order
8227                                                 return $.map( names, function (name, i) {
8228                                                         return name === match[1] ? i : null;
8229                                                 } );
8230                                 }
8231                         }
8232                         else {
8233                                 // jQuery selector on the TH elements for the columns
8234                                 return $( nodes )
8235                                         .filter( s )
8236                                         .map( function () {
8237                                                 return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8238                                         } )
8239                                         .toArray();
8240                         }
8241                 };
8242         
8243                 return _selector_run( 'column', selector, run, settings, opts );
8244         };
8245         
8246         
8247         var __setColumnVis = function ( settings, column, vis, recalc ) {
8248                 var
8249                         cols = settings.aoColumns,
8250                         col  = cols[ column ],
8251                         data = settings.aoData,
8252                         row, cells, i, ien, tr;
8253         
8254                 // Get
8255                 if ( vis === undefined ) {
8256                         return col.bVisible;
8257                 }
8258         
8259                 // Set
8260                 // No change
8261                 if ( col.bVisible === vis ) {
8262                         return;
8263                 }
8264         
8265                 if ( vis ) {
8266                         // Insert column
8267                         // Need to decide if we should use appendChild or insertBefore
8268                         var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8269         
8270                         for ( i=0, ien=data.length ; i<ien ; i++ ) {
8271                                 tr = data[i].nTr;
8272                                 cells = data[i].anCells;
8273         
8274                                 if ( tr ) {
8275                                         // insertBefore can act like appendChild if 2nd arg is null
8276                                         tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8277                                 }
8278                         }
8279                 }
8280                 else {
8281                         // Remove column
8282                         $( _pluck( settings.aoData, 'anCells', column ) ).detach();
8283                 }
8284         
8285                 // Common actions
8286                 col.bVisible = vis;
8287                 _fnDrawHead( settings, settings.aoHeader );
8288                 _fnDrawHead( settings, settings.aoFooter );
8289         
8290                 if ( recalc === undefined || recalc ) {
8291                         // Automatically adjust column sizing
8292                         _fnAdjustColumnSizing( settings );
8293         
8294                         // Realign columns for scrolling
8295                         if ( settings.oScroll.sX || settings.oScroll.sY ) {
8296                                 _fnScrollDraw( settings );
8297                         }
8298                 }
8299         
8300                 _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis] );
8301         
8302                 _fnSaveState( settings );
8303         };
8304         
8305         
8306         _api_register( 'columns()', function ( selector, opts ) {
8307                 // argument shifting
8308                 if ( selector === undefined ) {
8309                         selector = '';
8310                 }
8311                 else if ( $.isPlainObject( selector ) ) {
8312                         opts = selector;
8313                         selector = '';
8314                 }
8315         
8316                 opts = _selector_opts( opts );
8317         
8318                 var inst = this.iterator( 'table', function ( settings ) {
8319                         return __column_selector( settings, selector, opts );
8320                 }, 1 );
8321         
8322                 // Want argument shifting here and in _row_selector?
8323                 inst.selector.cols = selector;
8324                 inst.selector.opts = opts;
8325         
8326                 return inst;
8327         } );
8328         
8329         _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8330                 return this.iterator( 'column', function ( settings, column ) {
8331                         return settings.aoColumns[column].nTh;
8332                 }, 1 );
8333         } );
8334         
8335         _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8336                 return this.iterator( 'column', function ( settings, column ) {
8337                         return settings.aoColumns[column].nTf;
8338                 }, 1 );
8339         } );
8340         
8341         _api_registerPlural( 'columns().data()', 'column().data()', function () {
8342                 return this.iterator( 'column-rows', __columnData, 1 );
8343         } );
8344         
8345         _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8346                 return this.iterator( 'column', function ( settings, column ) {
8347                         return settings.aoColumns[column].mData;
8348                 }, 1 );
8349         } );
8350         
8351         _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8352                 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8353                         return _pluck_order( settings.aoData, rows,
8354                                 type === 'search' ? '_aFilterData' : '_aSortData', column
8355                         );
8356                 }, 1 );
8357         } );
8358         
8359         _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8360                 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8361                         return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8362                 }, 1 );
8363         } );
8364         
8365         _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8366                 return this.iterator( 'column', function ( settings, column ) {
8367                         if ( vis === undefined ) {
8368                                 return settings.aoColumns[ column ].bVisible;
8369                         } // else
8370                         __setColumnVis( settings, column, vis, calc );
8371                 } );
8372         } );
8373         
8374         _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8375                 return this.iterator( 'column', function ( settings, column ) {
8376                         return type === 'visible' ?
8377                                 _fnColumnIndexToVisible( settings, column ) :
8378                                 column;
8379                 }, 1 );
8380         } );
8381         
8382         _api_register( 'columns.adjust()', function () {
8383                 return this.iterator( 'table', function ( settings ) {
8384                         _fnAdjustColumnSizing( settings );
8385                 }, 1 );
8386         } );
8387         
8388         _api_register( 'column.index()', function ( type, idx ) {
8389                 if ( this.context.length !== 0 ) {
8390                         var ctx = this.context[0];
8391         
8392                         if ( type === 'fromVisible' || type === 'toData' ) {
8393                                 return _fnVisibleToColumnIndex( ctx, idx );
8394                         }
8395                         else if ( type === 'fromData' || type === 'toVisible' ) {
8396                                 return _fnColumnIndexToVisible( ctx, idx );
8397                         }
8398                 }
8399         } );
8400         
8401         _api_register( 'column()', function ( selector, opts ) {
8402                 return _selector_first( this.columns( selector, opts ) );
8403         } );
8404         
8405         
8406         
8407         
8408         var __cell_selector = function ( settings, selector, opts )
8409         {
8410                 var data = settings.aoData;
8411                 var rows = _selector_row_indexes( settings, opts );
8412                 var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8413                 var allCells = $( [].concat.apply([], cells) );
8414                 var row;
8415                 var columns = settings.aoColumns.length;
8416                 var a, i, ien, j, o, host;
8417         
8418                 var run = function ( s ) {
8419                         var fnSelector = typeof s === 'function';
8420         
8421                         if ( s === null || s === undefined || fnSelector ) {
8422                                 // All cells and function selectors
8423                                 a = [];
8424         
8425                                 for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8426                                         row = rows[i];
8427         
8428                                         for ( j=0 ; j<columns ; j++ ) {
8429                                                 o = {
8430                                                         row: row,
8431                                                         column: j
8432                                                 };
8433         
8434                                                 if ( fnSelector ) {
8435                                                         // Selector - function
8436                                                         host = settings.aoData[ row ];
8437         
8438                                                         if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8439                                                                 a.push( o );
8440                                                         }
8441                                                 }
8442                                                 else {
8443                                                         // Selector - all
8444                                                         a.push( o );
8445                                                 }
8446                                         }
8447                                 }
8448         
8449                                 return a;
8450                         }
8451                         
8452                         // Selector - index
8453                         if ( $.isPlainObject( s ) ) {
8454                                 return [s];
8455                         }
8456         
8457                         // Selector - jQuery filtered cells
8458                         return allCells
8459                                 .filter( s )
8460                                 .map( function (i, el) {
8461                                         row = el.parentNode._DT_RowIndex;
8462         
8463                                         return {
8464                                                 row: row,
8465                                                 column: $.inArray( el, data[ row ].anCells )
8466                                         };
8467                                 } )
8468                                 .toArray();
8469                 };
8470         
8471                 return _selector_run( 'cell', selector, run, settings, opts );
8472         };
8473         
8474         
8475         
8476         
8477         _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8478                 // Argument shifting
8479                 if ( $.isPlainObject( rowSelector ) ) {
8480                         // Indexes
8481                         if ( rowSelector.row === undefined ) {
8482                                 // Selector options in first parameter
8483                                 opts = rowSelector;
8484                                 rowSelector = null;
8485                         }
8486                         else {
8487                                 // Cell index objects in first parameter
8488                                 opts = columnSelector;
8489                                 columnSelector = null;
8490                         }
8491                 }
8492                 if ( $.isPlainObject( columnSelector ) ) {
8493                         opts = columnSelector;
8494                         columnSelector = null;
8495                 }
8496         
8497                 // Cell selector
8498                 if ( columnSelector === null || columnSelector === undefined ) {
8499                         return this.iterator( 'table', function ( settings ) {
8500                                 return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8501                         } );
8502                 }
8503         
8504                 // Row + column selector
8505                 var columns = this.columns( columnSelector, opts );
8506                 var rows = this.rows( rowSelector, opts );
8507                 var a, i, ien, j, jen;
8508         
8509                 var cells = this.iterator( 'table', function ( settings, idx ) {
8510                         a = [];
8511         
8512                         for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
8513                                 for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
8514                                         a.push( {
8515                                                 row:    rows[idx][i],
8516                                                 column: columns[idx][j]
8517                                         } );
8518                                 }
8519                         }
8520         
8521                         return a;
8522                 }, 1 );
8523         
8524                 $.extend( cells.selector, {
8525                         cols: columnSelector,
8526                         rows: rowSelector,
8527                         opts: opts
8528                 } );
8529         
8530                 return cells;
8531         } );
8532         
8533         
8534         _api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8535                 return this.iterator( 'cell', function ( settings, row, column ) {
8536                         var cells = settings.aoData[ row ].anCells;
8537                         return cells ?
8538                                 cells[ column ] :
8539                                 undefined;
8540                 }, 1 );
8541         } );
8542         
8543         
8544         _api_register( 'cells().data()', function () {
8545                 return this.iterator( 'cell', function ( settings, row, column ) {
8546                         return _fnGetCellData( settings, row, column );
8547                 }, 1 );
8548         } );
8549         
8550         
8551         _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8552                 type = type === 'search' ? '_aFilterData' : '_aSortData';
8553         
8554                 return this.iterator( 'cell', function ( settings, row, column ) {
8555                         return settings.aoData[ row ][ type ][ column ];
8556                 }, 1 );
8557         } );
8558         
8559         
8560         _api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
8561                 return this.iterator( 'cell', function ( settings, row, column ) {
8562                         return _fnGetCellData( settings, row, column, type );
8563                 }, 1 );
8564         } );
8565         
8566         
8567         _api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8568                 return this.iterator( 'cell', function ( settings, row, column ) {
8569                         return {
8570                                 row: row,
8571                                 column: column,
8572                                 columnVisible: _fnColumnIndexToVisible( settings, column )
8573                         };
8574                 }, 1 );
8575         } );
8576         
8577         
8578         _api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
8579                 return this.iterator( 'cell', function ( settings, row, column ) {
8580                         _fnInvalidate( settings, row, src, column );
8581                 } );
8582         } );
8583         
8584         
8585         
8586         _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8587                 return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8588         } );
8589         
8590         
8591         _api_register( 'cell().data()', function ( data ) {
8592                 var ctx = this.context;
8593                 var cell = this[0];
8594         
8595                 if ( data === undefined ) {
8596                         // Get
8597                         return ctx.length && cell.length ?
8598                                 _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8599                                 undefined;
8600                 }
8601         
8602                 // Set
8603                 _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8604                 _fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
8605         
8606                 return this;
8607         } );
8608         
8609         
8610         
8611         /**
8612          * Get current ordering (sorting) that has been applied to the table.
8613          *
8614          * @returns {array} 2D array containing the sorting information for the first
8615          *   table in the current context. Each element in the parent array represents
8616          *   a column being sorted upon (i.e. multi-sorting with two columns would have
8617          *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8618          *   the column index that the sorting condition applies to, the second is the
8619          *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8620          *   index of the sorting order from the `column.sorting` initialisation array.
8621          *//**
8622          * Set the ordering for the table.
8623          *
8624          * @param {integer} order Column index to sort upon.
8625          * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8626          * @returns {DataTables.Api} this
8627          *//**
8628          * Set the ordering for the table.
8629          *
8630          * @param {array} order 1D array of sorting information to be applied.
8631          * @param {array} [...] Optional additional sorting conditions
8632          * @returns {DataTables.Api} this
8633          *//**
8634          * Set the ordering for the table.
8635          *
8636          * @param {array} order 2D array of sorting information to be applied.
8637          * @returns {DataTables.Api} this
8638          */
8639         _api_register( 'order()', function ( order, dir ) {
8640                 var ctx = this.context;
8641         
8642                 if ( order === undefined ) {
8643                         // get
8644                         return ctx.length !== 0 ?
8645                                 ctx[0].aaSorting :
8646                                 undefined;
8647                 }
8648         
8649                 // set
8650                 if ( typeof order === 'number' ) {
8651                         // Simple column / direction passed in
8652                         order = [ [ order, dir ] ];
8653                 }
8654                 else if ( ! $.isArray( order[0] ) ) {
8655                         // Arguments passed in (list of 1D arrays)
8656                         order = Array.prototype.slice.call( arguments );
8657                 }
8658                 // otherwise a 2D array was passed in
8659         
8660                 return this.iterator( 'table', function ( settings ) {
8661                         settings.aaSorting = order.slice();
8662                 } );
8663         } );
8664         
8665         
8666         /**
8667          * Attach a sort listener to an element for a given column
8668          *
8669          * @param {node|jQuery|string} node Identifier for the element(s) to attach the
8670          *   listener to. This can take the form of a single DOM node, a jQuery
8671          *   collection of nodes or a jQuery selector which will identify the node(s).
8672          * @param {integer} column the column that a click on this node will sort on
8673          * @param {function} [callback] callback function when sort is run
8674          * @returns {DataTables.Api} this
8675          */
8676         _api_register( 'order.listener()', function ( node, column, callback ) {
8677                 return this.iterator( 'table', function ( settings ) {
8678                         _fnSortAttachListener( settings, node, column, callback );
8679                 } );
8680         } );
8681         
8682         
8683         // Order by the selected column(s)
8684         _api_register( [
8685                 'columns().order()',
8686                 'column().order()'
8687         ], function ( dir ) {
8688                 var that = this;
8689         
8690                 return this.iterator( 'table', function ( settings, i ) {
8691                         var sort = [];
8692         
8693                         $.each( that[i], function (j, col) {
8694                                 sort.push( [ col, dir ] );
8695                         } );
8696         
8697                         settings.aaSorting = sort;
8698                 } );
8699         } );
8700         
8701         
8702         
8703         _api_register( 'search()', function ( input, regex, smart, caseInsen ) {
8704                 var ctx = this.context;
8705         
8706                 if ( input === undefined ) {
8707                         // get
8708                         return ctx.length !== 0 ?
8709                                 ctx[0].oPreviousSearch.sSearch :
8710                                 undefined;
8711                 }
8712         
8713                 // set
8714                 return this.iterator( 'table', function ( settings ) {
8715                         if ( ! settings.oFeatures.bFilter ) {
8716                                 return;
8717                         }
8718         
8719                         _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
8720                                 "sSearch": input+"",
8721                                 "bRegex":  regex === null ? false : regex,
8722                                 "bSmart":  smart === null ? true  : smart,
8723                                 "bCaseInsensitive": caseInsen === null ? true : caseInsen
8724                         } ), 1 );
8725                 } );
8726         } );
8727         
8728         
8729         _api_registerPlural(
8730                 'columns().search()',
8731                 'column().search()',
8732                 function ( input, regex, smart, caseInsen ) {
8733                         return this.iterator( 'column', function ( settings, column ) {
8734                                 var preSearch = settings.aoPreSearchCols;
8735         
8736                                 if ( input === undefined ) {
8737                                         // get
8738                                         return preSearch[ column ].sSearch;
8739                                 }
8740         
8741                                 // set
8742                                 if ( ! settings.oFeatures.bFilter ) {
8743                                         return;
8744                                 }
8745         
8746                                 $.extend( preSearch[ column ], {
8747                                         "sSearch": input+"",
8748                                         "bRegex":  regex === null ? false : regex,
8749                                         "bSmart":  smart === null ? true  : smart,
8750                                         "bCaseInsensitive": caseInsen === null ? true : caseInsen
8751                                 } );
8752         
8753                                 _fnFilterComplete( settings, settings.oPreviousSearch, 1 );
8754                         } );
8755                 }
8756         );
8757         
8758         /*
8759          * State API methods
8760          */
8761         
8762         _api_register( 'state()', function () {
8763                 return this.context.length ?
8764                         this.context[0].oSavedState :
8765                         null;
8766         } );
8767         
8768         
8769         _api_register( 'state.clear()', function () {
8770                 return this.iterator( 'table', function ( settings ) {
8771                         // Save an empty object
8772                         settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
8773                 } );
8774         } );
8775         
8776         
8777         _api_register( 'state.loaded()', function () {
8778                 return this.context.length ?
8779                         this.context[0].oLoadedState :
8780                         null;
8781         } );
8782         
8783         
8784         _api_register( 'state.save()', function () {
8785                 return this.iterator( 'table', function ( settings ) {
8786                         _fnSaveState( settings );
8787                 } );
8788         } );
8789         
8790         
8791         
8792         /**
8793          * Provide a common method for plug-ins to check the version of DataTables being
8794          * used, in order to ensure compatibility.
8795          *
8796          *  @param {string} version Version string to check for, in the format "X.Y.Z".
8797          *    Note that the formats "X" and "X.Y" are also acceptable.
8798          *  @returns {boolean} true if this version of DataTables is greater or equal to
8799          *    the required version, or false if this version of DataTales is not
8800          *    suitable
8801          *  @static
8802          *  @dtopt API-Static
8803          *
8804          *  @example
8805          *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
8806          */
8807         DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
8808         {
8809                 var aThis = DataTable.version.split('.');
8810                 var aThat = version.split('.');
8811                 var iThis, iThat;
8812         
8813                 for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
8814                         iThis = parseInt( aThis[i], 10 ) || 0;
8815                         iThat = parseInt( aThat[i], 10 ) || 0;
8816         
8817                         // Parts are the same, keep comparing
8818                         if (iThis === iThat) {
8819                                 continue;
8820                         }
8821         
8822                         // Parts are different, return immediately
8823                         return iThis > iThat;
8824                 }
8825         
8826                 return true;
8827         };
8828         
8829         
8830         /**
8831          * Check if a `<table>` node is a DataTable table already or not.
8832          *
8833          *  @param {node|jquery|string} table Table node, jQuery object or jQuery
8834          *      selector for the table to test. Note that if more than more than one
8835          *      table is passed on, only the first will be checked
8836          *  @returns {boolean} true the table given is a DataTable, or false otherwise
8837          *  @static
8838          *  @dtopt API-Static
8839          *
8840          *  @example
8841          *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
8842          *      $('#example').dataTable();
8843          *    }
8844          */
8845         DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
8846         {
8847                 var t = $(table).get(0);
8848                 var is = false;
8849         
8850                 $.each( DataTable.settings, function (i, o) {
8851                         var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
8852                         var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
8853         
8854                         if ( o.nTable === t || head === t || foot === t ) {
8855                                 is = true;
8856                         }
8857                 } );
8858         
8859                 return is;
8860         };
8861         
8862         
8863         /**
8864          * Get all DataTable tables that have been initialised - optionally you can
8865          * select to get only currently visible tables.
8866          *
8867          *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
8868          *    or visible tables only.
8869          *  @returns {array} Array of `table` nodes (not DataTable instances) which are
8870          *    DataTables
8871          *  @static
8872          *  @dtopt API-Static
8873          *
8874          *  @example
8875          *    $.each( $.fn.dataTable.tables(true), function () {
8876          *      $(table).DataTable().columns.adjust();
8877          *    } );
8878          */
8879         DataTable.tables = DataTable.fnTables = function ( visible )
8880         {
8881                 return $.map( DataTable.settings, function (o) {
8882                         if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
8883                                 return o.nTable;
8884                         }
8885                 } );
8886         };
8887         
8888         
8889         /**
8890          * DataTables utility methods
8891          * 
8892          * This namespace provides helper methods that DataTables uses internally to
8893          * create a DataTable, but which are not exclusively used only for DataTables.
8894          * These methods can be used by extension authors to save the duplication of
8895          * code.
8896          *
8897          *  @namespace
8898          */
8899         DataTable.util = {
8900                 /**
8901                  * Throttle the calls to a function. Arguments and context are maintained
8902                  * for the throttled function.
8903                  *
8904                  * @param {function} fn Function to be called
8905                  * @param {integer} freq Call frequency in mS
8906                  * @return {function} Wrapped function
8907                  */
8908                 throttle: _fnThrottle,
8909         
8910         
8911                 /**
8912                  * Escape a string such that it can be used in a regular expression
8913                  *
8914                  *  @param {string} sVal string to escape
8915                  *  @returns {string} escaped string
8916                  */
8917                 escapeRegex: _fnEscapeRegex
8918         };
8919         
8920         
8921         /**
8922          * Convert from camel case parameters to Hungarian notation. This is made public
8923          * for the extensions to provide the same ability as DataTables core to accept
8924          * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
8925          * parameters.
8926          *
8927          *  @param {object} src The model object which holds all parameters that can be
8928          *    mapped.
8929          *  @param {object} user The object to convert from camel case to Hungarian.
8930          *  @param {boolean} force When set to `true`, properties which already have a
8931          *    Hungarian value in the `user` object will be overwritten. Otherwise they
8932          *    won't be.
8933          */
8934         DataTable.camelToHungarian = _fnCamelToHungarian;
8935         
8936         
8937         
8938         /**
8939          *
8940          */
8941         _api_register( '$()', function ( selector, opts ) {
8942                 var
8943                         rows   = this.rows( opts ).nodes(), // Get all rows
8944                         jqRows = $(rows);
8945         
8946                 return $( [].concat(
8947                         jqRows.filter( selector ).toArray(),
8948                         jqRows.find( selector ).toArray()
8949                 ) );
8950         } );
8951         
8952         
8953         // jQuery functions to operate on the tables
8954         $.each( [ 'on', 'one', 'off' ], function (i, key) {
8955                 _api_register( key+'()', function ( /* event, handler */ ) {
8956                         var args = Array.prototype.slice.call(arguments);
8957         
8958                         // Add the `dt` namespace automatically if it isn't already present
8959                         if ( ! args[0].match(/\.dt\b/) ) {
8960                                 args[0] += '.dt';
8961                         }
8962         
8963                         var inst = $( this.tables().nodes() );
8964                         inst[key].apply( inst, args );
8965                         return this;
8966                 } );
8967         } );
8968         
8969         
8970         _api_register( 'clear()', function () {
8971                 return this.iterator( 'table', function ( settings ) {
8972                         _fnClearTable( settings );
8973                 } );
8974         } );
8975         
8976         
8977         _api_register( 'settings()', function () {
8978                 return new _Api( this.context, this.context );
8979         } );
8980         
8981         
8982         _api_register( 'init()', function () {
8983                 var ctx = this.context;
8984                 return ctx.length ? ctx[0].oInit : null;
8985         } );
8986         
8987         
8988         _api_register( 'data()', function () {
8989                 return this.iterator( 'table', function ( settings ) {
8990                         return _pluck( settings.aoData, '_aData' );
8991                 } ).flatten();
8992         } );
8993         
8994         
8995         _api_register( 'destroy()', function ( remove ) {
8996                 remove = remove || false;
8997         
8998                 return this.iterator( 'table', function ( settings ) {
8999                         var orig      = settings.nTableWrapper.parentNode;
9000                         var classes   = settings.oClasses;
9001                         var table     = settings.nTable;
9002                         var tbody     = settings.nTBody;
9003                         var thead     = settings.nTHead;
9004                         var tfoot     = settings.nTFoot;
9005                         var jqTable   = $(table);
9006                         var jqTbody   = $(tbody);
9007                         var jqWrapper = $(settings.nTableWrapper);
9008                         var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9009                         var i, ien;
9010         
9011                         // Flag to note that the table is currently being destroyed - no action
9012                         // should be taken
9013                         settings.bDestroying = true;
9014         
9015                         // Fire off the destroy callbacks for plug-ins etc
9016                         _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9017         
9018                         // If not being removed from the document, make all columns visible
9019                         if ( ! remove ) {
9020                                 new _Api( settings ).columns().visible( true );
9021                         }
9022         
9023                         // Blitz all `DT` namespaced events (these are internal events, the
9024                         // lowercase, `dt` events are user subscribed and they are responsible
9025                         // for removing them
9026                         jqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT');
9027                         $(window).unbind('.DT-'+settings.sInstance);
9028         
9029                         // When scrolling we had to break the table up - restore it
9030                         if ( table != thead.parentNode ) {
9031                                 jqTable.children('thead').detach();
9032                                 jqTable.append( thead );
9033                         }
9034         
9035                         if ( tfoot && table != tfoot.parentNode ) {
9036                                 jqTable.children('tfoot').detach();
9037                                 jqTable.append( tfoot );
9038                         }
9039         
9040                         // Remove the DataTables generated nodes, events and classes
9041                         jqTable.detach();
9042                         jqWrapper.detach();
9043         
9044                         settings.aaSorting = [];
9045                         settings.aaSortingFixed = [];
9046                         _fnSortingClasses( settings );
9047         
9048                         $( rows ).removeClass( settings.asStripeClasses.join(' ') );
9049         
9050                         $('th, td', thead).removeClass( classes.sSortable+' '+
9051                                 classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9052                         );
9053         
9054                         if ( settings.bJUI ) {
9055                                 $('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach();
9056                                 $('th, td', thead).each( function () {
9057                                         var wrapper = $('div.'+classes.sSortJUIWrapper, this);
9058                                         $(this).append( wrapper.contents() );
9059                                         wrapper.detach();
9060                                 } );
9061                         }
9062         
9063                         if ( ! remove && orig ) {
9064                                 // insertBefore acts like appendChild if !arg[1]
9065                                 orig.insertBefore( table, settings.nTableReinsertBefore );
9066                         }
9067         
9068                         // Add the TR elements back into the table in their original order
9069                         jqTbody.children().detach();
9070                         jqTbody.append( rows );
9071         
9072                         // Restore the width of the original table - was read from the style property,
9073                         // so we can restore directly to that
9074                         jqTable
9075                                 .css( 'width', settings.sDestroyWidth )
9076                                 .removeClass( classes.sTable );
9077         
9078                         // If the were originally stripe classes - then we add them back here.
9079                         // Note this is not fool proof (for example if not all rows had stripe
9080                         // classes - but it's a good effort without getting carried away
9081                         ien = settings.asDestroyStripes.length;
9082         
9083                         if ( ien ) {
9084                                 jqTbody.children().each( function (i) {
9085                                         $(this).addClass( settings.asDestroyStripes[i % ien] );
9086                                 } );
9087                         }
9088         
9089                         /* Remove the settings object from the settings array */
9090                         var idx = $.inArray( settings, DataTable.settings );
9091                         if ( idx !== -1 ) {
9092                                 DataTable.settings.splice( idx, 1 );
9093                         }
9094                 } );
9095         } );
9096         
9097         
9098         // Add the `every()` method for rows, columns and cells in a compact form
9099         $.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9100                 _api_register( type+'s().every()', function ( fn ) {
9101                         return this.iterator( type, function ( settings, idx, idx2 ) {
9102                                 // idx2 is undefined for rows and columns.
9103                                 fn.call( new _Api( settings )[ type ]( idx, idx2 ) );
9104                         } );
9105                 } );
9106         } );
9107         
9108         
9109         // i18n method for extensions to be able to use the language object from the
9110         // DataTable
9111         _api_register( 'i18n()', function ( token, def, plural ) {
9112                 var ctx = this.context[0];
9113                 var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9114         
9115                 if ( resolved === undefined ) {
9116                         resolved = def;
9117                 }
9118         
9119                 if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9120                         resolved = resolved[ plural ] !== undefined ?
9121                                 resolved[ plural ] :
9122                                 resolved._;
9123                 }
9124         
9125                 return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9126         } );
9127
9128         /**
9129          * Version string for plug-ins to check compatibility. Allowed format is
9130          * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9131          * only for non-release builds. See http://semver.org/ for more information.
9132          *  @member
9133          *  @type string
9134          *  @default Version number
9135          */
9136         DataTable.version = "1.10.7";
9137
9138         /**
9139          * Private data store, containing all of the settings objects that are
9140          * created for the tables on a given page.
9141          *
9142          * Note that the `DataTable.settings` object is aliased to
9143          * `jQuery.fn.dataTableExt` through which it may be accessed and
9144          * manipulated, or `jQuery.fn.dataTable.settings`.
9145          *  @member
9146          *  @type array
9147          *  @default []
9148          *  @private
9149          */
9150         DataTable.settings = [];
9151
9152         /**
9153          * Object models container, for the various models that DataTables has
9154          * available to it. These models define the objects that are used to hold
9155          * the active state and configuration of the table.
9156          *  @namespace
9157          */
9158         DataTable.models = {};
9159         
9160         
9161         
9162         /**
9163          * Template object for the way in which DataTables holds information about
9164          * search information for the global filter and individual column filters.
9165          *  @namespace
9166          */
9167         DataTable.models.oSearch = {
9168                 /**
9169                  * Flag to indicate if the filtering should be case insensitive or not
9170                  *  @type boolean
9171                  *  @default true
9172                  */
9173                 "bCaseInsensitive": true,
9174         
9175                 /**
9176                  * Applied search term
9177                  *  @type string
9178                  *  @default <i>Empty string</i>
9179                  */
9180                 "sSearch": "",
9181         
9182                 /**
9183                  * Flag to indicate if the search term should be interpreted as a
9184                  * regular expression (true) or not (false) and therefore and special
9185                  * regex characters escaped.
9186                  *  @type boolean
9187                  *  @default false
9188                  */
9189                 "bRegex": false,
9190         
9191                 /**
9192                  * Flag to indicate if DataTables is to use its smart filtering or not.
9193                  *  @type boolean
9194                  *  @default true
9195                  */
9196                 "bSmart": true
9197         };
9198         
9199         
9200         
9201         
9202         /**
9203          * Template object for the way in which DataTables holds information about
9204          * each individual row. This is the object format used for the settings
9205          * aoData array.
9206          *  @namespace
9207          */
9208         DataTable.models.oRow = {
9209                 /**
9210                  * TR element for the row
9211                  *  @type node
9212                  *  @default null
9213                  */
9214                 "nTr": null,
9215         
9216                 /**
9217                  * Array of TD elements for each row. This is null until the row has been
9218                  * created.
9219                  *  @type array nodes
9220                  *  @default []
9221                  */
9222                 "anCells": null,
9223         
9224                 /**
9225                  * Data object from the original data source for the row. This is either
9226                  * an array if using the traditional form of DataTables, or an object if
9227                  * using mData options. The exact type will depend on the passed in
9228                  * data from the data source, or will be an array if using DOM a data
9229                  * source.
9230                  *  @type array|object
9231                  *  @default []
9232                  */
9233                 "_aData": [],
9234         
9235                 /**
9236                  * Sorting data cache - this array is ostensibly the same length as the
9237                  * number of columns (although each index is generated only as it is
9238                  * needed), and holds the data that is used for sorting each column in the
9239                  * row. We do this cache generation at the start of the sort in order that
9240                  * the formatting of the sort data need be done only once for each cell
9241                  * per sort. This array should not be read from or written to by anything
9242                  * other than the master sorting methods.
9243                  *  @type array
9244                  *  @default null
9245                  *  @private
9246                  */
9247                 "_aSortData": null,
9248         
9249                 /**
9250                  * Per cell filtering data cache. As per the sort data cache, used to
9251                  * increase the performance of the filtering in DataTables
9252                  *  @type array
9253                  *  @default null
9254                  *  @private
9255                  */
9256                 "_aFilterData": null,
9257         
9258                 /**
9259                  * Filtering data cache. This is the same as the cell filtering cache, but
9260                  * in this case a string rather than an array. This is easily computed with
9261                  * a join on `_aFilterData`, but is provided as a cache so the join isn't
9262                  * needed on every search (memory traded for performance)
9263                  *  @type array
9264                  *  @default null
9265                  *  @private
9266                  */
9267                 "_sFilterRow": null,
9268         
9269                 /**
9270                  * Cache of the class name that DataTables has applied to the row, so we
9271                  * can quickly look at this variable rather than needing to do a DOM check
9272                  * on className for the nTr property.
9273                  *  @type string
9274                  *  @default <i>Empty string</i>
9275                  *  @private
9276                  */
9277                 "_sRowStripe": "",
9278         
9279                 /**
9280                  * Denote if the original data source was from the DOM, or the data source
9281                  * object. This is used for invalidating data, so DataTables can
9282                  * automatically read data from the original source, unless uninstructed
9283                  * otherwise.
9284                  *  @type string
9285                  *  @default null
9286                  *  @private
9287                  */
9288                 "src": null
9289         };
9290         
9291         
9292         /**
9293          * Template object for the column information object in DataTables. This object
9294          * is held in the settings aoColumns array and contains all the information that
9295          * DataTables needs about each individual column.
9296          *
9297          * Note that this object is related to {@link DataTable.defaults.column}
9298          * but this one is the internal data store for DataTables's cache of columns.
9299          * It should NOT be manipulated outside of DataTables. Any configuration should
9300          * be done through the initialisation options.
9301          *  @namespace
9302          */
9303         DataTable.models.oColumn = {
9304                 /**
9305                  * Column index. This could be worked out on-the-fly with $.inArray, but it
9306                  * is faster to just hold it as a variable
9307                  *  @type integer
9308                  *  @default null
9309                  */
9310                 "idx": null,
9311         
9312                 /**
9313                  * A list of the columns that sorting should occur on when this column
9314                  * is sorted. That this property is an array allows multi-column sorting
9315                  * to be defined for a column (for example first name / last name columns
9316                  * would benefit from this). The values are integers pointing to the
9317                  * columns to be sorted on (typically it will be a single integer pointing
9318                  * at itself, but that doesn't need to be the case).
9319                  *  @type array
9320                  */
9321                 "aDataSort": null,
9322         
9323                 /**
9324                  * Define the sorting directions that are applied to the column, in sequence
9325                  * as the column is repeatedly sorted upon - i.e. the first value is used
9326                  * as the sorting direction when the column if first sorted (clicked on).
9327                  * Sort it again (click again) and it will move on to the next index.
9328                  * Repeat until loop.
9329                  *  @type array
9330                  */
9331                 "asSorting": null,
9332         
9333                 /**
9334                  * Flag to indicate if the column is searchable, and thus should be included
9335                  * in the filtering or not.
9336                  *  @type boolean
9337                  */
9338                 "bSearchable": null,
9339         
9340                 /**
9341                  * Flag to indicate if the column is sortable or not.
9342                  *  @type boolean
9343                  */
9344                 "bSortable": null,
9345         
9346                 /**
9347                  * Flag to indicate if the column is currently visible in the table or not
9348                  *  @type boolean
9349                  */
9350                 "bVisible": null,
9351         
9352                 /**
9353                  * Store for manual type assignment using the `column.type` option. This
9354                  * is held in store so we can manipulate the column's `sType` property.
9355                  *  @type string
9356                  *  @default null
9357                  *  @private
9358                  */
9359                 "_sManualType": null,
9360         
9361                 /**
9362                  * Flag to indicate if HTML5 data attributes should be used as the data
9363                  * source for filtering or sorting. True is either are.
9364                  *  @type boolean
9365                  *  @default false
9366                  *  @private
9367                  */
9368                 "_bAttrSrc": false,
9369         
9370                 /**
9371                  * Developer definable function that is called whenever a cell is created (Ajax source,
9372                  * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9373                  * allowing you to modify the DOM element (add background colour for example) when the
9374                  * element is available.
9375                  *  @type function
9376                  *  @param {element} nTd The TD node that has been created
9377                  *  @param {*} sData The Data for the cell
9378                  *  @param {array|object} oData The data for the whole row
9379                  *  @param {int} iRow The row index for the aoData data store
9380                  *  @default null
9381                  */
9382                 "fnCreatedCell": null,
9383         
9384                 /**
9385                  * Function to get data from a cell in a column. You should <b>never</b>
9386                  * access data directly through _aData internally in DataTables - always use
9387                  * the method attached to this property. It allows mData to function as
9388                  * required. This function is automatically assigned by the column
9389                  * initialisation method
9390                  *  @type function
9391                  *  @param {array|object} oData The data array/object for the array
9392                  *    (i.e. aoData[]._aData)
9393                  *  @param {string} sSpecific The specific data type you want to get -
9394                  *    'display', 'type' 'filter' 'sort'
9395                  *  @returns {*} The data for the cell from the given row's data
9396                  *  @default null
9397                  */
9398                 "fnGetData": null,
9399         
9400                 /**
9401                  * Function to set data for a cell in the column. You should <b>never</b>
9402                  * set the data directly to _aData internally in DataTables - always use
9403                  * this method. It allows mData to function as required. This function
9404                  * is automatically assigned by the column initialisation method
9405                  *  @type function
9406                  *  @param {array|object} oData The data array/object for the array
9407                  *    (i.e. aoData[]._aData)
9408                  *  @param {*} sValue Value to set
9409                  *  @default null
9410                  */
9411                 "fnSetData": null,
9412         
9413                 /**
9414                  * Property to read the value for the cells in the column from the data
9415                  * source array / object. If null, then the default content is used, if a
9416                  * function is given then the return from the function is used.
9417                  *  @type function|int|string|null
9418                  *  @default null
9419                  */
9420                 "mData": null,
9421         
9422                 /**
9423                  * Partner property to mData which is used (only when defined) to get
9424                  * the data - i.e. it is basically the same as mData, but without the
9425                  * 'set' option, and also the data fed to it is the result from mData.
9426                  * This is the rendering method to match the data method of mData.
9427                  *  @type function|int|string|null
9428                  *  @default null
9429                  */
9430                 "mRender": null,
9431         
9432                 /**
9433                  * Unique header TH/TD element for this column - this is what the sorting
9434                  * listener is attached to (if sorting is enabled.)
9435                  *  @type node
9436                  *  @default null
9437                  */
9438                 "nTh": null,
9439         
9440                 /**
9441                  * Unique footer TH/TD element for this column (if there is one). Not used
9442                  * in DataTables as such, but can be used for plug-ins to reference the
9443                  * footer for each column.
9444                  *  @type node
9445                  *  @default null
9446                  */
9447                 "nTf": null,
9448         
9449                 /**
9450                  * The class to apply to all TD elements in the table's TBODY for the column
9451                  *  @type string
9452                  *  @default null
9453                  */
9454                 "sClass": null,
9455         
9456                 /**
9457                  * When DataTables calculates the column widths to assign to each column,
9458                  * it finds the longest string in each column and then constructs a
9459                  * temporary table and reads the widths from that. The problem with this
9460                  * is that "mmm" is much wider then "iiii", but the latter is a longer
9461                  * string - thus the calculation can go wrong (doing it properly and putting
9462                  * it into an DOM object and measuring that is horribly(!) slow). Thus as
9463                  * a "work around" we provide this option. It will append its value to the
9464                  * text that is found to be the longest string for the column - i.e. padding.
9465                  *  @type string
9466                  */
9467                 "sContentPadding": null,
9468         
9469                 /**
9470                  * Allows a default value to be given for a column's data, and will be used
9471                  * whenever a null data source is encountered (this can be because mData
9472                  * is set to null, or because the data source itself is null).
9473                  *  @type string
9474                  *  @default null
9475                  */
9476                 "sDefaultContent": null,
9477         
9478                 /**
9479                  * Name for the column, allowing reference to the column by name as well as
9480                  * by index (needs a lookup to work by name).
9481                  *  @type string
9482                  */
9483                 "sName": null,
9484         
9485                 /**
9486                  * Custom sorting data type - defines which of the available plug-ins in
9487                  * afnSortData the custom sorting will use - if any is defined.
9488                  *  @type string
9489                  *  @default std
9490                  */
9491                 "sSortDataType": 'std',
9492         
9493                 /**
9494                  * Class to be applied to the header element when sorting on this column
9495                  *  @type string
9496                  *  @default null
9497                  */
9498                 "sSortingClass": null,
9499         
9500                 /**
9501                  * Class to be applied to the header element when sorting on this column -
9502                  * when jQuery UI theming is used.
9503                  *  @type string
9504                  *  @default null
9505                  */
9506                 "sSortingClassJUI": null,
9507         
9508                 /**
9509                  * Title of the column - what is seen in the TH element (nTh).
9510                  *  @type string
9511                  */
9512                 "sTitle": null,
9513         
9514                 /**
9515                  * Column sorting and filtering type
9516                  *  @type string
9517                  *  @default null
9518                  */
9519                 "sType": null,
9520         
9521                 /**
9522                  * Width of the column
9523                  *  @type string
9524                  *  @default null
9525                  */
9526                 "sWidth": null,
9527         
9528                 /**
9529                  * Width of the column when it was first "encountered"
9530                  *  @type string
9531                  *  @default null
9532                  */
9533                 "sWidthOrig": null
9534         };
9535         
9536         
9537         /*
9538          * Developer note: The properties of the object below are given in Hungarian
9539          * notation, that was used as the interface for DataTables prior to v1.10, however
9540          * from v1.10 onwards the primary interface is camel case. In order to avoid
9541          * breaking backwards compatibility utterly with this change, the Hungarian
9542          * version is still, internally the primary interface, but is is not documented
9543          * - hence the @name tags in each doc comment. This allows a Javascript function
9544          * to create a map from Hungarian notation to camel case (going the other direction
9545          * would require each property to be listed, which would at around 3K to the size
9546          * of DataTables, while this method is about a 0.5K hit.
9547          *
9548          * Ultimately this does pave the way for Hungarian notation to be dropped
9549          * completely, but that is a massive amount of work and will break current
9550          * installs (therefore is on-hold until v2).
9551          */
9552         
9553         /**
9554          * Initialisation options that can be given to DataTables at initialisation
9555          * time.
9556          *  @namespace
9557          */
9558         DataTable.defaults = {
9559                 /**
9560                  * An array of data to use for the table, passed in at initialisation which
9561                  * will be used in preference to any data which is already in the DOM. This is
9562                  * particularly useful for constructing tables purely in Javascript, for
9563                  * example with a custom Ajax call.
9564                  *  @type array
9565                  *  @default null
9566                  *
9567                  *  @dtopt Option
9568                  *  @name DataTable.defaults.data
9569                  *
9570                  *  @example
9571                  *    // Using a 2D array data source
9572                  *    $(document).ready( function () {
9573                  *      $('#example').dataTable( {
9574                  *        "data": [
9575                  *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9576                  *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9577                  *        ],
9578                  *        "columns": [
9579                  *          { "title": "Engine" },
9580                  *          { "title": "Browser" },
9581                  *          { "title": "Platform" },
9582                  *          { "title": "Version" },
9583                  *          { "title": "Grade" }
9584                  *        ]
9585                  *      } );
9586                  *    } );
9587                  *
9588                  *  @example
9589                  *    // Using an array of objects as a data source (`data`)
9590                  *    $(document).ready( function () {
9591                  *      $('#example').dataTable( {
9592                  *        "data": [
9593                  *          {
9594                  *            "engine":   "Trident",
9595                  *            "browser":  "Internet Explorer 4.0",
9596                  *            "platform": "Win 95+",
9597                  *            "version":  4,
9598                  *            "grade":    "X"
9599                  *          },
9600                  *          {
9601                  *            "engine":   "Trident",
9602                  *            "browser":  "Internet Explorer 5.0",
9603                  *            "platform": "Win 95+",
9604                  *            "version":  5,
9605                  *            "grade":    "C"
9606                  *          }
9607                  *        ],
9608                  *        "columns": [
9609                  *          { "title": "Engine",   "data": "engine" },
9610                  *          { "title": "Browser",  "data": "browser" },
9611                  *          { "title": "Platform", "data": "platform" },
9612                  *          { "title": "Version",  "data": "version" },
9613                  *          { "title": "Grade",    "data": "grade" }
9614                  *        ]
9615                  *      } );
9616                  *    } );
9617                  */
9618                 "aaData": null,
9619         
9620         
9621                 /**
9622                  * If ordering is enabled, then DataTables will perform a first pass sort on
9623                  * initialisation. You can define which column(s) the sort is performed
9624                  * upon, and the sorting direction, with this variable. The `sorting` array
9625                  * should contain an array for each column to be sorted initially containing
9626                  * the column's index and a direction string ('asc' or 'desc').
9627                  *  @type array
9628                  *  @default [[0,'asc']]
9629                  *
9630                  *  @dtopt Option
9631                  *  @name DataTable.defaults.order
9632                  *
9633                  *  @example
9634                  *    // Sort by 3rd column first, and then 4th column
9635                  *    $(document).ready( function() {
9636                  *      $('#example').dataTable( {
9637                  *        "order": [[2,'asc'], [3,'desc']]
9638                  *      } );
9639                  *    } );
9640                  *
9641                  *    // No initial sorting
9642                  *    $(document).ready( function() {
9643                  *      $('#example').dataTable( {
9644                  *        "order": []
9645                  *      } );
9646                  *    } );
9647                  */
9648                 "aaSorting": [[0,'asc']],
9649         
9650         
9651                 /**
9652                  * This parameter is basically identical to the `sorting` parameter, but
9653                  * cannot be overridden by user interaction with the table. What this means
9654                  * is that you could have a column (visible or hidden) which the sorting
9655                  * will always be forced on first - any sorting after that (from the user)
9656                  * will then be performed as required. This can be useful for grouping rows
9657                  * together.
9658                  *  @type array
9659                  *  @default null
9660                  *
9661                  *  @dtopt Option
9662                  *  @name DataTable.defaults.orderFixed
9663                  *
9664                  *  @example
9665                  *    $(document).ready( function() {
9666                  *      $('#example').dataTable( {
9667                  *        "orderFixed": [[0,'asc']]
9668                  *      } );
9669                  *    } )
9670                  */
9671                 "aaSortingFixed": [],
9672         
9673         
9674                 /**
9675                  * DataTables can be instructed to load data to display in the table from a
9676                  * Ajax source. This option defines how that Ajax call is made and where to.
9677                  *
9678                  * The `ajax` property has three different modes of operation, depending on
9679                  * how it is defined. These are:
9680                  *
9681                  * * `string` - Set the URL from where the data should be loaded from.
9682                  * * `object` - Define properties for `jQuery.ajax`.
9683                  * * `function` - Custom data get function
9684                  *
9685                  * `string`
9686                  * --------
9687                  *
9688                  * As a string, the `ajax` property simply defines the URL from which
9689                  * DataTables will load data.
9690                  *
9691                  * `object`
9692                  * --------
9693                  *
9694                  * As an object, the parameters in the object are passed to
9695                  * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
9696                  * of the Ajax request. DataTables has a number of default parameters which
9697                  * you can override using this option. Please refer to the jQuery
9698                  * documentation for a full description of the options available, although
9699                  * the following parameters provide additional options in DataTables or
9700                  * require special consideration:
9701                  *
9702                  * * `data` - As with jQuery, `data` can be provided as an object, but it
9703                  *   can also be used as a function to manipulate the data DataTables sends
9704                  *   to the server. The function takes a single parameter, an object of
9705                  *   parameters with the values that DataTables has readied for sending. An
9706                  *   object may be returned which will be merged into the DataTables
9707                  *   defaults, or you can add the items to the object that was passed in and
9708                  *   not return anything from the function. This supersedes `fnServerParams`
9709                  *   from DataTables 1.9-.
9710                  *
9711                  * * `dataSrc` - By default DataTables will look for the property `data` (or
9712                  *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
9713                  *   from an Ajax source or for server-side processing - this parameter
9714                  *   allows that property to be changed. You can use Javascript dotted
9715                  *   object notation to get a data source for multiple levels of nesting, or
9716                  *   it my be used as a function. As a function it takes a single parameter,
9717                  *   the JSON returned from the server, which can be manipulated as
9718                  *   required, with the returned value being that used by DataTables as the
9719                  *   data source for the table. This supersedes `sAjaxDataProp` from
9720                  *   DataTables 1.9-.
9721                  *
9722                  * * `success` - Should not be overridden it is used internally in
9723                  *   DataTables. To manipulate / transform the data returned by the server
9724                  *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
9725                  *
9726                  * `function`
9727                  * ----------
9728                  *
9729                  * As a function, making the Ajax call is left up to yourself allowing
9730                  * complete control of the Ajax request. Indeed, if desired, a method other
9731                  * than Ajax could be used to obtain the required data, such as Web storage
9732                  * or an AIR database.
9733                  *
9734                  * The function is given four parameters and no return is required. The
9735                  * parameters are:
9736                  *
9737                  * 1. _object_ - Data to send to the server
9738                  * 2. _function_ - Callback function that must be executed when the required
9739                  *    data has been obtained. That data should be passed into the callback
9740                  *    as the only parameter
9741                  * 3. _object_ - DataTables settings object for the table
9742                  *
9743                  * Note that this supersedes `fnServerData` from DataTables 1.9-.
9744                  *
9745                  *  @type string|object|function
9746                  *  @default null
9747                  *
9748                  *  @dtopt Option
9749                  *  @name DataTable.defaults.ajax
9750                  *  @since 1.10.0
9751                  *
9752                  * @example
9753                  *   // Get JSON data from a file via Ajax.
9754                  *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
9755                  *   $('#example').dataTable( {
9756                  *     "ajax": "data.json"
9757                  *   } );
9758                  *
9759                  * @example
9760                  *   // Get JSON data from a file via Ajax, using `dataSrc` to change
9761                  *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
9762                  *   $('#example').dataTable( {
9763                  *     "ajax": {
9764                  *       "url": "data.json",
9765                  *       "dataSrc": "tableData"
9766                  *     }
9767                  *   } );
9768                  *
9769                  * @example
9770                  *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
9771                  *   // from a plain array rather than an array in an object
9772                  *   $('#example').dataTable( {
9773                  *     "ajax": {
9774                  *       "url": "data.json",
9775                  *       "dataSrc": ""
9776                  *     }
9777                  *   } );
9778                  *
9779                  * @example
9780                  *   // Manipulate the data returned from the server - add a link to data
9781                  *   // (note this can, should, be done using `render` for the column - this
9782                  *   // is just a simple example of how the data can be manipulated).
9783                  *   $('#example').dataTable( {
9784                  *     "ajax": {
9785                  *       "url": "data.json",
9786                  *       "dataSrc": function ( json ) {
9787                  *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
9788                  *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
9789                  *         }
9790                  *         return json;
9791                  *       }
9792                  *     }
9793                  *   } );
9794                  *
9795                  * @example
9796                  *   // Add data to the request
9797                  *   $('#example').dataTable( {
9798                  *     "ajax": {
9799                  *       "url": "data.json",
9800                  *       "data": function ( d ) {
9801                  *         return {
9802                  *           "extra_search": $('#extra').val()
9803                  *         };
9804                  *       }
9805                  *     }
9806                  *   } );
9807                  *
9808                  * @example
9809                  *   // Send request as POST
9810                  *   $('#example').dataTable( {
9811                  *     "ajax": {
9812                  *       "url": "data.json",
9813                  *       "type": "POST"
9814                  *     }
9815                  *   } );
9816                  *
9817                  * @example
9818                  *   // Get the data from localStorage (could interface with a form for
9819                  *   // adding, editing and removing rows).
9820                  *   $('#example').dataTable( {
9821                  *     "ajax": function (data, callback, settings) {
9822                  *       callback(
9823                  *         JSON.parse( localStorage.getItem('dataTablesData') )
9824                  *       );
9825                  *     }
9826                  *   } );
9827                  */
9828                 "ajax": null,
9829         
9830         
9831                 /**
9832                  * This parameter allows you to readily specify the entries in the length drop
9833                  * down menu that DataTables shows when pagination is enabled. It can be
9834                  * either a 1D array of options which will be used for both the displayed
9835                  * option and the value, or a 2D array which will use the array in the first
9836                  * position as the value, and the array in the second position as the
9837                  * displayed options (useful for language strings such as 'All').
9838                  *
9839                  * Note that the `pageLength` property will be automatically set to the
9840                  * first value given in this array, unless `pageLength` is also provided.
9841                  *  @type array
9842                  *  @default [ 10, 25, 50, 100 ]
9843                  *
9844                  *  @dtopt Option
9845                  *  @name DataTable.defaults.lengthMenu
9846                  *
9847                  *  @example
9848                  *    $(document).ready( function() {
9849                  *      $('#example').dataTable( {
9850                  *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
9851                  *      } );
9852                  *    } );
9853                  */
9854                 "aLengthMenu": [ 10, 25, 50, 100 ],
9855         
9856         
9857                 /**
9858                  * The `columns` option in the initialisation parameter allows you to define
9859                  * details about the way individual columns behave. For a full list of
9860                  * column options that can be set, please see
9861                  * {@link DataTable.defaults.column}. Note that if you use `columns` to
9862                  * define your columns, you must have an entry in the array for every single
9863                  * column that you have in your table (these can be null if you don't which
9864                  * to specify any options).
9865                  *  @member
9866                  *
9867                  *  @name DataTable.defaults.column
9868                  */
9869                 "aoColumns": null,
9870         
9871                 /**
9872                  * Very similar to `columns`, `columnDefs` allows you to target a specific
9873                  * column, multiple columns, or all columns, using the `targets` property of
9874                  * each object in the array. This allows great flexibility when creating
9875                  * tables, as the `columnDefs` arrays can be of any length, targeting the
9876                  * columns you specifically want. `columnDefs` may use any of the column
9877                  * options available: {@link DataTable.defaults.column}, but it _must_
9878                  * have `targets` defined in each object in the array. Values in the `targets`
9879                  * array may be:
9880                  *   <ul>
9881                  *     <li>a string - class name will be matched on the TH for the column</li>
9882                  *     <li>0 or a positive integer - column index counting from the left</li>
9883                  *     <li>a negative integer - column index counting from the right</li>
9884                  *     <li>the string "_all" - all columns (i.e. assign a default)</li>
9885                  *   </ul>
9886                  *  @member
9887                  *
9888                  *  @name DataTable.defaults.columnDefs
9889                  */
9890                 "aoColumnDefs": null,
9891         
9892         
9893                 /**
9894                  * Basically the same as `search`, this parameter defines the individual column
9895                  * filtering state at initialisation time. The array must be of the same size
9896                  * as the number of columns, and each element be an object with the parameters
9897                  * `search` and `escapeRegex` (the latter is optional). 'null' is also
9898                  * accepted and the default will be used.
9899                  *  @type array
9900                  *  @default []
9901                  *
9902                  *  @dtopt Option
9903                  *  @name DataTable.defaults.searchCols
9904                  *
9905                  *  @example
9906                  *    $(document).ready( function() {
9907                  *      $('#example').dataTable( {
9908                  *        "searchCols": [
9909                  *          null,
9910                  *          { "search": "My filter" },
9911                  *          null,
9912                  *          { "search": "^[0-9]", "escapeRegex": false }
9913                  *        ]
9914                  *      } );
9915                  *    } )
9916                  */
9917                 "aoSearchCols": [],
9918         
9919         
9920                 /**
9921                  * An array of CSS classes that should be applied to displayed rows. This
9922                  * array may be of any length, and DataTables will apply each class
9923                  * sequentially, looping when required.
9924                  *  @type array
9925                  *  @default null <i>Will take the values determined by the `oClasses.stripe*`
9926                  *    options</i>
9927                  *
9928                  *  @dtopt Option
9929                  *  @name DataTable.defaults.stripeClasses
9930                  *
9931                  *  @example
9932                  *    $(document).ready( function() {
9933                  *      $('#example').dataTable( {
9934                  *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
9935                  *      } );
9936                  *    } )
9937                  */
9938                 "asStripeClasses": null,
9939         
9940         
9941                 /**
9942                  * Enable or disable automatic column width calculation. This can be disabled
9943                  * as an optimisation (it takes some time to calculate the widths) if the
9944                  * tables widths are passed in using `columns`.
9945                  *  @type boolean
9946                  *  @default true
9947                  *
9948                  *  @dtopt Features
9949                  *  @name DataTable.defaults.autoWidth
9950                  *
9951                  *  @example
9952                  *    $(document).ready( function () {
9953                  *      $('#example').dataTable( {
9954                  *        "autoWidth": false
9955                  *      } );
9956                  *    } );
9957                  */
9958                 "bAutoWidth": true,
9959         
9960         
9961                 /**
9962                  * Deferred rendering can provide DataTables with a huge speed boost when you
9963                  * are using an Ajax or JS data source for the table. This option, when set to
9964                  * true, will cause DataTables to defer the creation of the table elements for
9965                  * each row until they are needed for a draw - saving a significant amount of
9966                  * time.
9967                  *  @type boolean
9968                  *  @default false
9969                  *
9970                  *  @dtopt Features
9971                  *  @name DataTable.defaults.deferRender
9972                  *
9973                  *  @example
9974                  *    $(document).ready( function() {
9975                  *      $('#example').dataTable( {
9976                  *        "ajax": "sources/arrays.txt",
9977                  *        "deferRender": true
9978                  *      } );
9979                  *    } );
9980                  */
9981                 "bDeferRender": false,
9982         
9983         
9984                 /**
9985                  * Replace a DataTable which matches the given selector and replace it with
9986                  * one which has the properties of the new initialisation object passed. If no
9987                  * table matches the selector, then the new DataTable will be constructed as
9988                  * per normal.
9989                  *  @type boolean
9990                  *  @default false
9991                  *
9992                  *  @dtopt Options
9993                  *  @name DataTable.defaults.destroy
9994                  *
9995                  *  @example
9996                  *    $(document).ready( function() {
9997                  *      $('#example').dataTable( {
9998                  *        "srollY": "200px",
9999                  *        "paginate": false
10000                  *      } );
10001                  *
10002                  *      // Some time later....
10003                  *      $('#example').dataTable( {
10004                  *        "filter": false,
10005                  *        "destroy": true
10006                  *      } );
10007                  *    } );
10008                  */
10009                 "bDestroy": false,
10010         
10011         
10012                 /**
10013                  * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10014                  * that it allows the end user to input multiple words (space separated) and
10015                  * will match a row containing those words, even if not in the order that was
10016                  * specified (this allow matching across multiple columns). Note that if you
10017                  * wish to use filtering in DataTables this must remain 'true' - to remove the
10018                  * default filtering input box and retain filtering abilities, please use
10019                  * {@link DataTable.defaults.dom}.
10020                  *  @type boolean
10021                  *  @default true
10022                  *
10023                  *  @dtopt Features
10024                  *  @name DataTable.defaults.searching
10025                  *
10026                  *  @example
10027                  *    $(document).ready( function () {
10028                  *      $('#example').dataTable( {
10029                  *        "searching": false
10030                  *      } );
10031                  *    } );
10032                  */
10033                 "bFilter": true,
10034         
10035         
10036                 /**
10037                  * Enable or disable the table information display. This shows information
10038                  * about the data that is currently visible on the page, including information
10039                  * about filtered data if that action is being performed.
10040                  *  @type boolean
10041                  *  @default true
10042                  *
10043                  *  @dtopt Features
10044                  *  @name DataTable.defaults.info
10045                  *
10046                  *  @example
10047                  *    $(document).ready( function () {
10048                  *      $('#example').dataTable( {
10049                  *        "info": false
10050                  *      } );
10051                  *    } );
10052                  */
10053                 "bInfo": true,
10054         
10055         
10056                 /**
10057                  * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
10058                  * slightly different and additional mark-up from what DataTables has
10059                  * traditionally used).
10060                  *  @type boolean
10061                  *  @default false
10062                  *
10063                  *  @dtopt Features
10064                  *  @name DataTable.defaults.jQueryUI
10065                  *
10066                  *  @example
10067                  *    $(document).ready( function() {
10068                  *      $('#example').dataTable( {
10069                  *        "jQueryUI": true
10070                  *      } );
10071                  *    } );
10072                  */
10073                 "bJQueryUI": false,
10074         
10075         
10076                 /**
10077                  * Allows the end user to select the size of a formatted page from a select
10078                  * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10079                  *  @type boolean
10080                  *  @default true
10081                  *
10082                  *  @dtopt Features
10083                  *  @name DataTable.defaults.lengthChange
10084                  *
10085                  *  @example
10086                  *    $(document).ready( function () {
10087                  *      $('#example').dataTable( {
10088                  *        "lengthChange": false
10089                  *      } );
10090                  *    } );
10091                  */
10092                 "bLengthChange": true,
10093         
10094         
10095                 /**
10096                  * Enable or disable pagination.
10097                  *  @type boolean
10098                  *  @default true
10099                  *
10100                  *  @dtopt Features
10101                  *  @name DataTable.defaults.paging
10102                  *
10103                  *  @example
10104                  *    $(document).ready( function () {
10105                  *      $('#example').dataTable( {
10106                  *        "paging": false
10107                  *      } );
10108                  *    } );
10109                  */
10110                 "bPaginate": true,
10111         
10112         
10113                 /**
10114                  * Enable or disable the display of a 'processing' indicator when the table is
10115                  * being processed (e.g. a sort). This is particularly useful for tables with
10116                  * large amounts of data where it can take a noticeable amount of time to sort
10117                  * the entries.
10118                  *  @type boolean
10119                  *  @default false
10120                  *
10121                  *  @dtopt Features
10122                  *  @name DataTable.defaults.processing
10123                  *
10124                  *  @example
10125                  *    $(document).ready( function () {
10126                  *      $('#example').dataTable( {
10127                  *        "processing": true
10128                  *      } );
10129                  *    } );
10130                  */
10131                 "bProcessing": false,
10132         
10133         
10134                 /**
10135                  * Retrieve the DataTables object for the given selector. Note that if the
10136                  * table has already been initialised, this parameter will cause DataTables
10137                  * to simply return the object that has already been set up - it will not take
10138                  * account of any changes you might have made to the initialisation object
10139                  * passed to DataTables (setting this parameter to true is an acknowledgement
10140                  * that you understand this). `destroy` can be used to reinitialise a table if
10141                  * you need.
10142                  *  @type boolean
10143                  *  @default false
10144                  *
10145                  *  @dtopt Options
10146                  *  @name DataTable.defaults.retrieve
10147                  *
10148                  *  @example
10149                  *    $(document).ready( function() {
10150                  *      initTable();
10151                  *      tableActions();
10152                  *    } );
10153                  *
10154                  *    function initTable ()
10155                  *    {
10156                  *      return $('#example').dataTable( {
10157                  *        "scrollY": "200px",
10158                  *        "paginate": false,
10159                  *        "retrieve": true
10160                  *      } );
10161                  *    }
10162                  *
10163                  *    function tableActions ()
10164                  *    {
10165                  *      var table = initTable();
10166                  *      // perform API operations with oTable
10167                  *    }
10168                  */
10169                 "bRetrieve": false,
10170         
10171         
10172                 /**
10173                  * When vertical (y) scrolling is enabled, DataTables will force the height of
10174                  * the table's viewport to the given height at all times (useful for layout).
10175                  * However, this can look odd when filtering data down to a small data set,
10176                  * and the footer is left "floating" further down. This parameter (when
10177                  * enabled) will cause DataTables to collapse the table's viewport down when
10178                  * the result set will fit within the given Y height.
10179                  *  @type boolean
10180                  *  @default false
10181                  *
10182                  *  @dtopt Options
10183                  *  @name DataTable.defaults.scrollCollapse
10184                  *
10185                  *  @example
10186                  *    $(document).ready( function() {
10187                  *      $('#example').dataTable( {
10188                  *        "scrollY": "200",
10189                  *        "scrollCollapse": true
10190                  *      } );
10191                  *    } );
10192                  */
10193                 "bScrollCollapse": false,
10194         
10195         
10196                 /**
10197                  * Configure DataTables to use server-side processing. Note that the
10198                  * `ajax` parameter must also be given in order to give DataTables a
10199                  * source to obtain the required data for each draw.
10200                  *  @type boolean
10201                  *  @default false
10202                  *
10203                  *  @dtopt Features
10204                  *  @dtopt Server-side
10205                  *  @name DataTable.defaults.serverSide
10206                  *
10207                  *  @example
10208                  *    $(document).ready( function () {
10209                  *      $('#example').dataTable( {
10210                  *        "serverSide": true,
10211                  *        "ajax": "xhr.php"
10212                  *      } );
10213                  *    } );
10214                  */
10215                 "bServerSide": false,
10216         
10217         
10218                 /**
10219                  * Enable or disable sorting of columns. Sorting of individual columns can be
10220                  * disabled by the `sortable` option for each column.
10221                  *  @type boolean
10222                  *  @default true
10223                  *
10224                  *  @dtopt Features
10225                  *  @name DataTable.defaults.ordering
10226                  *
10227                  *  @example
10228                  *    $(document).ready( function () {
10229                  *      $('#example').dataTable( {
10230                  *        "ordering": false
10231                  *      } );
10232                  *    } );
10233                  */
10234                 "bSort": true,
10235         
10236         
10237                 /**
10238                  * Enable or display DataTables' ability to sort multiple columns at the
10239                  * same time (activated by shift-click by the user).
10240                  *  @type boolean
10241                  *  @default true
10242                  *
10243                  *  @dtopt Options
10244                  *  @name DataTable.defaults.orderMulti
10245                  *
10246                  *  @example
10247                  *    // Disable multiple column sorting ability
10248                  *    $(document).ready( function () {
10249                  *      $('#example').dataTable( {
10250                  *        "orderMulti": false
10251                  *      } );
10252                  *    } );
10253                  */
10254                 "bSortMulti": true,
10255         
10256         
10257                 /**
10258                  * Allows control over whether DataTables should use the top (true) unique
10259                  * cell that is found for a single column, or the bottom (false - default).
10260                  * This is useful when using complex headers.
10261                  *  @type boolean
10262                  *  @default false
10263                  *
10264                  *  @dtopt Options
10265                  *  @name DataTable.defaults.orderCellsTop
10266                  *
10267                  *  @example
10268                  *    $(document).ready( function() {
10269                  *      $('#example').dataTable( {
10270                  *        "orderCellsTop": true
10271                  *      } );
10272                  *    } );
10273                  */
10274                 "bSortCellsTop": false,
10275         
10276         
10277                 /**
10278                  * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10279                  * `sorting\_3` to the columns which are currently being sorted on. This is
10280                  * presented as a feature switch as it can increase processing time (while
10281                  * classes are removed and added) so for large data sets you might want to
10282                  * turn this off.
10283                  *  @type boolean
10284                  *  @default true
10285                  *
10286                  *  @dtopt Features
10287                  *  @name DataTable.defaults.orderClasses
10288                  *
10289                  *  @example
10290                  *    $(document).ready( function () {
10291                  *      $('#example').dataTable( {
10292                  *        "orderClasses": false
10293                  *      } );
10294                  *    } );
10295                  */
10296                 "bSortClasses": true,
10297         
10298         
10299                 /**
10300                  * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10301                  * used to save table display information such as pagination information,
10302                  * display length, filtering and sorting. As such when the end user reloads
10303                  * the page the display display will match what thy had previously set up.
10304                  *
10305                  * Due to the use of `localStorage` the default state saving is not supported
10306                  * in IE6 or 7. If state saving is required in those browsers, use
10307                  * `stateSaveCallback` to provide a storage solution such as cookies.
10308                  *  @type boolean
10309                  *  @default false
10310                  *
10311                  *  @dtopt Features
10312                  *  @name DataTable.defaults.stateSave
10313                  *
10314                  *  @example
10315                  *    $(document).ready( function () {
10316                  *      $('#example').dataTable( {
10317                  *        "stateSave": true
10318                  *      } );
10319                  *    } );
10320                  */
10321                 "bStateSave": false,
10322         
10323         
10324                 /**
10325                  * This function is called when a TR element is created (and all TD child
10326                  * elements have been inserted), or registered if using a DOM source, allowing
10327                  * manipulation of the TR element (adding classes etc).
10328                  *  @type function
10329                  *  @param {node} row "TR" element for the current row
10330                  *  @param {array} data Raw data array for this row
10331                  *  @param {int} dataIndex The index of this row in the internal aoData array
10332                  *
10333                  *  @dtopt Callbacks
10334                  *  @name DataTable.defaults.createdRow
10335                  *
10336                  *  @example
10337                  *    $(document).ready( function() {
10338                  *      $('#example').dataTable( {
10339                  *        "createdRow": function( row, data, dataIndex ) {
10340                  *          // Bold the grade for all 'A' grade browsers
10341                  *          if ( data[4] == "A" )
10342                  *          {
10343                  *            $('td:eq(4)', row).html( '<b>A</b>' );
10344                  *          }
10345                  *        }
10346                  *      } );
10347                  *    } );
10348                  */
10349                 "fnCreatedRow": null,
10350         
10351         
10352                 /**
10353                  * This function is called on every 'draw' event, and allows you to
10354                  * dynamically modify any aspect you want about the created DOM.
10355                  *  @type function
10356                  *  @param {object} settings DataTables settings object
10357                  *
10358                  *  @dtopt Callbacks
10359                  *  @name DataTable.defaults.drawCallback
10360                  *
10361                  *  @example
10362                  *    $(document).ready( function() {
10363                  *      $('#example').dataTable( {
10364                  *        "drawCallback": function( settings ) {
10365                  *          alert( 'DataTables has redrawn the table' );
10366                  *        }
10367                  *      } );
10368                  *    } );
10369                  */
10370                 "fnDrawCallback": null,
10371         
10372         
10373                 /**
10374                  * Identical to fnHeaderCallback() but for the table footer this function
10375                  * allows you to modify the table footer on every 'draw' event.
10376                  *  @type function
10377                  *  @param {node} foot "TR" element for the footer
10378                  *  @param {array} data Full table data (as derived from the original HTML)
10379                  *  @param {int} start Index for the current display starting point in the
10380                  *    display array
10381                  *  @param {int} end Index for the current display ending point in the
10382                  *    display array
10383                  *  @param {array int} display Index array to translate the visual position
10384                  *    to the full data array
10385                  *
10386                  *  @dtopt Callbacks
10387                  *  @name DataTable.defaults.footerCallback
10388                  *
10389                  *  @example
10390                  *    $(document).ready( function() {
10391                  *      $('#example').dataTable( {
10392                  *        "footerCallback": function( tfoot, data, start, end, display ) {
10393                  *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10394                  *        }
10395                  *      } );
10396                  *    } )
10397                  */
10398                 "fnFooterCallback": null,
10399         
10400         
10401                 /**
10402                  * When rendering large numbers in the information element for the table
10403                  * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10404                  * to have a comma separator for the 'thousands' units (e.g. 1 million is
10405                  * rendered as "1,000,000") to help readability for the end user. This
10406                  * function will override the default method DataTables uses.
10407                  *  @type function
10408                  *  @member
10409                  *  @param {int} toFormat number to be formatted
10410                  *  @returns {string} formatted string for DataTables to show the number
10411                  *
10412                  *  @dtopt Callbacks
10413                  *  @name DataTable.defaults.formatNumber
10414                  *
10415                  *  @example
10416                  *    // Format a number using a single quote for the separator (note that
10417                  *    // this can also be done with the language.thousands option)
10418                  *    $(document).ready( function() {
10419                  *      $('#example').dataTable( {
10420                  *        "formatNumber": function ( toFormat ) {
10421                  *          return toFormat.toString().replace(
10422                  *            /\B(?=(\d{3})+(?!\d))/g, "'"
10423                  *          );
10424                  *        };
10425                  *      } );
10426                  *    } );
10427                  */
10428                 "fnFormatNumber": function ( toFormat ) {
10429                         return toFormat.toString().replace(
10430                                 /\B(?=(\d{3})+(?!\d))/g,
10431                                 this.oLanguage.sThousands
10432                         );
10433                 },
10434         
10435         
10436                 /**
10437                  * This function is called on every 'draw' event, and allows you to
10438                  * dynamically modify the header row. This can be used to calculate and
10439                  * display useful information about the table.
10440                  *  @type function
10441                  *  @param {node} head "TR" element for the header
10442                  *  @param {array} data Full table data (as derived from the original HTML)
10443                  *  @param {int} start Index for the current display starting point in the
10444                  *    display array
10445                  *  @param {int} end Index for the current display ending point in the
10446                  *    display array
10447                  *  @param {array int} display Index array to translate the visual position
10448                  *    to the full data array
10449                  *
10450                  *  @dtopt Callbacks
10451                  *  @name DataTable.defaults.headerCallback
10452                  *
10453                  *  @example
10454                  *    $(document).ready( function() {
10455                  *      $('#example').dataTable( {
10456                  *        "fheaderCallback": function( head, data, start, end, display ) {
10457                  *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10458                  *        }
10459                  *      } );
10460                  *    } )
10461                  */
10462                 "fnHeaderCallback": null,
10463         
10464         
10465                 /**
10466                  * The information element can be used to convey information about the current
10467                  * state of the table. Although the internationalisation options presented by
10468                  * DataTables are quite capable of dealing with most customisations, there may
10469                  * be times where you wish to customise the string further. This callback
10470                  * allows you to do exactly that.
10471                  *  @type function
10472                  *  @param {object} oSettings DataTables settings object
10473                  *  @param {int} start Starting position in data for the draw
10474                  *  @param {int} end End position in data for the draw
10475                  *  @param {int} max Total number of rows in the table (regardless of
10476                  *    filtering)
10477                  *  @param {int} total Total number of rows in the data set, after filtering
10478                  *  @param {string} pre The string that DataTables has formatted using it's
10479                  *    own rules
10480                  *  @returns {string} The string to be displayed in the information element.
10481                  *
10482                  *  @dtopt Callbacks
10483                  *  @name DataTable.defaults.infoCallback
10484                  *
10485                  *  @example
10486                  *    $('#example').dataTable( {
10487                  *      "infoCallback": function( settings, start, end, max, total, pre ) {
10488                  *        return start +" to "+ end;
10489                  *      }
10490                  *    } );
10491                  */
10492                 "fnInfoCallback": null,
10493         
10494         
10495                 /**
10496                  * Called when the table has been initialised. Normally DataTables will
10497                  * initialise sequentially and there will be no need for this function,
10498                  * however, this does not hold true when using external language information
10499                  * since that is obtained using an async XHR call.
10500                  *  @type function
10501                  *  @param {object} settings DataTables settings object
10502                  *  @param {object} json The JSON object request from the server - only
10503                  *    present if client-side Ajax sourced data is used
10504                  *
10505                  *  @dtopt Callbacks
10506                  *  @name DataTable.defaults.initComplete
10507                  *
10508                  *  @example
10509                  *    $(document).ready( function() {
10510                  *      $('#example').dataTable( {
10511                  *        "initComplete": function(settings, json) {
10512                  *          alert( 'DataTables has finished its initialisation.' );
10513                  *        }
10514                  *      } );
10515                  *    } )
10516                  */
10517                 "fnInitComplete": null,
10518         
10519         
10520                 /**
10521                  * Called at the very start of each table draw and can be used to cancel the
10522                  * draw by returning false, any other return (including undefined) results in
10523                  * the full draw occurring).
10524                  *  @type function
10525                  *  @param {object} settings DataTables settings object
10526                  *  @returns {boolean} False will cancel the draw, anything else (including no
10527                  *    return) will allow it to complete.
10528                  *
10529                  *  @dtopt Callbacks
10530                  *  @name DataTable.defaults.preDrawCallback
10531                  *
10532                  *  @example
10533                  *    $(document).ready( function() {
10534                  *      $('#example').dataTable( {
10535                  *        "preDrawCallback": function( settings ) {
10536                  *          if ( $('#test').val() == 1 ) {
10537                  *            return false;
10538                  *          }
10539                  *        }
10540                  *      } );
10541                  *    } );
10542                  */
10543                 "fnPreDrawCallback": null,
10544         
10545         
10546                 /**
10547                  * This function allows you to 'post process' each row after it have been
10548                  * generated for each table draw, but before it is rendered on screen. This
10549                  * function might be used for setting the row class name etc.
10550                  *  @type function
10551                  *  @param {node} row "TR" element for the current row
10552                  *  @param {array} data Raw data array for this row
10553                  *  @param {int} displayIndex The display index for the current table draw
10554                  *  @param {int} displayIndexFull The index of the data in the full list of
10555                  *    rows (after filtering)
10556                  *
10557                  *  @dtopt Callbacks
10558                  *  @name DataTable.defaults.rowCallback
10559                  *
10560                  *  @example
10561                  *    $(document).ready( function() {
10562                  *      $('#example').dataTable( {
10563                  *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10564                  *          // Bold the grade for all 'A' grade browsers
10565                  *          if ( data[4] == "A" ) {
10566                  *            $('td:eq(4)', row).html( '<b>A</b>' );
10567                  *          }
10568                  *        }
10569                  *      } );
10570                  *    } );
10571                  */
10572                 "fnRowCallback": null,
10573         
10574         
10575                 /**
10576                  * __Deprecated__ The functionality provided by this parameter has now been
10577                  * superseded by that provided through `ajax`, which should be used instead.
10578                  *
10579                  * This parameter allows you to override the default function which obtains
10580                  * the data from the server so something more suitable for your application.
10581                  * For example you could use POST data, or pull information from a Gears or
10582                  * AIR database.
10583                  *  @type function
10584                  *  @member
10585                  *  @param {string} source HTTP source to obtain the data from (`ajax`)
10586                  *  @param {array} data A key/value pair object containing the data to send
10587                  *    to the server
10588                  *  @param {function} callback to be called on completion of the data get
10589                  *    process that will draw the data on the page.
10590                  *  @param {object} settings DataTables settings object
10591                  *
10592                  *  @dtopt Callbacks
10593                  *  @dtopt Server-side
10594                  *  @name DataTable.defaults.serverData
10595                  *
10596                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
10597                  */
10598                 "fnServerData": null,
10599         
10600         
10601                 /**
10602                  * __Deprecated__ The functionality provided by this parameter has now been
10603                  * superseded by that provided through `ajax`, which should be used instead.
10604                  *
10605                  *  It is often useful to send extra data to the server when making an Ajax
10606                  * request - for example custom filtering information, and this callback
10607                  * function makes it trivial to send extra information to the server. The
10608                  * passed in parameter is the data set that has been constructed by
10609                  * DataTables, and you can add to this or modify it as you require.
10610                  *  @type function
10611                  *  @param {array} data Data array (array of objects which are name/value
10612                  *    pairs) that has been constructed by DataTables and will be sent to the
10613                  *    server. In the case of Ajax sourced data with server-side processing
10614                  *    this will be an empty array, for server-side processing there will be a
10615                  *    significant number of parameters!
10616                  *  @returns {undefined} Ensure that you modify the data array passed in,
10617                  *    as this is passed by reference.
10618                  *
10619                  *  @dtopt Callbacks
10620                  *  @dtopt Server-side
10621                  *  @name DataTable.defaults.serverParams
10622                  *
10623                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
10624                  */
10625                 "fnServerParams": null,
10626         
10627         
10628                 /**
10629                  * Load the table state. With this function you can define from where, and how, the
10630                  * state of a table is loaded. By default DataTables will load from `localStorage`
10631                  * but you might wish to use a server-side database or cookies.
10632                  *  @type function
10633                  *  @member
10634                  *  @param {object} settings DataTables settings object
10635                  *  @return {object} The DataTables state object to be loaded
10636                  *
10637                  *  @dtopt Callbacks
10638                  *  @name DataTable.defaults.stateLoadCallback
10639                  *
10640                  *  @example
10641                  *    $(document).ready( function() {
10642                  *      $('#example').dataTable( {
10643                  *        "stateSave": true,
10644                  *        "stateLoadCallback": function (settings) {
10645                  *          var o;
10646                  *
10647                  *          // Send an Ajax request to the server to get the data. Note that
10648                  *          // this is a synchronous request.
10649                  *          $.ajax( {
10650                  *            "url": "/state_load",
10651                  *            "async": false,
10652                  *            "dataType": "json",
10653                  *            "success": function (json) {
10654                  *              o = json;
10655                  *            }
10656                  *          } );
10657                  *
10658                  *          return o;
10659                  *        }
10660                  *      } );
10661                  *    } );
10662                  */
10663                 "fnStateLoadCallback": function ( settings ) {
10664                         try {
10665                                 return JSON.parse(
10666                                         (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
10667                                                 'DataTables_'+settings.sInstance+'_'+location.pathname
10668                                         )
10669                                 );
10670                         } catch (e) {}
10671                 },
10672         
10673         
10674                 /**
10675                  * Callback which allows modification of the saved state prior to loading that state.
10676                  * This callback is called when the table is loading state from the stored data, but
10677                  * prior to the settings object being modified by the saved state. Note that for
10678                  * plug-in authors, you should use the `stateLoadParams` event to load parameters for
10679                  * a plug-in.
10680                  *  @type function
10681                  *  @param {object} settings DataTables settings object
10682                  *  @param {object} data The state object that is to be loaded
10683                  *
10684                  *  @dtopt Callbacks
10685                  *  @name DataTable.defaults.stateLoadParams
10686                  *
10687                  *  @example
10688                  *    // Remove a saved filter, so filtering is never loaded
10689                  *    $(document).ready( function() {
10690                  *      $('#example').dataTable( {
10691                  *        "stateSave": true,
10692                  *        "stateLoadParams": function (settings, data) {
10693                  *          data.oSearch.sSearch = "";
10694                  *        }
10695                  *      } );
10696                  *    } );
10697                  *
10698                  *  @example
10699                  *    // Disallow state loading by returning false
10700                  *    $(document).ready( function() {
10701                  *      $('#example').dataTable( {
10702                  *        "stateSave": true,
10703                  *        "stateLoadParams": function (settings, data) {
10704                  *          return false;
10705                  *        }
10706                  *      } );
10707                  *    } );
10708                  */
10709                 "fnStateLoadParams": null,
10710         
10711         
10712                 /**
10713                  * Callback that is called when the state has been loaded from the state saving method
10714                  * and the DataTables settings object has been modified as a result of the loaded state.
10715                  *  @type function
10716                  *  @param {object} settings DataTables settings object
10717                  *  @param {object} data The state object that was loaded
10718                  *
10719                  *  @dtopt Callbacks
10720                  *  @name DataTable.defaults.stateLoaded
10721                  *
10722                  *  @example
10723                  *    // Show an alert with the filtering value that was saved
10724                  *    $(document).ready( function() {
10725                  *      $('#example').dataTable( {
10726                  *        "stateSave": true,
10727                  *        "stateLoaded": function (settings, data) {
10728                  *          alert( 'Saved filter was: '+data.oSearch.sSearch );
10729                  *        }
10730                  *      } );
10731                  *    } );
10732                  */
10733                 "fnStateLoaded": null,
10734         
10735         
10736                 /**
10737                  * Save the table state. This function allows you to define where and how the state
10738                  * information for the table is stored By default DataTables will use `localStorage`
10739                  * but you might wish to use a server-side database or cookies.
10740                  *  @type function
10741                  *  @member
10742                  *  @param {object} settings DataTables settings object
10743                  *  @param {object} data The state object to be saved
10744                  *
10745                  *  @dtopt Callbacks
10746                  *  @name DataTable.defaults.stateSaveCallback
10747                  *
10748                  *  @example
10749                  *    $(document).ready( function() {
10750                  *      $('#example').dataTable( {
10751                  *        "stateSave": true,
10752                  *        "stateSaveCallback": function (settings, data) {
10753                  *          // Send an Ajax request to the server with the state object
10754                  *          $.ajax( {
10755                  *            "url": "/state_save",
10756                  *            "data": data,
10757                  *            "dataType": "json",
10758                  *            "method": "POST"
10759                  *            "success": function () {}
10760                  *          } );
10761                  *        }
10762                  *      } );
10763                  *    } );
10764                  */
10765                 "fnStateSaveCallback": function ( settings, data ) {
10766                         try {
10767                                 (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
10768                                         'DataTables_'+settings.sInstance+'_'+location.pathname,
10769                                         JSON.stringify( data )
10770                                 );
10771                         } catch (e) {}
10772                 },
10773         
10774         
10775                 /**
10776                  * Callback which allows modification of the state to be saved. Called when the table
10777                  * has changed state a new state save is required. This method allows modification of
10778                  * the state saving object prior to actually doing the save, including addition or
10779                  * other state properties or modification. Note that for plug-in authors, you should
10780                  * use the `stateSaveParams` event to save parameters for a plug-in.
10781                  *  @type function
10782                  *  @param {object} settings DataTables settings object
10783                  *  @param {object} data The state object to be saved
10784                  *
10785                  *  @dtopt Callbacks
10786                  *  @name DataTable.defaults.stateSaveParams
10787                  *
10788                  *  @example
10789                  *    // Remove a saved filter, so filtering is never saved
10790                  *    $(document).ready( function() {
10791                  *      $('#example').dataTable( {
10792                  *        "stateSave": true,
10793                  *        "stateSaveParams": function (settings, data) {
10794                  *          data.oSearch.sSearch = "";
10795                  *        }
10796                  *      } );
10797                  *    } );
10798                  */
10799                 "fnStateSaveParams": null,
10800         
10801         
10802                 /**
10803                  * Duration for which the saved state information is considered valid. After this period
10804                  * has elapsed the state will be returned to the default.
10805                  * Value is given in seconds.
10806                  *  @type int
10807                  *  @default 7200 <i>(2 hours)</i>
10808                  *
10809                  *  @dtopt Options
10810                  *  @name DataTable.defaults.stateDuration
10811                  *
10812                  *  @example
10813                  *    $(document).ready( function() {
10814                  *      $('#example').dataTable( {
10815                  *        "stateDuration": 60*60*24; // 1 day
10816                  *      } );
10817                  *    } )
10818                  */
10819                 "iStateDuration": 7200,
10820         
10821         
10822                 /**
10823                  * When enabled DataTables will not make a request to the server for the first
10824                  * page draw - rather it will use the data already on the page (no sorting etc
10825                  * will be applied to it), thus saving on an XHR at load time. `deferLoading`
10826                  * is used to indicate that deferred loading is required, but it is also used
10827                  * to tell DataTables how many records there are in the full table (allowing
10828                  * the information element and pagination to be displayed correctly). In the case
10829                  * where a filtering is applied to the table on initial load, this can be
10830                  * indicated by giving the parameter as an array, where the first element is
10831                  * the number of records available after filtering and the second element is the
10832                  * number of records without filtering (allowing the table information element
10833                  * to be shown correctly).
10834                  *  @type int | array
10835                  *  @default null
10836                  *
10837                  *  @dtopt Options
10838                  *  @name DataTable.defaults.deferLoading
10839                  *
10840                  *  @example
10841                  *    // 57 records available in the table, no filtering applied
10842                  *    $(document).ready( function() {
10843                  *      $('#example').dataTable( {
10844                  *        "serverSide": true,
10845                  *        "ajax": "scripts/server_processing.php",
10846                  *        "deferLoading": 57
10847                  *      } );
10848                  *    } );
10849                  *
10850                  *  @example
10851                  *    // 57 records after filtering, 100 without filtering (an initial filter applied)
10852                  *    $(document).ready( function() {
10853                  *      $('#example').dataTable( {
10854                  *        "serverSide": true,
10855                  *        "ajax": "scripts/server_processing.php",
10856                  *        "deferLoading": [ 57, 100 ],
10857                  *        "search": {
10858                  *          "search": "my_filter"
10859                  *        }
10860                  *      } );
10861                  *    } );
10862                  */
10863                 "iDeferLoading": null,
10864         
10865         
10866                 /**
10867                  * Number of rows to display on a single page when using pagination. If
10868                  * feature enabled (`lengthChange`) then the end user will be able to override
10869                  * this to a custom setting using a pop-up menu.
10870                  *  @type int
10871                  *  @default 10
10872                  *
10873                  *  @dtopt Options
10874                  *  @name DataTable.defaults.pageLength
10875                  *
10876                  *  @example
10877                  *    $(document).ready( function() {
10878                  *      $('#example').dataTable( {
10879                  *        "pageLength": 50
10880                  *      } );
10881                  *    } )
10882                  */
10883                 "iDisplayLength": 10,
10884         
10885         
10886                 /**
10887                  * Define the starting point for data display when using DataTables with
10888                  * pagination. Note that this parameter is the number of records, rather than
10889                  * the page number, so if you have 10 records per page and want to start on
10890                  * the third page, it should be "20".
10891                  *  @type int
10892                  *  @default 0
10893                  *
10894                  *  @dtopt Options
10895                  *  @name DataTable.defaults.displayStart
10896                  *
10897                  *  @example
10898                  *    $(document).ready( function() {
10899                  *      $('#example').dataTable( {
10900                  *        "displayStart": 20
10901                  *      } );
10902                  *    } )
10903                  */
10904                 "iDisplayStart": 0,
10905         
10906         
10907                 /**
10908                  * By default DataTables allows keyboard navigation of the table (sorting, paging,
10909                  * and filtering) by adding a `tabindex` attribute to the required elements. This
10910                  * allows you to tab through the controls and press the enter key to activate them.
10911                  * The tabindex is default 0, meaning that the tab follows the flow of the document.
10912                  * You can overrule this using this parameter if you wish. Use a value of -1 to
10913                  * disable built-in keyboard navigation.
10914                  *  @type int
10915                  *  @default 0
10916                  *
10917                  *  @dtopt Options
10918                  *  @name DataTable.defaults.tabIndex
10919                  *
10920                  *  @example
10921                  *    $(document).ready( function() {
10922                  *      $('#example').dataTable( {
10923                  *        "tabIndex": 1
10924                  *      } );
10925                  *    } );
10926                  */
10927                 "iTabIndex": 0,
10928         
10929         
10930                 /**
10931                  * Classes that DataTables assigns to the various components and features
10932                  * that it adds to the HTML table. This allows classes to be configured
10933                  * during initialisation in addition to through the static
10934                  * {@link DataTable.ext.oStdClasses} object).
10935                  *  @namespace
10936                  *  @name DataTable.defaults.classes
10937                  */
10938                 "oClasses": {},
10939         
10940         
10941                 /**
10942                  * All strings that DataTables uses in the user interface that it creates
10943                  * are defined in this object, allowing you to modified them individually or
10944                  * completely replace them all as required.
10945                  *  @namespace
10946                  *  @name DataTable.defaults.language
10947                  */
10948                 "oLanguage": {
10949                         /**
10950                          * Strings that are used for WAI-ARIA labels and controls only (these are not
10951                          * actually visible on the page, but will be read by screenreaders, and thus
10952                          * must be internationalised as well).
10953                          *  @namespace
10954                          *  @name DataTable.defaults.language.aria
10955                          */
10956                         "oAria": {
10957                                 /**
10958                                  * ARIA label that is added to the table headers when the column may be
10959                                  * sorted ascending by activing the column (click or return when focused).
10960                                  * Note that the column header is prefixed to this string.
10961                                  *  @type string
10962                                  *  @default : activate to sort column ascending
10963                                  *
10964                                  *  @dtopt Language
10965                                  *  @name DataTable.defaults.language.aria.sortAscending
10966                                  *
10967                                  *  @example
10968                                  *    $(document).ready( function() {
10969                                  *      $('#example').dataTable( {
10970                                  *        "language": {
10971                                  *          "aria": {
10972                                  *            "sortAscending": " - click/return to sort ascending"
10973                                  *          }
10974                                  *        }
10975                                  *      } );
10976                                  *    } );
10977                                  */
10978                                 "sSortAscending": ": activate to sort column ascending",
10979         
10980                                 /**
10981                                  * ARIA label that is added to the table headers when the column may be
10982                                  * sorted descending by activing the column (click or return when focused).
10983                                  * Note that the column header is prefixed to this string.
10984                                  *  @type string
10985                                  *  @default : activate to sort column ascending
10986                                  *
10987                                  *  @dtopt Language
10988                                  *  @name DataTable.defaults.language.aria.sortDescending
10989                                  *
10990                                  *  @example
10991                                  *    $(document).ready( function() {
10992                                  *      $('#example').dataTable( {
10993                                  *        "language": {
10994                                  *          "aria": {
10995                                  *            "sortDescending": " - click/return to sort descending"
10996                                  *          }
10997                                  *        }
10998                                  *      } );
10999                                  *    } );
11000                                  */
11001                                 "sSortDescending": ": activate to sort column descending"
11002                         },
11003         
11004                         /**
11005                          * Pagination string used by DataTables for the built-in pagination
11006                          * control types.
11007                          *  @namespace
11008                          *  @name DataTable.defaults.language.paginate
11009                          */
11010                         "oPaginate": {
11011                                 /**
11012                                  * Text to use when using the 'full_numbers' type of pagination for the
11013                                  * button to take the user to the first page.
11014                                  *  @type string
11015                                  *  @default First
11016                                  *
11017                                  *  @dtopt Language
11018                                  *  @name DataTable.defaults.language.paginate.first
11019                                  *
11020                                  *  @example
11021                                  *    $(document).ready( function() {
11022                                  *      $('#example').dataTable( {
11023                                  *        "language": {
11024                                  *          "paginate": {
11025                                  *            "first": "First page"
11026                                  *          }
11027                                  *        }
11028                                  *      } );
11029                                  *    } );
11030                                  */
11031                                 "sFirst": "First",
11032         
11033         
11034                                 /**
11035                                  * Text to use when using the 'full_numbers' type of pagination for the
11036                                  * button to take the user to the last page.
11037                                  *  @type string
11038                                  *  @default Last
11039                                  *
11040                                  *  @dtopt Language
11041                                  *  @name DataTable.defaults.language.paginate.last
11042                                  *
11043                                  *  @example
11044                                  *    $(document).ready( function() {
11045                                  *      $('#example').dataTable( {
11046                                  *        "language": {
11047                                  *          "paginate": {
11048                                  *            "last": "Last page"
11049                                  *          }
11050                                  *        }
11051                                  *      } );
11052                                  *    } );
11053                                  */
11054                                 "sLast": "Last",
11055         
11056         
11057                                 /**
11058                                  * Text to use for the 'next' pagination button (to take the user to the
11059                                  * next page).
11060                                  *  @type string
11061                                  *  @default Next
11062                                  *
11063                                  *  @dtopt Language
11064                                  *  @name DataTable.defaults.language.paginate.next
11065                                  *
11066                                  *  @example
11067                                  *    $(document).ready( function() {
11068                                  *      $('#example').dataTable( {
11069                                  *        "language": {
11070                                  *          "paginate": {
11071                                  *            "next": "Next page"
11072                                  *          }
11073                                  *        }
11074                                  *      } );
11075                                  *    } );
11076                                  */
11077                                 "sNext": "Next",
11078         
11079         
11080                                 /**
11081                                  * Text to use for the 'previous' pagination button (to take the user to
11082                                  * the previous page).
11083                                  *  @type string
11084                                  *  @default Previous
11085                                  *
11086                                  *  @dtopt Language
11087                                  *  @name DataTable.defaults.language.paginate.previous
11088                                  *
11089                                  *  @example
11090                                  *    $(document).ready( function() {
11091                                  *      $('#example').dataTable( {
11092                                  *        "language": {
11093                                  *          "paginate": {
11094                                  *            "previous": "Previous page"
11095                                  *          }
11096                                  *        }
11097                                  *      } );
11098                                  *    } );
11099                                  */
11100                                 "sPrevious": "Previous"
11101                         },
11102         
11103                         /**
11104                          * This string is shown in preference to `zeroRecords` when the table is
11105                          * empty of data (regardless of filtering). Note that this is an optional
11106                          * parameter - if it is not given, the value of `zeroRecords` will be used
11107                          * instead (either the default or given value).
11108                          *  @type string
11109                          *  @default No data available in table
11110                          *
11111                          *  @dtopt Language
11112                          *  @name DataTable.defaults.language.emptyTable
11113                          *
11114                          *  @example
11115                          *    $(document).ready( function() {
11116                          *      $('#example').dataTable( {
11117                          *        "language": {
11118                          *          "emptyTable": "No data available in table"
11119                          *        }
11120                          *      } );
11121                          *    } );
11122                          */
11123                         "sEmptyTable": "No data available in table",
11124         
11125         
11126                         /**
11127                          * This string gives information to the end user about the information
11128                          * that is current on display on the page. The following tokens can be
11129                          * used in the string and will be dynamically replaced as the table
11130                          * display updates. This tokens can be placed anywhere in the string, or
11131                          * removed as needed by the language requires:
11132                          *
11133                          * * `\_START\_` - Display index of the first record on the current page
11134                          * * `\_END\_` - Display index of the last record on the current page
11135                          * * `\_TOTAL\_` - Number of records in the table after filtering
11136                          * * `\_MAX\_` - Number of records in the table without filtering
11137                          * * `\_PAGE\_` - Current page number
11138                          * * `\_PAGES\_` - Total number of pages of data in the table
11139                          *
11140                          *  @type string
11141                          *  @default Showing _START_ to _END_ of _TOTAL_ entries
11142                          *
11143                          *  @dtopt Language
11144                          *  @name DataTable.defaults.language.info
11145                          *
11146                          *  @example
11147                          *    $(document).ready( function() {
11148                          *      $('#example').dataTable( {
11149                          *        "language": {
11150                          *          "info": "Showing page _PAGE_ of _PAGES_"
11151                          *        }
11152                          *      } );
11153                          *    } );
11154                          */
11155                         "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11156         
11157         
11158                         /**
11159                          * Display information string for when the table is empty. Typically the
11160                          * format of this string should match `info`.
11161                          *  @type string
11162                          *  @default Showing 0 to 0 of 0 entries
11163                          *
11164                          *  @dtopt Language
11165                          *  @name DataTable.defaults.language.infoEmpty
11166                          *
11167                          *  @example
11168                          *    $(document).ready( function() {
11169                          *      $('#example').dataTable( {
11170                          *        "language": {
11171                          *          "infoEmpty": "No entries to show"
11172                          *        }
11173                          *      } );
11174                          *    } );
11175                          */
11176                         "sInfoEmpty": "Showing 0 to 0 of 0 entries",
11177         
11178         
11179                         /**
11180                          * When a user filters the information in a table, this string is appended
11181                          * to the information (`info`) to give an idea of how strong the filtering
11182                          * is. The variable _MAX_ is dynamically updated.
11183                          *  @type string
11184                          *  @default (filtered from _MAX_ total entries)
11185                          *
11186                          *  @dtopt Language
11187                          *  @name DataTable.defaults.language.infoFiltered
11188                          *
11189                          *  @example
11190                          *    $(document).ready( function() {
11191                          *      $('#example').dataTable( {
11192                          *        "language": {
11193                          *          "infoFiltered": " - filtering from _MAX_ records"
11194                          *        }
11195                          *      } );
11196                          *    } );
11197                          */
11198                         "sInfoFiltered": "(filtered from _MAX_ total entries)",
11199         
11200         
11201                         /**
11202                          * If can be useful to append extra information to the info string at times,
11203                          * and this variable does exactly that. This information will be appended to
11204                          * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11205                          * being used) at all times.
11206                          *  @type string
11207                          *  @default <i>Empty string</i>
11208                          *
11209                          *  @dtopt Language
11210                          *  @name DataTable.defaults.language.infoPostFix
11211                          *
11212                          *  @example
11213                          *    $(document).ready( function() {
11214                          *      $('#example').dataTable( {
11215                          *        "language": {
11216                          *          "infoPostFix": "All records shown are derived from real information."
11217                          *        }
11218                          *      } );
11219                          *    } );
11220                          */
11221                         "sInfoPostFix": "",
11222         
11223         
11224                         /**
11225                          * This decimal place operator is a little different from the other
11226                          * language options since DataTables doesn't output floating point
11227                          * numbers, so it won't ever use this for display of a number. Rather,
11228                          * what this parameter does is modify the sort methods of the table so
11229                          * that numbers which are in a format which has a character other than
11230                          * a period (`.`) as a decimal place will be sorted numerically.
11231                          *
11232                          * Note that numbers with different decimal places cannot be shown in
11233                          * the same table and still be sortable, the table must be consistent.
11234                          * However, multiple different tables on the page can use different
11235                          * decimal place characters.
11236                          *  @type string
11237                          *  @default 
11238                          *
11239                          *  @dtopt Language
11240                          *  @name DataTable.defaults.language.decimal
11241                          *
11242                          *  @example
11243                          *    $(document).ready( function() {
11244                          *      $('#example').dataTable( {
11245                          *        "language": {
11246                          *          "decimal": ","
11247                          *          "thousands": "."
11248                          *        }
11249                          *      } );
11250                          *    } );
11251                          */
11252                         "sDecimal": "",
11253         
11254         
11255                         /**
11256                          * DataTables has a build in number formatter (`formatNumber`) which is
11257                          * used to format large numbers that are used in the table information.
11258                          * By default a comma is used, but this can be trivially changed to any
11259                          * character you wish with this parameter.
11260                          *  @type string
11261                          *  @default ,
11262                          *
11263                          *  @dtopt Language
11264                          *  @name DataTable.defaults.language.thousands
11265                          *
11266                          *  @example
11267                          *    $(document).ready( function() {
11268                          *      $('#example').dataTable( {
11269                          *        "language": {
11270                          *          "thousands": "'"
11271                          *        }
11272                          *      } );
11273                          *    } );
11274                          */
11275                         "sThousands": ",",
11276         
11277         
11278                         /**
11279                          * Detail the action that will be taken when the drop down menu for the
11280                          * pagination length option is changed. The '_MENU_' variable is replaced
11281                          * with a default select list of 10, 25, 50 and 100, and can be replaced
11282                          * with a custom select box if required.
11283                          *  @type string
11284                          *  @default Show _MENU_ entries
11285                          *
11286                          *  @dtopt Language
11287                          *  @name DataTable.defaults.language.lengthMenu
11288                          *
11289                          *  @example
11290                          *    // Language change only
11291                          *    $(document).ready( function() {
11292                          *      $('#example').dataTable( {
11293                          *        "language": {
11294                          *          "lengthMenu": "Display _MENU_ records"
11295                          *        }
11296                          *      } );
11297                          *    } );
11298                          *
11299                          *  @example
11300                          *    // Language and options change
11301                          *    $(document).ready( function() {
11302                          *      $('#example').dataTable( {
11303                          *        "language": {
11304                          *          "lengthMenu": 'Display <select>'+
11305                          *            '<option value="10">10</option>'+
11306                          *            '<option value="20">20</option>'+
11307                          *            '<option value="30">30</option>'+
11308                          *            '<option value="40">40</option>'+
11309                          *            '<option value="50">50</option>'+
11310                          *            '<option value="-1">All</option>'+
11311                          *            '</select> records'
11312                          *        }
11313                          *      } );
11314                          *    } );
11315                          */
11316                         "sLengthMenu": "Show _MENU_ entries",
11317         
11318         
11319                         /**
11320                          * When using Ajax sourced data and during the first draw when DataTables is
11321                          * gathering the data, this message is shown in an empty row in the table to
11322                          * indicate to the end user the the data is being loaded. Note that this
11323                          * parameter is not used when loading data by server-side processing, just
11324                          * Ajax sourced data with client-side processing.
11325                          *  @type string
11326                          *  @default Loading...
11327                          *
11328                          *  @dtopt Language
11329                          *  @name DataTable.defaults.language.loadingRecords
11330                          *
11331                          *  @example
11332                          *    $(document).ready( function() {
11333                          *      $('#example').dataTable( {
11334                          *        "language": {
11335                          *          "loadingRecords": "Please wait - loading..."
11336                          *        }
11337                          *      } );
11338                          *    } );
11339                          */
11340                         "sLoadingRecords": "Loading...",
11341         
11342         
11343                         /**
11344                          * Text which is displayed when the table is processing a user action
11345                          * (usually a sort command or similar).
11346                          *  @type string
11347                          *  @default Processing...
11348                          *
11349                          *  @dtopt Language
11350                          *  @name DataTable.defaults.language.processing
11351                          *
11352                          *  @example
11353                          *    $(document).ready( function() {
11354                          *      $('#example').dataTable( {
11355                          *        "language": {
11356                          *          "processing": "DataTables is currently busy"
11357                          *        }
11358                          *      } );
11359                          *    } );
11360                          */
11361                         "sProcessing": "Processing...",
11362         
11363         
11364                         /**
11365                          * Details the actions that will be taken when the user types into the
11366                          * filtering input text box. The variable "_INPUT_", if used in the string,
11367                          * is replaced with the HTML text box for the filtering input allowing
11368                          * control over where it appears in the string. If "_INPUT_" is not given
11369                          * then the input box is appended to the string automatically.
11370                          *  @type string
11371                          *  @default Search:
11372                          *
11373                          *  @dtopt Language
11374                          *  @name DataTable.defaults.language.search
11375                          *
11376                          *  @example
11377                          *    // Input text box will be appended at the end automatically
11378                          *    $(document).ready( function() {
11379                          *      $('#example').dataTable( {
11380                          *        "language": {
11381                          *          "search": "Filter records:"
11382                          *        }
11383                          *      } );
11384                          *    } );
11385                          *
11386                          *  @example
11387                          *    // Specify where the filter should appear
11388                          *    $(document).ready( function() {
11389                          *      $('#example').dataTable( {
11390                          *        "language": {
11391                          *          "search": "Apply filter _INPUT_ to table"
11392                          *        }
11393                          *      } );
11394                          *    } );
11395                          */
11396                         "sSearch": "Search:",
11397         
11398         
11399                         /**
11400                          * Assign a `placeholder` attribute to the search `input` element
11401                          *  @type string
11402                          *  @default 
11403                          *
11404                          *  @dtopt Language
11405                          *  @name DataTable.defaults.language.searchPlaceholder
11406                          */
11407                         "sSearchPlaceholder": "",
11408         
11409         
11410                         /**
11411                          * All of the language information can be stored in a file on the
11412                          * server-side, which DataTables will look up if this parameter is passed.
11413                          * It must store the URL of the language file, which is in a JSON format,
11414                          * and the object has the same properties as the oLanguage object in the
11415                          * initialiser object (i.e. the above parameters). Please refer to one of
11416                          * the example language files to see how this works in action.
11417                          *  @type string
11418                          *  @default <i>Empty string - i.e. disabled</i>
11419                          *
11420                          *  @dtopt Language
11421                          *  @name DataTable.defaults.language.url
11422                          *
11423                          *  @example
11424                          *    $(document).ready( function() {
11425                          *      $('#example').dataTable( {
11426                          *        "language": {
11427                          *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11428                          *        }
11429                          *      } );
11430                          *    } );
11431                          */
11432                         "sUrl": "",
11433         
11434         
11435                         /**
11436                          * Text shown inside the table records when the is no information to be
11437                          * displayed after filtering. `emptyTable` is shown when there is simply no
11438                          * information in the table at all (regardless of filtering).
11439                          *  @type string
11440                          *  @default No matching records found
11441                          *
11442                          *  @dtopt Language
11443                          *  @name DataTable.defaults.language.zeroRecords
11444                          *
11445                          *  @example
11446                          *    $(document).ready( function() {
11447                          *      $('#example').dataTable( {
11448                          *        "language": {
11449                          *          "zeroRecords": "No records to display"
11450                          *        }
11451                          *      } );
11452                          *    } );
11453                          */
11454                         "sZeroRecords": "No matching records found"
11455                 },
11456         
11457         
11458                 /**
11459                  * This parameter allows you to have define the global filtering state at
11460                  * initialisation time. As an object the `search` parameter must be
11461                  * defined, but all other parameters are optional. When `regex` is true,
11462                  * the search string will be treated as a regular expression, when false
11463                  * (default) it will be treated as a straight string. When `smart`
11464                  * DataTables will use it's smart filtering methods (to word match at
11465                  * any point in the data), when false this will not be done.
11466                  *  @namespace
11467                  *  @extends DataTable.models.oSearch
11468                  *
11469                  *  @dtopt Options
11470                  *  @name DataTable.defaults.search
11471                  *
11472                  *  @example
11473                  *    $(document).ready( function() {
11474                  *      $('#example').dataTable( {
11475                  *        "search": {"search": "Initial search"}
11476                  *      } );
11477                  *    } )
11478                  */
11479                 "oSearch": $.extend( {}, DataTable.models.oSearch ),
11480         
11481         
11482                 /**
11483                  * __Deprecated__ The functionality provided by this parameter has now been
11484                  * superseded by that provided through `ajax`, which should be used instead.
11485                  *
11486                  * By default DataTables will look for the property `data` (or `aaData` for
11487                  * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11488                  * source or for server-side processing - this parameter allows that
11489                  * property to be changed. You can use Javascript dotted object notation to
11490                  * get a data source for multiple levels of nesting.
11491                  *  @type string
11492                  *  @default data
11493                  *
11494                  *  @dtopt Options
11495                  *  @dtopt Server-side
11496                  *  @name DataTable.defaults.ajaxDataProp
11497                  *
11498                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
11499                  */
11500                 "sAjaxDataProp": "data",
11501         
11502         
11503                 /**
11504                  * __Deprecated__ The functionality provided by this parameter has now been
11505                  * superseded by that provided through `ajax`, which should be used instead.
11506                  *
11507                  * You can instruct DataTables to load data from an external
11508                  * source using this parameter (use aData if you want to pass data in you
11509                  * already have). Simply provide a url a JSON object can be obtained from.
11510                  *  @type string
11511                  *  @default null
11512                  *
11513                  *  @dtopt Options
11514                  *  @dtopt Server-side
11515                  *  @name DataTable.defaults.ajaxSource
11516                  *
11517                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
11518                  */
11519                 "sAjaxSource": null,
11520         
11521         
11522                 /**
11523                  * This initialisation variable allows you to specify exactly where in the
11524                  * DOM you want DataTables to inject the various controls it adds to the page
11525                  * (for example you might want the pagination controls at the top of the
11526                  * table). DIV elements (with or without a custom class) can also be added to
11527                  * aid styling. The follow syntax is used:
11528                  *   <ul>
11529                  *     <li>The following options are allowed:
11530                  *       <ul>
11531                  *         <li>'l' - Length changing</li>
11532                  *         <li>'f' - Filtering input</li>
11533                  *         <li>'t' - The table!</li>
11534                  *         <li>'i' - Information</li>
11535                  *         <li>'p' - Pagination</li>
11536                  *         <li>'r' - pRocessing</li>
11537                  *       </ul>
11538                  *     </li>
11539                  *     <li>The following constants are allowed:
11540                  *       <ul>
11541                  *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11542                  *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11543                  *       </ul>
11544                  *     </li>
11545                  *     <li>The following syntax is expected:
11546                  *       <ul>
11547                  *         <li>'&lt;' and '&gt;' - div elements</li>
11548                  *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11549                  *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11550                  *       </ul>
11551                  *     </li>
11552                  *     <li>Examples:
11553                  *       <ul>
11554                  *         <li>'&lt;"wrapper"flipt&gt;'</li>
11555                  *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11556                  *       </ul>
11557                  *     </li>
11558                  *   </ul>
11559                  *  @type string
11560                  *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11561                  *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11562                  *
11563                  *  @dtopt Options
11564                  *  @name DataTable.defaults.dom
11565                  *
11566                  *  @example
11567                  *    $(document).ready( function() {
11568                  *      $('#example').dataTable( {
11569                  *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11570                  *      } );
11571                  *    } );
11572                  */
11573                 "sDom": "lfrtip",
11574         
11575         
11576                 /**
11577                  * Search delay option. This will throttle full table searches that use the
11578                  * DataTables provided search input element (it does not effect calls to
11579                  * `dt-api search()`, providing a delay before the search is made.
11580                  *  @type integer
11581                  *  @default 0
11582                  *
11583                  *  @dtopt Options
11584                  *  @name DataTable.defaults.searchDelay
11585                  *
11586                  *  @example
11587                  *    $(document).ready( function() {
11588                  *      $('#example').dataTable( {
11589                  *        "searchDelay": 200
11590                  *      } );
11591                  *    } )
11592                  */
11593                 "searchDelay": null,
11594         
11595         
11596                 /**
11597                  * DataTables features four different built-in options for the buttons to
11598                  * display for pagination control:
11599                  *
11600                  * * `simple` - 'Previous' and 'Next' buttons only
11601                  * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11602                  * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11603                  * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus
11604                  *   page numbers
11605                  *  
11606                  * Further methods can be added using {@link DataTable.ext.oPagination}.
11607                  *  @type string
11608                  *  @default simple_numbers
11609                  *
11610                  *  @dtopt Options
11611                  *  @name DataTable.defaults.pagingType
11612                  *
11613                  *  @example
11614                  *    $(document).ready( function() {
11615                  *      $('#example').dataTable( {
11616                  *        "pagingType": "full_numbers"
11617                  *      } );
11618                  *    } )
11619                  */
11620                 "sPaginationType": "simple_numbers",
11621         
11622         
11623                 /**
11624                  * Enable horizontal scrolling. When a table is too wide to fit into a
11625                  * certain layout, or you have a large number of columns in the table, you
11626                  * can enable x-scrolling to show the table in a viewport, which can be
11627                  * scrolled. This property can be `true` which will allow the table to
11628                  * scroll horizontally when needed, or any CSS unit, or a number (in which
11629                  * case it will be treated as a pixel measurement). Setting as simply `true`
11630                  * is recommended.
11631                  *  @type boolean|string
11632                  *  @default <i>blank string - i.e. disabled</i>
11633                  *
11634                  *  @dtopt Features
11635                  *  @name DataTable.defaults.scrollX
11636                  *
11637                  *  @example
11638                  *    $(document).ready( function() {
11639                  *      $('#example').dataTable( {
11640                  *        "scrollX": true,
11641                  *        "scrollCollapse": true
11642                  *      } );
11643                  *    } );
11644                  */
11645                 "sScrollX": "",
11646         
11647         
11648                 /**
11649                  * This property can be used to force a DataTable to use more width than it
11650                  * might otherwise do when x-scrolling is enabled. For example if you have a
11651                  * table which requires to be well spaced, this parameter is useful for
11652                  * "over-sizing" the table, and thus forcing scrolling. This property can by
11653                  * any CSS unit, or a number (in which case it will be treated as a pixel
11654                  * measurement).
11655                  *  @type string
11656                  *  @default <i>blank string - i.e. disabled</i>
11657                  *
11658                  *  @dtopt Options
11659                  *  @name DataTable.defaults.scrollXInner
11660                  *
11661                  *  @example
11662                  *    $(document).ready( function() {
11663                  *      $('#example').dataTable( {
11664                  *        "scrollX": "100%",
11665                  *        "scrollXInner": "110%"
11666                  *      } );
11667                  *    } );
11668                  */
11669                 "sScrollXInner": "",
11670         
11671         
11672                 /**
11673                  * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
11674                  * to the given height, and enable scrolling for any data which overflows the
11675                  * current viewport. This can be used as an alternative to paging to display
11676                  * a lot of data in a small area (although paging and scrolling can both be
11677                  * enabled at the same time). This property can be any CSS unit, or a number
11678                  * (in which case it will be treated as a pixel measurement).
11679                  *  @type string
11680                  *  @default <i>blank string - i.e. disabled</i>
11681                  *
11682                  *  @dtopt Features
11683                  *  @name DataTable.defaults.scrollY
11684                  *
11685                  *  @example
11686                  *    $(document).ready( function() {
11687                  *      $('#example').dataTable( {
11688                  *        "scrollY": "200px",
11689                  *        "paginate": false
11690                  *      } );
11691                  *    } );
11692                  */
11693                 "sScrollY": "",
11694         
11695         
11696                 /**
11697                  * __Deprecated__ The functionality provided by this parameter has now been
11698                  * superseded by that provided through `ajax`, which should be used instead.
11699                  *
11700                  * Set the HTTP method that is used to make the Ajax call for server-side
11701                  * processing or Ajax sourced data.
11702                  *  @type string
11703                  *  @default GET
11704                  *
11705                  *  @dtopt Options
11706                  *  @dtopt Server-side
11707                  *  @name DataTable.defaults.serverMethod
11708                  *
11709                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
11710                  */
11711                 "sServerMethod": "GET",
11712         
11713         
11714                 /**
11715                  * DataTables makes use of renderers when displaying HTML elements for
11716                  * a table. These renderers can be added or modified by plug-ins to
11717                  * generate suitable mark-up for a site. For example the Bootstrap
11718                  * integration plug-in for DataTables uses a paging button renderer to
11719                  * display pagination buttons in the mark-up required by Bootstrap.
11720                  *
11721                  * For further information about the renderers available see
11722                  * DataTable.ext.renderer
11723                  *  @type string|object
11724                  *  @default null
11725                  *
11726                  *  @name DataTable.defaults.renderer
11727                  *
11728                  */
11729                 "renderer": null
11730         };
11731         
11732         _fnHungarianMap( DataTable.defaults );
11733         
11734         
11735         
11736         /*
11737          * Developer note - See note in model.defaults.js about the use of Hungarian
11738          * notation and camel case.
11739          */
11740         
11741         /**
11742          * Column options that can be given to DataTables at initialisation time.
11743          *  @namespace
11744          */
11745         DataTable.defaults.column = {
11746                 /**
11747                  * Define which column(s) an order will occur on for this column. This
11748                  * allows a column's ordering to take multiple columns into account when
11749                  * doing a sort or use the data from a different column. For example first
11750                  * name / last name columns make sense to do a multi-column sort over the
11751                  * two columns.
11752                  *  @type array|int
11753                  *  @default null <i>Takes the value of the column index automatically</i>
11754                  *
11755                  *  @name DataTable.defaults.column.orderData
11756                  *  @dtopt Columns
11757                  *
11758                  *  @example
11759                  *    // Using `columnDefs`
11760                  *    $(document).ready( function() {
11761                  *      $('#example').dataTable( {
11762                  *        "columnDefs": [
11763                  *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
11764                  *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
11765                  *          { "orderData": 2, "targets": [ 2 ] }
11766                  *        ]
11767                  *      } );
11768                  *    } );
11769                  *
11770                  *  @example
11771                  *    // Using `columns`
11772                  *    $(document).ready( function() {
11773                  *      $('#example').dataTable( {
11774                  *        "columns": [
11775                  *          { "orderData": [ 0, 1 ] },
11776                  *          { "orderData": [ 1, 0 ] },
11777                  *          { "orderData": 2 },
11778                  *          null,
11779                  *          null
11780                  *        ]
11781                  *      } );
11782                  *    } );
11783                  */
11784                 "aDataSort": null,
11785                 "iDataSort": -1,
11786         
11787         
11788                 /**
11789                  * You can control the default ordering direction, and even alter the
11790                  * behaviour of the sort handler (i.e. only allow ascending ordering etc)
11791                  * using this parameter.
11792                  *  @type array
11793                  *  @default [ 'asc', 'desc' ]
11794                  *
11795                  *  @name DataTable.defaults.column.orderSequence
11796                  *  @dtopt Columns
11797                  *
11798                  *  @example
11799                  *    // Using `columnDefs`
11800                  *    $(document).ready( function() {
11801                  *      $('#example').dataTable( {
11802                  *        "columnDefs": [
11803                  *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
11804                  *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
11805                  *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
11806                  *        ]
11807                  *      } );
11808                  *    } );
11809                  *
11810                  *  @example
11811                  *    // Using `columns`
11812                  *    $(document).ready( function() {
11813                  *      $('#example').dataTable( {
11814                  *        "columns": [
11815                  *          null,
11816                  *          { "orderSequence": [ "asc" ] },
11817                  *          { "orderSequence": [ "desc", "asc", "asc" ] },
11818                  *          { "orderSequence": [ "desc" ] },
11819                  *          null
11820                  *        ]
11821                  *      } );
11822                  *    } );
11823                  */
11824                 "asSorting": [ 'asc', 'desc' ],
11825         
11826         
11827                 /**
11828                  * Enable or disable filtering on the data in this column.
11829                  *  @type boolean
11830                  *  @default true
11831                  *
11832                  *  @name DataTable.defaults.column.searchable
11833                  *  @dtopt Columns
11834                  *
11835                  *  @example
11836                  *    // Using `columnDefs`
11837                  *    $(document).ready( function() {
11838                  *      $('#example').dataTable( {
11839                  *        "columnDefs": [
11840                  *          { "searchable": false, "targets": [ 0 ] }
11841                  *        ] } );
11842                  *    } );
11843                  *
11844                  *  @example
11845                  *    // Using `columns`
11846                  *    $(document).ready( function() {
11847                  *      $('#example').dataTable( {
11848                  *        "columns": [
11849                  *          { "searchable": false },
11850                  *          null,
11851                  *          null,
11852                  *          null,
11853                  *          null
11854                  *        ] } );
11855                  *    } );
11856                  */
11857                 "bSearchable": true,
11858         
11859         
11860                 /**
11861                  * Enable or disable ordering on this column.
11862                  *  @type boolean
11863                  *  @default true
11864                  *
11865                  *  @name DataTable.defaults.column.orderable
11866                  *  @dtopt Columns
11867                  *
11868                  *  @example
11869                  *    // Using `columnDefs`
11870                  *    $(document).ready( function() {
11871                  *      $('#example').dataTable( {
11872                  *        "columnDefs": [
11873                  *          { "orderable": false, "targets": [ 0 ] }
11874                  *        ] } );
11875                  *    } );
11876                  *
11877                  *  @example
11878                  *    // Using `columns`
11879                  *    $(document).ready( function() {
11880                  *      $('#example').dataTable( {
11881                  *        "columns": [
11882                  *          { "orderable": false },
11883                  *          null,
11884                  *          null,
11885                  *          null,
11886                  *          null
11887                  *        ] } );
11888                  *    } );
11889                  */
11890                 "bSortable": true,
11891         
11892         
11893                 /**
11894                  * Enable or disable the display of this column.
11895                  *  @type boolean
11896                  *  @default true
11897                  *
11898                  *  @name DataTable.defaults.column.visible
11899                  *  @dtopt Columns
11900                  *
11901                  *  @example
11902                  *    // Using `columnDefs`
11903                  *    $(document).ready( function() {
11904                  *      $('#example').dataTable( {
11905                  *        "columnDefs": [
11906                  *          { "visible": false, "targets": [ 0 ] }
11907                  *        ] } );
11908                  *    } );
11909                  *
11910                  *  @example
11911                  *    // Using `columns`
11912                  *    $(document).ready( function() {
11913                  *      $('#example').dataTable( {
11914                  *        "columns": [
11915                  *          { "visible": false },
11916                  *          null,
11917                  *          null,
11918                  *          null,
11919                  *          null
11920                  *        ] } );
11921                  *    } );
11922                  */
11923                 "bVisible": true,
11924         
11925         
11926                 /**
11927                  * Developer definable function that is called whenever a cell is created (Ajax source,
11928                  * etc) or processed for input (DOM source). This can be used as a compliment to mRender
11929                  * allowing you to modify the DOM element (add background colour for example) when the
11930                  * element is available.
11931                  *  @type function
11932                  *  @param {element} td The TD node that has been created
11933                  *  @param {*} cellData The Data for the cell
11934                  *  @param {array|object} rowData The data for the whole row
11935                  *  @param {int} row The row index for the aoData data store
11936                  *  @param {int} col The column index for aoColumns
11937                  *
11938                  *  @name DataTable.defaults.column.createdCell
11939                  *  @dtopt Columns
11940                  *
11941                  *  @example
11942                  *    $(document).ready( function() {
11943                  *      $('#example').dataTable( {
11944                  *        "columnDefs": [ {
11945                  *          "targets": [3],
11946                  *          "createdCell": function (td, cellData, rowData, row, col) {
11947                  *            if ( cellData == "1.7" ) {
11948                  *              $(td).css('color', 'blue')
11949                  *            }
11950                  *          }
11951                  *        } ]
11952                  *      });
11953                  *    } );
11954                  */
11955                 "fnCreatedCell": null,
11956         
11957         
11958                 /**
11959                  * This parameter has been replaced by `data` in DataTables to ensure naming
11960                  * consistency. `dataProp` can still be used, as there is backwards
11961                  * compatibility in DataTables for this option, but it is strongly
11962                  * recommended that you use `data` in preference to `dataProp`.
11963                  *  @name DataTable.defaults.column.dataProp
11964                  */
11965         
11966         
11967                 /**
11968                  * This property can be used to read data from any data source property,
11969                  * including deeply nested objects / properties. `data` can be given in a
11970                  * number of different ways which effect its behaviour:
11971                  *
11972                  * * `integer` - treated as an array index for the data source. This is the
11973                  *   default that DataTables uses (incrementally increased for each column).
11974                  * * `string` - read an object property from the data source. There are
11975                  *   three 'special' options that can be used in the string to alter how
11976                  *   DataTables reads the data from the source object:
11977                  *    * `.` - Dotted Javascript notation. Just as you use a `.` in
11978                  *      Javascript to read from nested objects, so to can the options
11979                  *      specified in `data`. For example: `browser.version` or
11980                  *      `browser.name`. If your object parameter name contains a period, use
11981                  *      `\\` to escape it - i.e. `first\\.name`.
11982                  *    * `[]` - Array notation. DataTables can automatically combine data
11983                  *      from and array source, joining the data with the characters provided
11984                  *      between the two brackets. For example: `name[, ]` would provide a
11985                  *      comma-space separated list from the source array. If no characters
11986                  *      are provided between the brackets, the original array source is
11987                  *      returned.
11988                  *    * `()` - Function notation. Adding `()` to the end of a parameter will
11989                  *      execute a function of the name given. For example: `browser()` for a
11990                  *      simple function on the data source, `browser.version()` for a
11991                  *      function in a nested property or even `browser().version` to get an
11992                  *      object property if the function called returns an object. Note that
11993                  *      function notation is recommended for use in `render` rather than
11994                  *      `data` as it is much simpler to use as a renderer.
11995                  * * `null` - use the original data source for the row rather than plucking
11996                  *   data directly from it. This action has effects on two other
11997                  *   initialisation options:
11998                  *    * `defaultContent` - When null is given as the `data` option and
11999                  *      `defaultContent` is specified for the column, the value defined by
12000                  *      `defaultContent` will be used for the cell.
12001                  *    * `render` - When null is used for the `data` option and the `render`
12002                  *      option is specified for the column, the whole data source for the
12003                  *      row is used for the renderer.
12004                  * * `function` - the function given will be executed whenever DataTables
12005                  *   needs to set or get the data for a cell in the column. The function
12006                  *   takes three parameters:
12007                  *    * Parameters:
12008                  *      * `{array|object}` The data source for the row
12009                  *      * `{string}` The type call data requested - this will be 'set' when
12010                  *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12011                  *        when gathering data. Note that when `undefined` is given for the
12012                  *        type DataTables expects to get the raw data for the object back<
12013                  *      * `{*}` Data to set when the second parameter is 'set'.
12014                  *    * Return:
12015                  *      * The return value from the function is not required when 'set' is
12016                  *        the type of call, but otherwise the return is what will be used
12017                  *        for the data requested.
12018                  *
12019                  * Note that `data` is a getter and setter option. If you just require
12020                  * formatting of data for output, you will likely want to use `render` which
12021                  * is simply a getter and thus simpler to use.
12022                  *
12023                  * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12024                  * name change reflects the flexibility of this property and is consistent
12025                  * with the naming of mRender. If 'mDataProp' is given, then it will still
12026                  * be used by DataTables, as it automatically maps the old name to the new
12027                  * if required.
12028                  *
12029                  *  @type string|int|function|null
12030                  *  @default null <i>Use automatically calculated column index</i>
12031                  *
12032                  *  @name DataTable.defaults.column.data
12033                  *  @dtopt Columns
12034                  *
12035                  *  @example
12036                  *    // Read table data from objects
12037                  *    // JSON structure for each row:
12038                  *    //   {
12039                  *    //      "engine": {value},
12040                  *    //      "browser": {value},
12041                  *    //      "platform": {value},
12042                  *    //      "version": {value},
12043                  *    //      "grade": {value}
12044                  *    //   }
12045                  *    $(document).ready( function() {
12046                  *      $('#example').dataTable( {
12047                  *        "ajaxSource": "sources/objects.txt",
12048                  *        "columns": [
12049                  *          { "data": "engine" },
12050                  *          { "data": "browser" },
12051                  *          { "data": "platform" },
12052                  *          { "data": "version" },
12053                  *          { "data": "grade" }
12054                  *        ]
12055                  *      } );
12056                  *    } );
12057                  *
12058                  *  @example
12059                  *    // Read information from deeply nested objects
12060                  *    // JSON structure for each row:
12061                  *    //   {
12062                  *    //      "engine": {value},
12063                  *    //      "browser": {value},
12064                  *    //      "platform": {
12065                  *    //         "inner": {value}
12066                  *    //      },
12067                  *    //      "details": [
12068                  *    //         {value}, {value}
12069                  *    //      ]
12070                  *    //   }
12071                  *    $(document).ready( function() {
12072                  *      $('#example').dataTable( {
12073                  *        "ajaxSource": "sources/deep.txt",
12074                  *        "columns": [
12075                  *          { "data": "engine" },
12076                  *          { "data": "browser" },
12077                  *          { "data": "platform.inner" },
12078                  *          { "data": "platform.details.0" },
12079                  *          { "data": "platform.details.1" }
12080                  *        ]
12081                  *      } );
12082                  *    } );
12083                  *
12084                  *  @example
12085                  *    // Using `data` as a function to provide different information for
12086                  *    // sorting, filtering and display. In this case, currency (price)
12087                  *    $(document).ready( function() {
12088                  *      $('#example').dataTable( {
12089                  *        "columnDefs": [ {
12090                  *          "targets": [ 0 ],
12091                  *          "data": function ( source, type, val ) {
12092                  *            if (type === 'set') {
12093                  *              source.price = val;
12094                  *              // Store the computed dislay and filter values for efficiency
12095                  *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12096                  *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12097                  *              return;
12098                  *            }
12099                  *            else if (type === 'display') {
12100                  *              return source.price_display;
12101                  *            }
12102                  *            else if (type === 'filter') {
12103                  *              return source.price_filter;
12104                  *            }
12105                  *            // 'sort', 'type' and undefined all just use the integer
12106                  *            return source.price;
12107                  *          }
12108                  *        } ]
12109                  *      } );
12110                  *    } );
12111                  *
12112                  *  @example
12113                  *    // Using default content
12114                  *    $(document).ready( function() {
12115                  *      $('#example').dataTable( {
12116                  *        "columnDefs": [ {
12117                  *          "targets": [ 0 ],
12118                  *          "data": null,
12119                  *          "defaultContent": "Click to edit"
12120                  *        } ]
12121                  *      } );
12122                  *    } );
12123                  *
12124                  *  @example
12125                  *    // Using array notation - outputting a list from an array
12126                  *    $(document).ready( function() {
12127                  *      $('#example').dataTable( {
12128                  *        "columnDefs": [ {
12129                  *          "targets": [ 0 ],
12130                  *          "data": "name[, ]"
12131                  *        } ]
12132                  *      } );
12133                  *    } );
12134                  *
12135                  */
12136                 "mData": null,
12137         
12138         
12139                 /**
12140                  * This property is the rendering partner to `data` and it is suggested that
12141                  * when you want to manipulate data for display (including filtering,
12142                  * sorting etc) without altering the underlying data for the table, use this
12143                  * property. `render` can be considered to be the the read only companion to
12144                  * `data` which is read / write (then as such more complex). Like `data`
12145                  * this option can be given in a number of different ways to effect its
12146                  * behaviour:
12147                  *
12148                  * * `integer` - treated as an array index for the data source. This is the
12149                  *   default that DataTables uses (incrementally increased for each column).
12150                  * * `string` - read an object property from the data source. There are
12151                  *   three 'special' options that can be used in the string to alter how
12152                  *   DataTables reads the data from the source object:
12153                  *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12154                  *      Javascript to read from nested objects, so to can the options
12155                  *      specified in `data`. For example: `browser.version` or
12156                  *      `browser.name`. If your object parameter name contains a period, use
12157                  *      `\\` to escape it - i.e. `first\\.name`.
12158                  *    * `[]` - Array notation. DataTables can automatically combine data
12159                  *      from and array source, joining the data with the characters provided
12160                  *      between the two brackets. For example: `name[, ]` would provide a
12161                  *      comma-space separated list from the source array. If no characters
12162                  *      are provided between the brackets, the original array source is
12163                  *      returned.
12164                  *    * `()` - Function notation. Adding `()` to the end of a parameter will
12165                  *      execute a function of the name given. For example: `browser()` for a
12166                  *      simple function on the data source, `browser.version()` for a
12167                  *      function in a nested property or even `browser().version` to get an
12168                  *      object property if the function called returns an object.
12169                  * * `object` - use different data for the different data types requested by
12170                  *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12171                  *   of the object is the data type the property refers to and the value can
12172                  *   defined using an integer, string or function using the same rules as
12173                  *   `render` normally does. Note that an `_` option _must_ be specified.
12174                  *   This is the default value to use if you haven't specified a value for
12175                  *   the data type requested by DataTables.
12176                  * * `function` - the function given will be executed whenever DataTables
12177                  *   needs to set or get the data for a cell in the column. The function
12178                  *   takes three parameters:
12179                  *    * Parameters:
12180                  *      * {array|object} The data source for the row (based on `data`)
12181                  *      * {string} The type call data requested - this will be 'filter',
12182                  *        'display', 'type' or 'sort'.
12183                  *      * {array|object} The full data source for the row (not based on
12184                  *        `data`)
12185                  *    * Return:
12186                  *      * The return value from the function is what will be used for the
12187                  *        data requested.
12188                  *
12189                  *  @type string|int|function|object|null
12190                  *  @default null Use the data source value.
12191                  *
12192                  *  @name DataTable.defaults.column.render
12193                  *  @dtopt Columns
12194                  *
12195                  *  @example
12196                  *    // Create a comma separated list from an array of objects
12197                  *    $(document).ready( function() {
12198                  *      $('#example').dataTable( {
12199                  *        "ajaxSource": "sources/deep.txt",
12200                  *        "columns": [
12201                  *          { "data": "engine" },
12202                  *          { "data": "browser" },
12203                  *          {
12204                  *            "data": "platform",
12205                  *            "render": "[, ].name"
12206                  *          }
12207                  *        ]
12208                  *      } );
12209                  *    } );
12210                  *
12211                  *  @example
12212                  *    // Execute a function to obtain data
12213                  *    $(document).ready( function() {
12214                  *      $('#example').dataTable( {
12215                  *        "columnDefs": [ {
12216                  *          "targets": [ 0 ],
12217                  *          "data": null, // Use the full data source object for the renderer's source
12218                  *          "render": "browserName()"
12219                  *        } ]
12220                  *      } );
12221                  *    } );
12222                  *
12223                  *  @example
12224                  *    // As an object, extracting different data for the different types
12225                  *    // This would be used with a data source such as:
12226                  *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12227                  *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12228                  *    // (which has both forms) is used for filtering for if a user inputs either format, while
12229                  *    // the formatted phone number is the one that is shown in the table.
12230                  *    $(document).ready( function() {
12231                  *      $('#example').dataTable( {
12232                  *        "columnDefs": [ {
12233                  *          "targets": [ 0 ],
12234                  *          "data": null, // Use the full data source object for the renderer's source
12235                  *          "render": {
12236                  *            "_": "phone",
12237                  *            "filter": "phone_filter",
12238                  *            "display": "phone_display"
12239                  *          }
12240                  *        } ]
12241                  *      } );
12242                  *    } );
12243                  *
12244                  *  @example
12245                  *    // Use as a function to create a link from the data source
12246                  *    $(document).ready( function() {
12247                  *      $('#example').dataTable( {
12248                  *        "columnDefs": [ {
12249                  *          "targets": [ 0 ],
12250                  *          "data": "download_link",
12251                  *          "render": function ( data, type, full ) {
12252                  *            return '<a href="'+data+'">Download</a>';
12253                  *          }
12254                  *        } ]
12255                  *      } );
12256                  *    } );
12257                  */
12258                 "mRender": null,
12259         
12260         
12261                 /**
12262                  * Change the cell type created for the column - either TD cells or TH cells. This
12263                  * can be useful as TH cells have semantic meaning in the table body, allowing them
12264                  * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12265                  *  @type string
12266                  *  @default td
12267                  *
12268                  *  @name DataTable.defaults.column.cellType
12269                  *  @dtopt Columns
12270                  *
12271                  *  @example
12272                  *    // Make the first column use TH cells
12273                  *    $(document).ready( function() {
12274                  *      $('#example').dataTable( {
12275                  *        "columnDefs": [ {
12276                  *          "targets": [ 0 ],
12277                  *          "cellType": "th"
12278                  *        } ]
12279                  *      } );
12280                  *    } );
12281                  */
12282                 "sCellType": "td",
12283         
12284         
12285                 /**
12286                  * Class to give to each cell in this column.
12287                  *  @type string
12288                  *  @default <i>Empty string</i>
12289                  *
12290                  *  @name DataTable.defaults.column.class
12291                  *  @dtopt Columns
12292                  *
12293                  *  @example
12294                  *    // Using `columnDefs`
12295                  *    $(document).ready( function() {
12296                  *      $('#example').dataTable( {
12297                  *        "columnDefs": [
12298                  *          { "class": "my_class", "targets": [ 0 ] }
12299                  *        ]
12300                  *      } );
12301                  *    } );
12302                  *
12303                  *  @example
12304                  *    // Using `columns`
12305                  *    $(document).ready( function() {
12306                  *      $('#example').dataTable( {
12307                  *        "columns": [
12308                  *          { "class": "my_class" },
12309                  *          null,
12310                  *          null,
12311                  *          null,
12312                  *          null
12313                  *        ]
12314                  *      } );
12315                  *    } );
12316                  */
12317                 "sClass": "",
12318         
12319                 /**
12320                  * When DataTables calculates the column widths to assign to each column,
12321                  * it finds the longest string in each column and then constructs a
12322                  * temporary table and reads the widths from that. The problem with this
12323                  * is that "mmm" is much wider then "iiii", but the latter is a longer
12324                  * string - thus the calculation can go wrong (doing it properly and putting
12325                  * it into an DOM object and measuring that is horribly(!) slow). Thus as
12326                  * a "work around" we provide this option. It will append its value to the
12327                  * text that is found to be the longest string for the column - i.e. padding.
12328                  * Generally you shouldn't need this!
12329                  *  @type string
12330                  *  @default <i>Empty string<i>
12331                  *
12332                  *  @name DataTable.defaults.column.contentPadding
12333                  *  @dtopt Columns
12334                  *
12335                  *  @example
12336                  *    // Using `columns`
12337                  *    $(document).ready( function() {
12338                  *      $('#example').dataTable( {
12339                  *        "columns": [
12340                  *          null,
12341                  *          null,
12342                  *          null,
12343                  *          {
12344                  *            "contentPadding": "mmm"
12345                  *          }
12346                  *        ]
12347                  *      } );
12348                  *    } );
12349                  */
12350                 "sContentPadding": "",
12351         
12352         
12353                 /**
12354                  * Allows a default value to be given for a column's data, and will be used
12355                  * whenever a null data source is encountered (this can be because `data`
12356                  * is set to null, or because the data source itself is null).
12357                  *  @type string
12358                  *  @default null
12359                  *
12360                  *  @name DataTable.defaults.column.defaultContent
12361                  *  @dtopt Columns
12362                  *
12363                  *  @example
12364                  *    // Using `columnDefs`
12365                  *    $(document).ready( function() {
12366                  *      $('#example').dataTable( {
12367                  *        "columnDefs": [
12368                  *          {
12369                  *            "data": null,
12370                  *            "defaultContent": "Edit",
12371                  *            "targets": [ -1 ]
12372                  *          }
12373                  *        ]
12374                  *      } );
12375                  *    } );
12376                  *
12377                  *  @example
12378                  *    // Using `columns`
12379                  *    $(document).ready( function() {
12380                  *      $('#example').dataTable( {
12381                  *        "columns": [
12382                  *          null,
12383                  *          null,
12384                  *          null,
12385                  *          {
12386                  *            "data": null,
12387                  *            "defaultContent": "Edit"
12388                  *          }
12389                  *        ]
12390                  *      } );
12391                  *    } );
12392                  */
12393                 "sDefaultContent": null,
12394         
12395         
12396                 /**
12397                  * This parameter is only used in DataTables' server-side processing. It can
12398                  * be exceptionally useful to know what columns are being displayed on the
12399                  * client side, and to map these to database fields. When defined, the names
12400                  * also allow DataTables to reorder information from the server if it comes
12401                  * back in an unexpected order (i.e. if you switch your columns around on the
12402                  * client-side, your server-side code does not also need updating).
12403                  *  @type string
12404                  *  @default <i>Empty string</i>
12405                  *
12406                  *  @name DataTable.defaults.column.name
12407                  *  @dtopt Columns
12408                  *
12409                  *  @example
12410                  *    // Using `columnDefs`
12411                  *    $(document).ready( function() {
12412                  *      $('#example').dataTable( {
12413                  *        "columnDefs": [
12414                  *          { "name": "engine", "targets": [ 0 ] },
12415                  *          { "name": "browser", "targets": [ 1 ] },
12416                  *          { "name": "platform", "targets": [ 2 ] },
12417                  *          { "name": "version", "targets": [ 3 ] },
12418                  *          { "name": "grade", "targets": [ 4 ] }
12419                  *        ]
12420                  *      } );
12421                  *    } );
12422                  *
12423                  *  @example
12424                  *    // Using `columns`
12425                  *    $(document).ready( function() {
12426                  *      $('#example').dataTable( {
12427                  *        "columns": [
12428                  *          { "name": "engine" },
12429                  *          { "name": "browser" },
12430                  *          { "name": "platform" },
12431                  *          { "name": "version" },
12432                  *          { "name": "grade" }
12433                  *        ]
12434                  *      } );
12435                  *    } );
12436                  */
12437                 "sName": "",
12438         
12439         
12440                 /**
12441                  * Defines a data source type for the ordering which can be used to read
12442                  * real-time information from the table (updating the internally cached
12443                  * version) prior to ordering. This allows ordering to occur on user
12444                  * editable elements such as form inputs.
12445                  *  @type string
12446                  *  @default std
12447                  *
12448                  *  @name DataTable.defaults.column.orderDataType
12449                  *  @dtopt Columns
12450                  *
12451                  *  @example
12452                  *    // Using `columnDefs`
12453                  *    $(document).ready( function() {
12454                  *      $('#example').dataTable( {
12455                  *        "columnDefs": [
12456                  *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12457                  *          { "type": "numeric", "targets": [ 3 ] },
12458                  *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12459                  *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12460                  *        ]
12461                  *      } );
12462                  *    } );
12463                  *
12464                  *  @example
12465                  *    // Using `columns`
12466                  *    $(document).ready( function() {
12467                  *      $('#example').dataTable( {
12468                  *        "columns": [
12469                  *          null,
12470                  *          null,
12471                  *          { "orderDataType": "dom-text" },
12472                  *          { "orderDataType": "dom-text", "type": "numeric" },
12473                  *          { "orderDataType": "dom-select" },
12474                  *          { "orderDataType": "dom-checkbox" }
12475                  *        ]
12476                  *      } );
12477                  *    } );
12478                  */
12479                 "sSortDataType": "std",
12480         
12481         
12482                 /**
12483                  * The title of this column.
12484                  *  @type string
12485                  *  @default null <i>Derived from the 'TH' value for this column in the
12486                  *    original HTML table.</i>
12487                  *
12488                  *  @name DataTable.defaults.column.title
12489                  *  @dtopt Columns
12490                  *
12491                  *  @example
12492                  *    // Using `columnDefs`
12493                  *    $(document).ready( function() {
12494                  *      $('#example').dataTable( {
12495                  *        "columnDefs": [
12496                  *          { "title": "My column title", "targets": [ 0 ] }
12497                  *        ]
12498                  *      } );
12499                  *    } );
12500                  *
12501                  *  @example
12502                  *    // Using `columns`
12503                  *    $(document).ready( function() {
12504                  *      $('#example').dataTable( {
12505                  *        "columns": [
12506                  *          { "title": "My column title" },
12507                  *          null,
12508                  *          null,
12509                  *          null,
12510                  *          null
12511                  *        ]
12512                  *      } );
12513                  *    } );
12514                  */
12515                 "sTitle": null,
12516         
12517         
12518                 /**
12519                  * The type allows you to specify how the data for this column will be
12520                  * ordered. Four types (string, numeric, date and html (which will strip
12521                  * HTML tags before ordering)) are currently available. Note that only date
12522                  * formats understood by Javascript's Date() object will be accepted as type
12523                  * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12524                  * 'numeric', 'date' or 'html' (by default). Further types can be adding
12525                  * through plug-ins.
12526                  *  @type string
12527                  *  @default null <i>Auto-detected from raw data</i>
12528                  *
12529                  *  @name DataTable.defaults.column.type
12530                  *  @dtopt Columns
12531                  *
12532                  *  @example
12533                  *    // Using `columnDefs`
12534                  *    $(document).ready( function() {
12535                  *      $('#example').dataTable( {
12536                  *        "columnDefs": [
12537                  *          { "type": "html", "targets": [ 0 ] }
12538                  *        ]
12539                  *      } );
12540                  *    } );
12541                  *
12542                  *  @example
12543                  *    // Using `columns`
12544                  *    $(document).ready( function() {
12545                  *      $('#example').dataTable( {
12546                  *        "columns": [
12547                  *          { "type": "html" },
12548                  *          null,
12549                  *          null,
12550                  *          null,
12551                  *          null
12552                  *        ]
12553                  *      } );
12554                  *    } );
12555                  */
12556                 "sType": null,
12557         
12558         
12559                 /**
12560                  * Defining the width of the column, this parameter may take any CSS value
12561                  * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12562                  * been given a specific width through this interface ensuring that the table
12563                  * remains readable.
12564                  *  @type string
12565                  *  @default null <i>Automatic</i>
12566                  *
12567                  *  @name DataTable.defaults.column.width
12568                  *  @dtopt Columns
12569                  *
12570                  *  @example
12571                  *    // Using `columnDefs`
12572                  *    $(document).ready( function() {
12573                  *      $('#example').dataTable( {
12574                  *        "columnDefs": [
12575                  *          { "width": "20%", "targets": [ 0 ] }
12576                  *        ]
12577                  *      } );
12578                  *    } );
12579                  *
12580                  *  @example
12581                  *    // Using `columns`
12582                  *    $(document).ready( function() {
12583                  *      $('#example').dataTable( {
12584                  *        "columns": [
12585                  *          { "width": "20%" },
12586                  *          null,
12587                  *          null,
12588                  *          null,
12589                  *          null
12590                  *        ]
12591                  *      } );
12592                  *    } );
12593                  */
12594                 "sWidth": null
12595         };
12596         
12597         _fnHungarianMap( DataTable.defaults.column );
12598         
12599         
12600         
12601         /**
12602          * DataTables settings object - this holds all the information needed for a
12603          * given table, including configuration, data and current application of the
12604          * table options. DataTables does not have a single instance for each DataTable
12605          * with the settings attached to that instance, but rather instances of the
12606          * DataTable "class" are created on-the-fly as needed (typically by a
12607          * $().dataTable() call) and the settings object is then applied to that
12608          * instance.
12609          *
12610          * Note that this object is related to {@link DataTable.defaults} but this
12611          * one is the internal data store for DataTables's cache of columns. It should
12612          * NOT be manipulated outside of DataTables. Any configuration should be done
12613          * through the initialisation options.
12614          *  @namespace
12615          *  @todo Really should attach the settings object to individual instances so we
12616          *    don't need to create new instances on each $().dataTable() call (if the
12617          *    table already exists). It would also save passing oSettings around and
12618          *    into every single function. However, this is a very significant
12619          *    architecture change for DataTables and will almost certainly break
12620          *    backwards compatibility with older installations. This is something that
12621          *    will be done in 2.0.
12622          */
12623         DataTable.models.oSettings = {
12624                 /**
12625                  * Primary features of DataTables and their enablement state.
12626                  *  @namespace
12627                  */
12628                 "oFeatures": {
12629         
12630                         /**
12631                          * Flag to say if DataTables should automatically try to calculate the
12632                          * optimum table and columns widths (true) or not (false).
12633                          * Note that this parameter will be set by the initialisation routine. To
12634                          * set a default use {@link DataTable.defaults}.
12635                          *  @type boolean
12636                          */
12637                         "bAutoWidth": null,
12638         
12639                         /**
12640                          * Delay the creation of TR and TD elements until they are actually
12641                          * needed by a driven page draw. This can give a significant speed
12642                          * increase for Ajax source and Javascript source data, but makes no
12643                          * difference at all fro DOM and server-side processing tables.
12644                          * Note that this parameter will be set by the initialisation routine. To
12645                          * set a default use {@link DataTable.defaults}.
12646                          *  @type boolean
12647                          */
12648                         "bDeferRender": null,
12649         
12650                         /**
12651                          * Enable filtering on the table or not. Note that if this is disabled
12652                          * then there is no filtering at all on the table, including fnFilter.
12653                          * To just remove the filtering input use sDom and remove the 'f' option.
12654                          * Note that this parameter will be set by the initialisation routine. To
12655                          * set a default use {@link DataTable.defaults}.
12656                          *  @type boolean
12657                          */
12658                         "bFilter": null,
12659         
12660                         /**
12661                          * Table information element (the 'Showing x of y records' div) enable
12662                          * flag.
12663                          * Note that this parameter will be set by the initialisation routine. To
12664                          * set a default use {@link DataTable.defaults}.
12665                          *  @type boolean
12666                          */
12667                         "bInfo": null,
12668         
12669                         /**
12670                          * Present a user control allowing the end user to change the page size
12671                          * when pagination is enabled.
12672                          * Note that this parameter will be set by the initialisation routine. To
12673                          * set a default use {@link DataTable.defaults}.
12674                          *  @type boolean
12675                          */
12676                         "bLengthChange": null,
12677         
12678                         /**
12679                          * Pagination enabled or not. Note that if this is disabled then length
12680                          * changing must also be disabled.
12681                          * Note that this parameter will be set by the initialisation routine. To
12682                          * set a default use {@link DataTable.defaults}.
12683                          *  @type boolean
12684                          */
12685                         "bPaginate": null,
12686         
12687                         /**
12688                          * Processing indicator enable flag whenever DataTables is enacting a
12689                          * user request - typically an Ajax request for server-side processing.
12690                          * Note that this parameter will be set by the initialisation routine. To
12691                          * set a default use {@link DataTable.defaults}.
12692                          *  @type boolean
12693                          */
12694                         "bProcessing": null,
12695         
12696                         /**
12697                          * Server-side processing enabled flag - when enabled DataTables will
12698                          * get all data from the server for every draw - there is no filtering,
12699                          * sorting or paging done on the client-side.
12700                          * Note that this parameter will be set by the initialisation routine. To
12701                          * set a default use {@link DataTable.defaults}.
12702                          *  @type boolean
12703                          */
12704                         "bServerSide": null,
12705         
12706                         /**
12707                          * Sorting enablement flag.
12708                          * Note that this parameter will be set by the initialisation routine. To
12709                          * set a default use {@link DataTable.defaults}.
12710                          *  @type boolean
12711                          */
12712                         "bSort": null,
12713         
12714                         /**
12715                          * Multi-column sorting
12716                          * Note that this parameter will be set by the initialisation routine. To
12717                          * set a default use {@link DataTable.defaults}.
12718                          *  @type boolean
12719                          */
12720                         "bSortMulti": null,
12721         
12722                         /**
12723                          * Apply a class to the columns which are being sorted to provide a
12724                          * visual highlight or not. This can slow things down when enabled since
12725                          * there is a lot of DOM interaction.
12726                          * Note that this parameter will be set by the initialisation routine. To
12727                          * set a default use {@link DataTable.defaults}.
12728                          *  @type boolean
12729                          */
12730                         "bSortClasses": null,
12731         
12732                         /**
12733                          * State saving enablement flag.
12734                          * Note that this parameter will be set by the initialisation routine. To
12735                          * set a default use {@link DataTable.defaults}.
12736                          *  @type boolean
12737                          */
12738                         "bStateSave": null
12739                 },
12740         
12741         
12742                 /**
12743                  * Scrolling settings for a table.
12744                  *  @namespace
12745                  */
12746                 "oScroll": {
12747                         /**
12748                          * When the table is shorter in height than sScrollY, collapse the
12749                          * table container down to the height of the table (when true).
12750                          * Note that this parameter will be set by the initialisation routine. To
12751                          * set a default use {@link DataTable.defaults}.
12752                          *  @type boolean
12753                          */
12754                         "bCollapse": null,
12755         
12756                         /**
12757                          * Width of the scrollbar for the web-browser's platform. Calculated
12758                          * during table initialisation.
12759                          *  @type int
12760                          *  @default 0
12761                          */
12762                         "iBarWidth": 0,
12763         
12764                         /**
12765                          * Viewport width for horizontal scrolling. Horizontal scrolling is
12766                          * disabled if an empty string.
12767                          * Note that this parameter will be set by the initialisation routine. To
12768                          * set a default use {@link DataTable.defaults}.
12769                          *  @type string
12770                          */
12771                         "sX": null,
12772         
12773                         /**
12774                          * Width to expand the table to when using x-scrolling. Typically you
12775                          * should not need to use this.
12776                          * Note that this parameter will be set by the initialisation routine. To
12777                          * set a default use {@link DataTable.defaults}.
12778                          *  @type string
12779                          *  @deprecated
12780                          */
12781                         "sXInner": null,
12782         
12783                         /**
12784                          * Viewport height for vertical scrolling. Vertical scrolling is disabled
12785                          * if an empty string.
12786                          * Note that this parameter will be set by the initialisation routine. To
12787                          * set a default use {@link DataTable.defaults}.
12788                          *  @type string
12789                          */
12790                         "sY": null
12791                 },
12792         
12793                 /**
12794                  * Language information for the table.
12795                  *  @namespace
12796                  *  @extends DataTable.defaults.oLanguage
12797                  */
12798                 "oLanguage": {
12799                         /**
12800                          * Information callback function. See
12801                          * {@link DataTable.defaults.fnInfoCallback}
12802                          *  @type function
12803                          *  @default null
12804                          */
12805                         "fnInfoCallback": null
12806                 },
12807         
12808                 /**
12809                  * Browser support parameters
12810                  *  @namespace
12811                  */
12812                 "oBrowser": {
12813                         /**
12814                          * Indicate if the browser incorrectly calculates width:100% inside a
12815                          * scrolling element (IE6/7)
12816                          *  @type boolean
12817                          *  @default false
12818                          */
12819                         "bScrollOversize": false,
12820         
12821                         /**
12822                          * Determine if the vertical scrollbar is on the right or left of the
12823                          * scrolling container - needed for rtl language layout, although not
12824                          * all browsers move the scrollbar (Safari).
12825                          *  @type boolean
12826                          *  @default false
12827                          */
12828                         "bScrollbarLeft": false
12829                 },
12830         
12831         
12832                 "ajax": null,
12833         
12834         
12835                 /**
12836                  * Array referencing the nodes which are used for the features. The
12837                  * parameters of this object match what is allowed by sDom - i.e.
12838                  *   <ul>
12839                  *     <li>'l' - Length changing</li>
12840                  *     <li>'f' - Filtering input</li>
12841                  *     <li>'t' - The table!</li>
12842                  *     <li>'i' - Information</li>
12843                  *     <li>'p' - Pagination</li>
12844                  *     <li>'r' - pRocessing</li>
12845                  *   </ul>
12846                  *  @type array
12847                  *  @default []
12848                  */
12849                 "aanFeatures": [],
12850         
12851                 /**
12852                  * Store data information - see {@link DataTable.models.oRow} for detailed
12853                  * information.
12854                  *  @type array
12855                  *  @default []
12856                  */
12857                 "aoData": [],
12858         
12859                 /**
12860                  * Array of indexes which are in the current display (after filtering etc)
12861                  *  @type array
12862                  *  @default []
12863                  */
12864                 "aiDisplay": [],
12865         
12866                 /**
12867                  * Array of indexes for display - no filtering
12868                  *  @type array
12869                  *  @default []
12870                  */
12871                 "aiDisplayMaster": [],
12872         
12873                 /**
12874                  * Store information about each column that is in use
12875                  *  @type array
12876                  *  @default []
12877                  */
12878                 "aoColumns": [],
12879         
12880                 /**
12881                  * Store information about the table's header
12882                  *  @type array
12883                  *  @default []
12884                  */
12885                 "aoHeader": [],
12886         
12887                 /**
12888                  * Store information about the table's footer
12889                  *  @type array
12890                  *  @default []
12891                  */
12892                 "aoFooter": [],
12893         
12894                 /**
12895                  * Store the applied global search information in case we want to force a
12896                  * research or compare the old search to a new one.
12897                  * Note that this parameter will be set by the initialisation routine. To
12898                  * set a default use {@link DataTable.defaults}.
12899                  *  @namespace
12900                  *  @extends DataTable.models.oSearch
12901                  */
12902                 "oPreviousSearch": {},
12903         
12904                 /**
12905                  * Store the applied search for each column - see
12906                  * {@link DataTable.models.oSearch} for the format that is used for the
12907                  * filtering information for each column.
12908                  *  @type array
12909                  *  @default []
12910                  */
12911                 "aoPreSearchCols": [],
12912         
12913                 /**
12914                  * Sorting that is applied to the table. Note that the inner arrays are
12915                  * used in the following manner:
12916                  * <ul>
12917                  *   <li>Index 0 - column number</li>
12918                  *   <li>Index 1 - current sorting direction</li>
12919                  * </ul>
12920                  * Note that this parameter will be set by the initialisation routine. To
12921                  * set a default use {@link DataTable.defaults}.
12922                  *  @type array
12923                  *  @todo These inner arrays should really be objects
12924                  */
12925                 "aaSorting": null,
12926         
12927                 /**
12928                  * Sorting that is always applied to the table (i.e. prefixed in front of
12929                  * aaSorting).
12930                  * Note that this parameter will be set by the initialisation routine. To
12931                  * set a default use {@link DataTable.defaults}.
12932                  *  @type array
12933                  *  @default []
12934                  */
12935                 "aaSortingFixed": [],
12936         
12937                 /**
12938                  * Classes to use for the striping of a table.
12939                  * Note that this parameter will be set by the initialisation routine. To
12940                  * set a default use {@link DataTable.defaults}.
12941                  *  @type array
12942                  *  @default []
12943                  */
12944                 "asStripeClasses": null,
12945         
12946                 /**
12947                  * If restoring a table - we should restore its striping classes as well
12948                  *  @type array
12949                  *  @default []
12950                  */
12951                 "asDestroyStripes": [],
12952         
12953                 /**
12954                  * If restoring a table - we should restore its width
12955                  *  @type int
12956                  *  @default 0
12957                  */
12958                 "sDestroyWidth": 0,
12959         
12960                 /**
12961                  * Callback functions array for every time a row is inserted (i.e. on a draw).
12962                  *  @type array
12963                  *  @default []
12964                  */
12965                 "aoRowCallback": [],
12966         
12967                 /**
12968                  * Callback functions for the header on each draw.
12969                  *  @type array
12970                  *  @default []
12971                  */
12972                 "aoHeaderCallback": [],
12973         
12974                 /**
12975                  * Callback function for the footer on each draw.
12976                  *  @type array
12977                  *  @default []
12978                  */
12979                 "aoFooterCallback": [],
12980         
12981                 /**
12982                  * Array of callback functions for draw callback functions
12983                  *  @type array
12984                  *  @default []
12985                  */
12986                 "aoDrawCallback": [],
12987         
12988                 /**
12989                  * Array of callback functions for row created function
12990                  *  @type array
12991                  *  @default []
12992                  */
12993                 "aoRowCreatedCallback": [],
12994         
12995                 /**
12996                  * Callback functions for just before the table is redrawn. A return of
12997                  * false will be used to cancel the draw.
12998                  *  @type array
12999                  *  @default []
13000                  */
13001                 "aoPreDrawCallback": [],
13002         
13003                 /**
13004                  * Callback functions for when the table has been initialised.
13005                  *  @type array
13006                  *  @default []
13007                  */
13008                 "aoInitComplete": [],
13009         
13010         
13011                 /**
13012                  * Callbacks for modifying the settings to be stored for state saving, prior to
13013                  * saving state.
13014                  *  @type array
13015                  *  @default []
13016                  */
13017                 "aoStateSaveParams": [],
13018         
13019                 /**
13020                  * Callbacks for modifying the settings that have been stored for state saving
13021                  * prior to using the stored values to restore the state.
13022                  *  @type array
13023                  *  @default []
13024                  */
13025                 "aoStateLoadParams": [],
13026         
13027                 /**
13028                  * Callbacks for operating on the settings object once the saved state has been
13029                  * loaded
13030                  *  @type array
13031                  *  @default []
13032                  */
13033                 "aoStateLoaded": [],
13034         
13035                 /**
13036                  * Cache the table ID for quick access
13037                  *  @type string
13038                  *  @default <i>Empty string</i>
13039                  */
13040                 "sTableId": "",
13041         
13042                 /**
13043                  * The TABLE node for the main table
13044                  *  @type node
13045                  *  @default null
13046                  */
13047                 "nTable": null,
13048         
13049                 /**
13050                  * Permanent ref to the thead element
13051                  *  @type node
13052                  *  @default null
13053                  */
13054                 "nTHead": null,
13055         
13056                 /**
13057                  * Permanent ref to the tfoot element - if it exists
13058                  *  @type node
13059                  *  @default null
13060                  */
13061                 "nTFoot": null,
13062         
13063                 /**
13064                  * Permanent ref to the tbody element
13065                  *  @type node
13066                  *  @default null
13067                  */
13068                 "nTBody": null,
13069         
13070                 /**
13071                  * Cache the wrapper node (contains all DataTables controlled elements)
13072                  *  @type node
13073                  *  @default null
13074                  */
13075                 "nTableWrapper": null,
13076         
13077                 /**
13078                  * Indicate if when using server-side processing the loading of data
13079                  * should be deferred until the second draw.
13080                  * Note that this parameter will be set by the initialisation routine. To
13081                  * set a default use {@link DataTable.defaults}.
13082                  *  @type boolean
13083                  *  @default false
13084                  */
13085                 "bDeferLoading": false,
13086         
13087                 /**
13088                  * Indicate if all required information has been read in
13089                  *  @type boolean
13090                  *  @default false
13091                  */
13092                 "bInitialised": false,
13093         
13094                 /**
13095                  * Information about open rows. Each object in the array has the parameters
13096                  * 'nTr' and 'nParent'
13097                  *  @type array
13098                  *  @default []
13099                  */
13100                 "aoOpenRows": [],
13101         
13102                 /**
13103                  * Dictate the positioning of DataTables' control elements - see
13104                  * {@link DataTable.model.oInit.sDom}.
13105                  * Note that this parameter will be set by the initialisation routine. To
13106                  * set a default use {@link DataTable.defaults}.
13107                  *  @type string
13108                  *  @default null
13109                  */
13110                 "sDom": null,
13111         
13112                 /**
13113                  * Search delay (in mS)
13114                  *  @type integer
13115                  *  @default null
13116                  */
13117                 "searchDelay": null,
13118         
13119                 /**
13120                  * Which type of pagination should be used.
13121                  * Note that this parameter will be set by the initialisation routine. To
13122                  * set a default use {@link DataTable.defaults}.
13123                  *  @type string
13124                  *  @default two_button
13125                  */
13126                 "sPaginationType": "two_button",
13127         
13128                 /**
13129                  * The state duration (for `stateSave`) in seconds.
13130                  * Note that this parameter will be set by the initialisation routine. To
13131                  * set a default use {@link DataTable.defaults}.
13132                  *  @type int
13133                  *  @default 0
13134                  */
13135                 "iStateDuration": 0,
13136         
13137                 /**
13138                  * Array of callback functions for state saving. Each array element is an
13139                  * object with the following parameters:
13140                  *   <ul>
13141                  *     <li>function:fn - function to call. Takes two parameters, oSettings
13142                  *       and the JSON string to save that has been thus far created. Returns
13143                  *       a JSON string to be inserted into a json object
13144                  *       (i.e. '"param": [ 0, 1, 2]')</li>
13145                  *     <li>string:sName - name of callback</li>
13146                  *   </ul>
13147                  *  @type array
13148                  *  @default []
13149                  */
13150                 "aoStateSave": [],
13151         
13152                 /**
13153                  * Array of callback functions for state loading. Each array element is an
13154                  * object with the following parameters:
13155                  *   <ul>
13156                  *     <li>function:fn - function to call. Takes two parameters, oSettings
13157                  *       and the object stored. May return false to cancel state loading</li>
13158                  *     <li>string:sName - name of callback</li>
13159                  *   </ul>
13160                  *  @type array
13161                  *  @default []
13162                  */
13163                 "aoStateLoad": [],
13164         
13165                 /**
13166                  * State that was saved. Useful for back reference
13167                  *  @type object
13168                  *  @default null
13169                  */
13170                 "oSavedState": null,
13171         
13172                 /**
13173                  * State that was loaded. Useful for back reference
13174                  *  @type object
13175                  *  @default null
13176                  */
13177                 "oLoadedState": null,
13178         
13179                 /**
13180                  * Source url for AJAX data for the table.
13181                  * Note that this parameter will be set by the initialisation routine. To
13182                  * set a default use {@link DataTable.defaults}.
13183                  *  @type string
13184                  *  @default null
13185                  */
13186                 "sAjaxSource": null,
13187         
13188                 /**
13189                  * Property from a given object from which to read the table data from. This
13190                  * can be an empty string (when not server-side processing), in which case
13191                  * it is  assumed an an array is given directly.
13192                  * Note that this parameter will be set by the initialisation routine. To
13193                  * set a default use {@link DataTable.defaults}.
13194                  *  @type string
13195                  */
13196                 "sAjaxDataProp": null,
13197         
13198                 /**
13199                  * Note if draw should be blocked while getting data
13200                  *  @type boolean
13201                  *  @default true
13202                  */
13203                 "bAjaxDataGet": true,
13204         
13205                 /**
13206                  * The last jQuery XHR object that was used for server-side data gathering.
13207                  * This can be used for working with the XHR information in one of the
13208                  * callbacks
13209                  *  @type object
13210                  *  @default null
13211                  */
13212                 "jqXHR": null,
13213         
13214                 /**
13215                  * JSON returned from the server in the last Ajax request
13216                  *  @type object
13217                  *  @default undefined
13218                  */
13219                 "json": undefined,
13220         
13221                 /**
13222                  * Data submitted as part of the last Ajax request
13223                  *  @type object
13224                  *  @default undefined
13225                  */
13226                 "oAjaxData": undefined,
13227         
13228                 /**
13229                  * Function to get the server-side data.
13230                  * Note that this parameter will be set by the initialisation routine. To
13231                  * set a default use {@link DataTable.defaults}.
13232                  *  @type function
13233                  */
13234                 "fnServerData": null,
13235         
13236                 /**
13237                  * Functions which are called prior to sending an Ajax request so extra
13238                  * parameters can easily be sent to the server
13239                  *  @type array
13240                  *  @default []
13241                  */
13242                 "aoServerParams": [],
13243         
13244                 /**
13245                  * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13246                  * required).
13247                  * Note that this parameter will be set by the initialisation routine. To
13248                  * set a default use {@link DataTable.defaults}.
13249                  *  @type string
13250                  */
13251                 "sServerMethod": null,
13252         
13253                 /**
13254                  * Format numbers for display.
13255                  * Note that this parameter will be set by the initialisation routine. To
13256                  * set a default use {@link DataTable.defaults}.
13257                  *  @type function
13258                  */
13259                 "fnFormatNumber": null,
13260         
13261                 /**
13262                  * List of options that can be used for the user selectable length menu.
13263                  * Note that this parameter will be set by the initialisation routine. To
13264                  * set a default use {@link DataTable.defaults}.
13265                  *  @type array
13266                  *  @default []
13267                  */
13268                 "aLengthMenu": null,
13269         
13270                 /**
13271                  * Counter for the draws that the table does. Also used as a tracker for
13272                  * server-side processing
13273                  *  @type int
13274                  *  @default 0
13275                  */
13276                 "iDraw": 0,
13277         
13278                 /**
13279                  * Indicate if a redraw is being done - useful for Ajax
13280                  *  @type boolean
13281                  *  @default false
13282                  */
13283                 "bDrawing": false,
13284         
13285                 /**
13286                  * Draw index (iDraw) of the last error when parsing the returned data
13287                  *  @type int
13288                  *  @default -1
13289                  */
13290                 "iDrawError": -1,
13291         
13292                 /**
13293                  * Paging display length
13294                  *  @type int
13295                  *  @default 10
13296                  */
13297                 "_iDisplayLength": 10,
13298         
13299                 /**
13300                  * Paging start point - aiDisplay index
13301                  *  @type int
13302                  *  @default 0
13303                  */
13304                 "_iDisplayStart": 0,
13305         
13306                 /**
13307                  * Server-side processing - number of records in the result set
13308                  * (i.e. before filtering), Use fnRecordsTotal rather than
13309                  * this property to get the value of the number of records, regardless of
13310                  * the server-side processing setting.
13311                  *  @type int
13312                  *  @default 0
13313                  *  @private
13314                  */
13315                 "_iRecordsTotal": 0,
13316         
13317                 /**
13318                  * Server-side processing - number of records in the current display set
13319                  * (i.e. after filtering). Use fnRecordsDisplay rather than
13320                  * this property to get the value of the number of records, regardless of
13321                  * the server-side processing setting.
13322                  *  @type boolean
13323                  *  @default 0
13324                  *  @private
13325                  */
13326                 "_iRecordsDisplay": 0,
13327         
13328                 /**
13329                  * Flag to indicate if jQuery UI marking and classes should be used.
13330                  * Note that this parameter will be set by the initialisation routine. To
13331                  * set a default use {@link DataTable.defaults}.
13332                  *  @type boolean
13333                  */
13334                 "bJUI": null,
13335         
13336                 /**
13337                  * The classes to use for the table
13338                  *  @type object
13339                  *  @default {}
13340                  */
13341                 "oClasses": {},
13342         
13343                 /**
13344                  * Flag attached to the settings object so you can check in the draw
13345                  * callback if filtering has been done in the draw. Deprecated in favour of
13346                  * events.
13347                  *  @type boolean
13348                  *  @default false
13349                  *  @deprecated
13350                  */
13351                 "bFiltered": false,
13352         
13353                 /**
13354                  * Flag attached to the settings object so you can check in the draw
13355                  * callback if sorting has been done in the draw. Deprecated in favour of
13356                  * events.
13357                  *  @type boolean
13358                  *  @default false
13359                  *  @deprecated
13360                  */
13361                 "bSorted": false,
13362         
13363                 /**
13364                  * Indicate that if multiple rows are in the header and there is more than
13365                  * one unique cell per column, if the top one (true) or bottom one (false)
13366                  * should be used for sorting / title by DataTables.
13367                  * Note that this parameter will be set by the initialisation routine. To
13368                  * set a default use {@link DataTable.defaults}.
13369                  *  @type boolean
13370                  */
13371                 "bSortCellsTop": null,
13372         
13373                 /**
13374                  * Initialisation object that is used for the table
13375                  *  @type object
13376                  *  @default null
13377                  */
13378                 "oInit": null,
13379         
13380                 /**
13381                  * Destroy callback functions - for plug-ins to attach themselves to the
13382                  * destroy so they can clean up markup and events.
13383                  *  @type array
13384                  *  @default []
13385                  */
13386                 "aoDestroyCallback": [],
13387         
13388         
13389                 /**
13390                  * Get the number of records in the current record set, before filtering
13391                  *  @type function
13392                  */
13393                 "fnRecordsTotal": function ()
13394                 {
13395                         return _fnDataSource( this ) == 'ssp' ?
13396                                 this._iRecordsTotal * 1 :
13397                                 this.aiDisplayMaster.length;
13398                 },
13399         
13400                 /**
13401                  * Get the number of records in the current record set, after filtering
13402                  *  @type function
13403                  */
13404                 "fnRecordsDisplay": function ()
13405                 {
13406                         return _fnDataSource( this ) == 'ssp' ?
13407                                 this._iRecordsDisplay * 1 :
13408                                 this.aiDisplay.length;
13409                 },
13410         
13411                 /**
13412                  * Get the display end point - aiDisplay index
13413                  *  @type function
13414                  */
13415                 "fnDisplayEnd": function ()
13416                 {
13417                         var
13418                                 len      = this._iDisplayLength,
13419                                 start    = this._iDisplayStart,
13420                                 calc     = start + len,
13421                                 records  = this.aiDisplay.length,
13422                                 features = this.oFeatures,
13423                                 paginate = features.bPaginate;
13424         
13425                         if ( features.bServerSide ) {
13426                                 return paginate === false || len === -1 ?
13427                                         start + records :
13428                                         Math.min( start+len, this._iRecordsDisplay );
13429                         }
13430                         else {
13431                                 return ! paginate || calc>records || len===-1 ?
13432                                         records :
13433                                         calc;
13434                         }
13435                 },
13436         
13437                 /**
13438                  * The DataTables object for this table
13439                  *  @type object
13440                  *  @default null
13441                  */
13442                 "oInstance": null,
13443         
13444                 /**
13445                  * Unique identifier for each instance of the DataTables object. If there
13446                  * is an ID on the table node, then it takes that value, otherwise an
13447                  * incrementing internal counter is used.
13448                  *  @type string
13449                  *  @default null
13450                  */
13451                 "sInstance": null,
13452         
13453                 /**
13454                  * tabindex attribute value that is added to DataTables control elements, allowing
13455                  * keyboard navigation of the table and its controls.
13456                  */
13457                 "iTabIndex": 0,
13458         
13459                 /**
13460                  * DIV container for the footer scrolling table if scrolling
13461                  */
13462                 "nScrollHead": null,
13463         
13464                 /**
13465                  * DIV container for the footer scrolling table if scrolling
13466                  */
13467                 "nScrollFoot": null,
13468         
13469                 /**
13470                  * Last applied sort
13471                  *  @type array
13472                  *  @default []
13473                  */
13474                 "aLastSort": [],
13475         
13476                 /**
13477                  * Stored plug-in instances
13478                  *  @type object
13479                  *  @default {}
13480                  */
13481                 "oPlugins": {}
13482         };
13483
13484         /**
13485          * Extension object for DataTables that is used to provide all extension
13486          * options.
13487          *
13488          * Note that the `DataTable.ext` object is available through
13489          * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13490          * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13491          *  @namespace
13492          *  @extends DataTable.models.ext
13493          */
13494         
13495         
13496         /**
13497          * DataTables extensions
13498          * 
13499          * This namespace acts as a collection area for plug-ins that can be used to
13500          * extend DataTables capabilities. Indeed many of the build in methods
13501          * use this method to provide their own capabilities (sorting methods for
13502          * example).
13503          *
13504          * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13505          * reasons
13506          *
13507          *  @namespace
13508          */
13509         DataTable.ext = _ext = {
13510                 /**
13511                  * Buttons. For use with the Buttons extension for DataTables. This is
13512                  * defined here so other extensions can define buttons regardless of load
13513                  * order. It is _not_ used by DataTables core.
13514                  *
13515                  *  @type object
13516                  *  @default {}
13517                  */
13518                 buttons: {},
13519         
13520         
13521                 /**
13522                  * Element class names
13523                  *
13524                  *  @type object
13525                  *  @default {}
13526                  */
13527                 classes: {},
13528         
13529         
13530                 /**
13531                  * Error reporting.
13532                  * 
13533                  * How should DataTables report an error. Can take the value 'alert',
13534                  * 'throw', 'none' or a function.
13535                  *
13536                  *  @type string|function
13537                  *  @default alert
13538                  */
13539                 errMode: "alert",
13540         
13541         
13542                 /**
13543                  * Feature plug-ins.
13544                  * 
13545                  * This is an array of objects which describe the feature plug-ins that are
13546                  * available to DataTables. These feature plug-ins are then available for
13547                  * use through the `dom` initialisation option.
13548                  * 
13549                  * Each feature plug-in is described by an object which must have the
13550                  * following properties:
13551                  * 
13552                  * * `fnInit` - function that is used to initialise the plug-in,
13553                  * * `cFeature` - a character so the feature can be enabled by the `dom`
13554                  *   instillation option. This is case sensitive.
13555                  *
13556                  * The `fnInit` function has the following input parameters:
13557                  *
13558                  * 1. `{object}` DataTables settings object: see
13559                  *    {@link DataTable.models.oSettings}
13560                  *
13561                  * And the following return is expected:
13562                  * 
13563                  * * {node|null} The element which contains your feature. Note that the
13564                  *   return may also be void if your plug-in does not require to inject any
13565                  *   DOM elements into DataTables control (`dom`) - for example this might
13566                  *   be useful when developing a plug-in which allows table control via
13567                  *   keyboard entry
13568                  *
13569                  *  @type array
13570                  *
13571                  *  @example
13572                  *    $.fn.dataTable.ext.features.push( {
13573                  *      "fnInit": function( oSettings ) {
13574                  *        return new TableTools( { "oDTSettings": oSettings } );
13575                  *      },
13576                  *      "cFeature": "T"
13577                  *    } );
13578                  */
13579                 feature: [],
13580         
13581         
13582                 /**
13583                  * Row searching.
13584                  * 
13585                  * This method of searching is complimentary to the default type based
13586                  * searching, and a lot more comprehensive as it allows you complete control
13587                  * over the searching logic. Each element in this array is a function
13588                  * (parameters described below) that is called for every row in the table,
13589                  * and your logic decides if it should be included in the searching data set
13590                  * or not.
13591                  *
13592                  * Searching functions have the following input parameters:
13593                  *
13594                  * 1. `{object}` DataTables settings object: see
13595                  *    {@link DataTable.models.oSettings}
13596                  * 2. `{array|object}` Data for the row to be processed (same as the
13597                  *    original format that was passed in as the data source, or an array
13598                  *    from a DOM data source
13599                  * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13600                  *    can be useful to retrieve the `TR` element if you need DOM interaction.
13601                  *
13602                  * And the following return is expected:
13603                  *
13604                  * * {boolean} Include the row in the searched result set (true) or not
13605                  *   (false)
13606                  *
13607                  * Note that as with the main search ability in DataTables, technically this
13608                  * is "filtering", since it is subtractive. However, for consistency in
13609                  * naming we call it searching here.
13610                  *
13611                  *  @type array
13612                  *  @default []
13613                  *
13614                  *  @example
13615                  *    // The following example shows custom search being applied to the
13616                  *    // fourth column (i.e. the data[3] index) based on two input values
13617                  *    // from the end-user, matching the data in a certain range.
13618                  *    $.fn.dataTable.ext.search.push(
13619                  *      function( settings, data, dataIndex ) {
13620                  *        var min = document.getElementById('min').value * 1;
13621                  *        var max = document.getElementById('max').value * 1;
13622                  *        var version = data[3] == "-" ? 0 : data[3]*1;
13623                  *
13624                  *        if ( min == "" && max == "" ) {
13625                  *          return true;
13626                  *        }
13627                  *        else if ( min == "" && version < max ) {
13628                  *          return true;
13629                  *        }
13630                  *        else if ( min < version && "" == max ) {
13631                  *          return true;
13632                  *        }
13633                  *        else if ( min < version && version < max ) {
13634                  *          return true;
13635                  *        }
13636                  *        return false;
13637                  *      }
13638                  *    );
13639                  */
13640                 search: [],
13641         
13642         
13643                 /**
13644                  * Selector extensions
13645                  *
13646                  * The `selector` option can be used to extend the options available for the
13647                  * selector modifier options (`selector-modifier` object data type) that
13648                  * each of the three built in selector types offer (row, column and cell +
13649                  * their plural counterparts). For example the Select extension uses this
13650                  * mechanism to provide an option to select only rows, columns and cells
13651                  * that have been marked as selected by the end user (`{selected: true}`),
13652                  * which can be used in conjunction with the existing built in selector
13653                  * options.
13654                  *
13655                  * Each property is an array to which functions can be pushed. The functions
13656                  * take three attributes:
13657                  *
13658                  * * Settings object for the host table
13659                  * * Options object (`selector-modifier` object type)
13660                  * * Array of selected item indexes
13661                  *
13662                  * The return is an array of the resulting item indexes after the custom
13663                  * selector has been applied.
13664                  *
13665                  *  @type object
13666                  */
13667                 selector: {
13668                         cell: [],
13669                         column: [],
13670                         row: []
13671                 },
13672         
13673         
13674                 /**
13675                  * Internal functions, exposed for used in plug-ins.
13676                  * 
13677                  * Please note that you should not need to use the internal methods for
13678                  * anything other than a plug-in (and even then, try to avoid if possible).
13679                  * The internal function may change between releases.
13680                  *
13681                  *  @type object
13682                  *  @default {}
13683                  */
13684                 internal: {},
13685         
13686         
13687                 /**
13688                  * Legacy configuration options. Enable and disable legacy options that
13689                  * are available in DataTables.
13690                  *
13691                  *  @type object
13692                  */
13693                 legacy: {
13694                         /**
13695                          * Enable / disable DataTables 1.9 compatible server-side processing
13696                          * requests
13697                          *
13698                          *  @type boolean
13699                          *  @default null
13700                          */
13701                         ajax: null
13702                 },
13703         
13704         
13705                 /**
13706                  * Pagination plug-in methods.
13707                  * 
13708                  * Each entry in this object is a function and defines which buttons should
13709                  * be shown by the pagination rendering method that is used for the table:
13710                  * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
13711                  * buttons are displayed in the document, while the functions here tell it
13712                  * what buttons to display. This is done by returning an array of button
13713                  * descriptions (what each button will do).
13714                  *
13715                  * Pagination types (the four built in options and any additional plug-in
13716                  * options defined here) can be used through the `paginationType`
13717                  * initialisation parameter.
13718                  *
13719                  * The functions defined take two parameters:
13720                  *
13721                  * 1. `{int} page` The current page index
13722                  * 2. `{int} pages` The number of pages in the table
13723                  *
13724                  * Each function is expected to return an array where each element of the
13725                  * array can be one of:
13726                  *
13727                  * * `first` - Jump to first page when activated
13728                  * * `last` - Jump to last page when activated
13729                  * * `previous` - Show previous page when activated
13730                  * * `next` - Show next page when activated
13731                  * * `{int}` - Show page of the index given
13732                  * * `{array}` - A nested array containing the above elements to add a
13733                  *   containing 'DIV' element (might be useful for styling).
13734                  *
13735                  * Note that DataTables v1.9- used this object slightly differently whereby
13736                  * an object with two functions would be defined for each plug-in. That
13737                  * ability is still supported by DataTables 1.10+ to provide backwards
13738                  * compatibility, but this option of use is now decremented and no longer
13739                  * documented in DataTables 1.10+.
13740                  *
13741                  *  @type object
13742                  *  @default {}
13743                  *
13744                  *  @example
13745                  *    // Show previous, next and current page buttons only
13746                  *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
13747                  *      return [ 'previous', page, 'next' ];
13748                  *    };
13749                  */
13750                 pager: {},
13751         
13752         
13753                 renderer: {
13754                         pageButton: {},
13755                         header: {}
13756                 },
13757         
13758         
13759                 /**
13760                  * Ordering plug-ins - custom data source
13761                  * 
13762                  * The extension options for ordering of data available here is complimentary
13763                  * to the default type based ordering that DataTables typically uses. It
13764                  * allows much greater control over the the data that is being used to
13765                  * order a column, but is necessarily therefore more complex.
13766                  * 
13767                  * This type of ordering is useful if you want to do ordering based on data
13768                  * live from the DOM (for example the contents of an 'input' element) rather
13769                  * than just the static string that DataTables knows of.
13770                  * 
13771                  * The way these plug-ins work is that you create an array of the values you
13772                  * wish to be ordering for the column in question and then return that
13773                  * array. The data in the array much be in the index order of the rows in
13774                  * the table (not the currently ordering order!). Which order data gathering
13775                  * function is run here depends on the `dt-init columns.orderDataType`
13776                  * parameter that is used for the column (if any).
13777                  *
13778                  * The functions defined take two parameters:
13779                  *
13780                  * 1. `{object}` DataTables settings object: see
13781                  *    {@link DataTable.models.oSettings}
13782                  * 2. `{int}` Target column index
13783                  *
13784                  * Each function is expected to return an array:
13785                  *
13786                  * * `{array}` Data for the column to be ordering upon
13787                  *
13788                  *  @type array
13789                  *
13790                  *  @example
13791                  *    // Ordering using `input` node values
13792                  *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
13793                  *    {
13794                  *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
13795                  *        return $('input', td).val();
13796                  *      } );
13797                  *    }
13798                  */
13799                 order: {},
13800         
13801         
13802                 /**
13803                  * Type based plug-ins.
13804                  *
13805                  * Each column in DataTables has a type assigned to it, either by automatic
13806                  * detection or by direct assignment using the `type` option for the column.
13807                  * The type of a column will effect how it is ordering and search (plug-ins
13808                  * can also make use of the column type if required).
13809                  *
13810                  * @namespace
13811                  */
13812                 type: {
13813                         /**
13814                          * Type detection functions.
13815                          *
13816                          * The functions defined in this object are used to automatically detect
13817                          * a column's type, making initialisation of DataTables super easy, even
13818                          * when complex data is in the table.
13819                          *
13820                          * The functions defined take two parameters:
13821                          *
13822                      *  1. `{*}` Data from the column cell to be analysed
13823                      *  2. `{settings}` DataTables settings object. This can be used to
13824                      *     perform context specific type detection - for example detection
13825                      *     based on language settings such as using a comma for a decimal
13826                      *     place. Generally speaking the options from the settings will not
13827                      *     be required
13828                          *
13829                          * Each function is expected to return:
13830                          *
13831                          * * `{string|null}` Data type detected, or null if unknown (and thus
13832                          *   pass it on to the other type detection functions.
13833                          *
13834                          *  @type array
13835                          *
13836                          *  @example
13837                          *    // Currency type detection plug-in:
13838                          *    $.fn.dataTable.ext.type.detect.push(
13839                          *      function ( data, settings ) {
13840                          *        // Check the numeric part
13841                          *        if ( ! $.isNumeric( data.substring(1) ) ) {
13842                          *          return null;
13843                          *        }
13844                          *
13845                          *        // Check prefixed by currency
13846                          *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
13847                          *          return 'currency';
13848                          *        }
13849                          *        return null;
13850                          *      }
13851                          *    );
13852                          */
13853                         detect: [],
13854         
13855         
13856                         /**
13857                          * Type based search formatting.
13858                          *
13859                          * The type based searching functions can be used to pre-format the
13860                          * data to be search on. For example, it can be used to strip HTML
13861                          * tags or to de-format telephone numbers for numeric only searching.
13862                          *
13863                          * Note that is a search is not defined for a column of a given type,
13864                          * no search formatting will be performed.
13865                          * 
13866                          * Pre-processing of searching data plug-ins - When you assign the sType
13867                          * for a column (or have it automatically detected for you by DataTables
13868                          * or a type detection plug-in), you will typically be using this for
13869                          * custom sorting, but it can also be used to provide custom searching
13870                          * by allowing you to pre-processing the data and returning the data in
13871                          * the format that should be searched upon. This is done by adding
13872                          * functions this object with a parameter name which matches the sType
13873                          * for that target column. This is the corollary of <i>afnSortData</i>
13874                          * for searching data.
13875                          *
13876                          * The functions defined take a single parameter:
13877                          *
13878                      *  1. `{*}` Data from the column cell to be prepared for searching
13879                          *
13880                          * Each function is expected to return:
13881                          *
13882                          * * `{string|null}` Formatted string that will be used for the searching.
13883                          *
13884                          *  @type object
13885                          *  @default {}
13886                          *
13887                          *  @example
13888                          *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
13889                          *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
13890                          *    }
13891                          */
13892                         search: {},
13893         
13894         
13895                         /**
13896                          * Type based ordering.
13897                          *
13898                          * The column type tells DataTables what ordering to apply to the table
13899                          * when a column is sorted upon. The order for each type that is defined,
13900                          * is defined by the functions available in this object.
13901                          *
13902                          * Each ordering option can be described by three properties added to
13903                          * this object:
13904                          *
13905                          * * `{type}-pre` - Pre-formatting function
13906                          * * `{type}-asc` - Ascending order function
13907                          * * `{type}-desc` - Descending order function
13908                          *
13909                          * All three can be used together, only `{type}-pre` or only
13910                          * `{type}-asc` and `{type}-desc` together. It is generally recommended
13911                          * that only `{type}-pre` is used, as this provides the optimal
13912                          * implementation in terms of speed, although the others are provided
13913                          * for compatibility with existing Javascript sort functions.
13914                          *
13915                          * `{type}-pre`: Functions defined take a single parameter:
13916                          *
13917                      *  1. `{*}` Data from the column cell to be prepared for ordering
13918                          *
13919                          * And return:
13920                          *
13921                          * * `{*}` Data to be sorted upon
13922                          *
13923                          * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
13924                          * functions, taking two parameters:
13925                          *
13926                      *  1. `{*}` Data to compare to the second parameter
13927                      *  2. `{*}` Data to compare to the first parameter
13928                          *
13929                          * And returning:
13930                          *
13931                          * * `{*}` Ordering match: <0 if first parameter should be sorted lower
13932                          *   than the second parameter, ===0 if the two parameters are equal and
13933                          *   >0 if the first parameter should be sorted height than the second
13934                          *   parameter.
13935                          * 
13936                          *  @type object
13937                          *  @default {}
13938                          *
13939                          *  @example
13940                          *    // Numeric ordering of formatted numbers with a pre-formatter
13941                          *    $.extend( $.fn.dataTable.ext.type.order, {
13942                          *      "string-pre": function(x) {
13943                          *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
13944                          *        return parseFloat( a );
13945                          *      }
13946                          *    } );
13947                          *
13948                          *  @example
13949                          *    // Case-sensitive string ordering, with no pre-formatting method
13950                          *    $.extend( $.fn.dataTable.ext.order, {
13951                          *      "string-case-asc": function(x,y) {
13952                          *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
13953                          *      },
13954                          *      "string-case-desc": function(x,y) {
13955                          *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
13956                          *      }
13957                          *    } );
13958                          */
13959                         order: {}
13960                 },
13961         
13962                 /**
13963                  * Unique DataTables instance counter
13964                  *
13965                  * @type int
13966                  * @private
13967                  */
13968                 _unique: 0,
13969         
13970         
13971                 //
13972                 // Depreciated
13973                 // The following properties are retained for backwards compatiblity only.
13974                 // The should not be used in new projects and will be removed in a future
13975                 // version
13976                 //
13977         
13978                 /**
13979                  * Version check function.
13980                  *  @type function
13981                  *  @depreciated Since 1.10
13982                  */
13983                 fnVersionCheck: DataTable.fnVersionCheck,
13984         
13985         
13986                 /**
13987                  * Index for what 'this' index API functions should use
13988                  *  @type int
13989                  *  @deprecated Since v1.10
13990                  */
13991                 iApiIndex: 0,
13992         
13993         
13994                 /**
13995                  * jQuery UI class container
13996                  *  @type object
13997                  *  @deprecated Since v1.10
13998                  */
13999                 oJUIClasses: {},
14000         
14001         
14002                 /**
14003                  * Software version
14004                  *  @type string
14005                  *  @deprecated Since v1.10
14006                  */
14007                 sVersion: DataTable.version
14008         };
14009         
14010         
14011         //
14012         // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14013         //
14014         $.extend( _ext, {
14015                 afnFiltering: _ext.search,
14016                 aTypes:       _ext.type.detect,
14017                 ofnSearch:    _ext.type.search,
14018                 oSort:        _ext.type.order,
14019                 afnSortData:  _ext.order,
14020                 aoFeatures:   _ext.feature,
14021                 oApi:         _ext.internal,
14022                 oStdClasses:  _ext.classes,
14023                 oPagination:  _ext.pager
14024         } );
14025         
14026         
14027         $.extend( DataTable.ext.classes, {
14028                 "sTable": "dataTable",
14029                 "sNoFooter": "no-footer",
14030         
14031                 /* Paging buttons */
14032                 "sPageButton": "paginate_button",
14033                 "sPageButtonActive": "current",
14034                 "sPageButtonDisabled": "disabled",
14035         
14036                 /* Striping classes */
14037                 "sStripeOdd": "odd",
14038                 "sStripeEven": "even",
14039         
14040                 /* Empty row */
14041                 "sRowEmpty": "dataTables_empty",
14042         
14043                 /* Features */
14044                 "sWrapper": "dataTables_wrapper",
14045                 "sFilter": "dataTables_filter",
14046                 "sInfo": "dataTables_info",
14047                 "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14048                 "sLength": "dataTables_length",
14049                 "sProcessing": "dataTables_processing",
14050         
14051                 /* Sorting */
14052                 "sSortAsc": "sorting_asc",
14053                 "sSortDesc": "sorting_desc",
14054                 "sSortable": "sorting", /* Sortable in both directions */
14055                 "sSortableAsc": "sorting_asc_disabled",
14056                 "sSortableDesc": "sorting_desc_disabled",
14057                 "sSortableNone": "sorting_disabled",
14058                 "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14059         
14060                 /* Filtering */
14061                 "sFilterInput": "",
14062         
14063                 /* Page length */
14064                 "sLengthSelect": "",
14065         
14066                 /* Scrolling */
14067                 "sScrollWrapper": "dataTables_scroll",
14068                 "sScrollHead": "dataTables_scrollHead",
14069                 "sScrollHeadInner": "dataTables_scrollHeadInner",
14070                 "sScrollBody": "dataTables_scrollBody",
14071                 "sScrollFoot": "dataTables_scrollFoot",
14072                 "sScrollFootInner": "dataTables_scrollFootInner",
14073         
14074                 /* Misc */
14075                 "sHeaderTH": "",
14076                 "sFooterTH": "",
14077         
14078                 // Deprecated
14079                 "sSortJUIAsc": "",
14080                 "sSortJUIDesc": "",
14081                 "sSortJUI": "",
14082                 "sSortJUIAscAllowed": "",
14083                 "sSortJUIDescAllowed": "",
14084                 "sSortJUIWrapper": "",
14085                 "sSortIcon": "",
14086                 "sJUIHeader": "",
14087                 "sJUIFooter": ""
14088         } );
14089         
14090         
14091         (function() {
14092         
14093         // Reused strings for better compression. Closure compiler appears to have a
14094         // weird edge case where it is trying to expand strings rather than use the
14095         // variable version. This results in about 200 bytes being added, for very
14096         // little preference benefit since it this run on script load only.
14097         var _empty = '';
14098         _empty = '';
14099         
14100         var _stateDefault = _empty + 'ui-state-default';
14101         var _sortIcon     = _empty + 'css_right ui-icon ui-icon-';
14102         var _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix';
14103         
14104         $.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, {
14105                 /* Full numbers paging buttons */
14106                 "sPageButton":         "fg-button ui-button "+_stateDefault,
14107                 "sPageButtonActive":   "ui-state-disabled",
14108                 "sPageButtonDisabled": "ui-state-disabled",
14109         
14110                 /* Features */
14111                 "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
14112                         "ui-buttonset-multi paging_", /* Note that the type is postfixed */
14113         
14114                 /* Sorting */
14115                 "sSortAsc":            _stateDefault+" sorting_asc",
14116                 "sSortDesc":           _stateDefault+" sorting_desc",
14117                 "sSortable":           _stateDefault+" sorting",
14118                 "sSortableAsc":        _stateDefault+" sorting_asc_disabled",
14119                 "sSortableDesc":       _stateDefault+" sorting_desc_disabled",
14120                 "sSortableNone":       _stateDefault+" sorting_disabled",
14121                 "sSortJUIAsc":         _sortIcon+"triangle-1-n",
14122                 "sSortJUIDesc":        _sortIcon+"triangle-1-s",
14123                 "sSortJUI":            _sortIcon+"carat-2-n-s",
14124                 "sSortJUIAscAllowed":  _sortIcon+"carat-1-n",
14125                 "sSortJUIDescAllowed": _sortIcon+"carat-1-s",
14126                 "sSortJUIWrapper":     "DataTables_sort_wrapper",
14127                 "sSortIcon":           "DataTables_sort_icon",
14128         
14129                 /* Scrolling */
14130                 "sScrollHead": "dataTables_scrollHead "+_stateDefault,
14131                 "sScrollFoot": "dataTables_scrollFoot "+_stateDefault,
14132         
14133                 /* Misc */
14134                 "sHeaderTH":  _stateDefault,
14135                 "sFooterTH":  _stateDefault,
14136                 "sJUIHeader": _headerFooter+" ui-corner-tl ui-corner-tr",
14137                 "sJUIFooter": _headerFooter+" ui-corner-bl ui-corner-br"
14138         } );
14139         
14140         }());
14141         
14142         
14143         
14144         var extPagination = DataTable.ext.pager;
14145         
14146         function _numbers ( page, pages ) {
14147                 var
14148                         numbers = [],
14149                         buttons = extPagination.numbers_length,
14150                         half = Math.floor( buttons / 2 ),
14151                         i = 1;
14152         
14153                 if ( pages <= buttons ) {
14154                         numbers = _range( 0, pages );
14155                 }
14156                 else if ( page <= half ) {
14157                         numbers = _range( 0, buttons-2 );
14158                         numbers.push( 'ellipsis' );
14159                         numbers.push( pages-1 );
14160                 }
14161                 else if ( page >= pages - 1 - half ) {
14162                         numbers = _range( pages-(buttons-2), pages );
14163                         numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14164                         numbers.splice( 0, 0, 0 );
14165                 }
14166                 else {
14167                         numbers = _range( page-half+2, page+half-1 );
14168                         numbers.push( 'ellipsis' );
14169                         numbers.push( pages-1 );
14170                         numbers.splice( 0, 0, 'ellipsis' );
14171                         numbers.splice( 0, 0, 0 );
14172                 }
14173         
14174                 numbers.DT_el = 'span';
14175                 return numbers;
14176         }
14177         
14178         
14179         $.extend( extPagination, {
14180                 simple: function ( page, pages ) {
14181                         return [ 'previous', 'next' ];
14182                 },
14183         
14184                 full: function ( page, pages ) {
14185                         return [  'first', 'previous', 'next', 'last' ];
14186                 },
14187         
14188                 simple_numbers: function ( page, pages ) {
14189                         return [ 'previous', _numbers(page, pages), 'next' ];
14190                 },
14191         
14192                 full_numbers: function ( page, pages ) {
14193                         return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14194                 },
14195         
14196                 // For testing and plug-ins to use
14197                 _numbers: _numbers,
14198         
14199                 // Number of number buttons (including ellipsis) to show. _Must be odd!_
14200                 numbers_length: 7
14201         } );
14202         
14203         
14204         $.extend( true, DataTable.ext.renderer, {
14205                 pageButton: {
14206                         _: function ( settings, host, idx, buttons, page, pages ) {
14207                                 var classes = settings.oClasses;
14208                                 var lang = settings.oLanguage.oPaginate;
14209                                 var btnDisplay, btnClass, counter=0;
14210         
14211                                 var attach = function( container, buttons ) {
14212                                         var i, ien, node, button;
14213                                         var clickHandler = function ( e ) {
14214                                                 _fnPageChange( settings, e.data.action, true );
14215                                         };
14216         
14217                                         for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14218                                                 button = buttons[i];
14219         
14220                                                 if ( $.isArray( button ) ) {
14221                                                         var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14222                                                                 .appendTo( container );
14223                                                         attach( inner, button );
14224                                                 }
14225                                                 else {
14226                                                         btnDisplay = '';
14227                                                         btnClass = '';
14228         
14229                                                         switch ( button ) {
14230                                                                 case 'ellipsis':
14231                                                                         container.append('<span class="ellipsis">&#x2026;</span>');
14232                                                                         break;
14233         
14234                                                                 case 'first':
14235                                                                         btnDisplay = lang.sFirst;
14236                                                                         btnClass = button + (page > 0 ?
14237                                                                                 '' : ' '+classes.sPageButtonDisabled);
14238                                                                         break;
14239         
14240                                                                 case 'previous':
14241                                                                         btnDisplay = lang.sPrevious;
14242                                                                         btnClass = button + (page > 0 ?
14243                                                                                 '' : ' '+classes.sPageButtonDisabled);
14244                                                                         break;
14245         
14246                                                                 case 'next':
14247                                                                         btnDisplay = lang.sNext;
14248                                                                         btnClass = button + (page < pages-1 ?
14249                                                                                 '' : ' '+classes.sPageButtonDisabled);
14250                                                                         break;
14251         
14252                                                                 case 'last':
14253                                                                         btnDisplay = lang.sLast;
14254                                                                         btnClass = button + (page < pages-1 ?
14255                                                                                 '' : ' '+classes.sPageButtonDisabled);
14256                                                                         break;
14257         
14258                                                                 default:
14259                                                                         btnDisplay = button + 1;
14260                                                                         btnClass = page === button ?
14261                                                                                 classes.sPageButtonActive : '';
14262                                                                         break;
14263                                                         }
14264         
14265                                                         if ( btnDisplay ) {
14266                                                                 node = $('<a>', {
14267                                                                                 'class': classes.sPageButton+' '+btnClass,
14268                                                                                 'aria-controls': settings.sTableId,
14269                                                                                 'data-dt-idx': counter,
14270                                                                                 'tabindex': settings.iTabIndex,
14271                                                                                 'id': idx === 0 && typeof button === 'string' ?
14272                                                                                         settings.sTableId +'_'+ button :
14273                                                                                         null
14274                                                                         } )
14275                                                                         .html( btnDisplay )
14276                                                                         .appendTo( container );
14277         
14278                                                                 _fnBindAction(
14279                                                                         node, {action: button}, clickHandler
14280                                                                 );
14281         
14282                                                                 counter++;
14283                                                         }
14284                                                 }
14285                                         }
14286                                 };
14287         
14288                                 // IE9 throws an 'unknown error' if document.activeElement is used
14289                                 // inside an iframe or frame. Try / catch the error. Not good for
14290                                 // accessibility, but neither are frames.
14291                                 var activeEl;
14292         
14293                                 try {
14294                                         // Because this approach is destroying and recreating the paging
14295                                         // elements, focus is lost on the select button which is bad for
14296                                         // accessibility. So we want to restore focus once the draw has
14297                                         // completed
14298                                         activeEl = $(document.activeElement).data('dt-idx');
14299                                 }
14300                                 catch (e) {}
14301         
14302                                 attach( $(host).empty(), buttons );
14303         
14304                                 if ( activeEl ) {
14305                                         $(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14306                                 }
14307                         }
14308                 }
14309         } );
14310         
14311         
14312         
14313         // Built in type detection. See model.ext.aTypes for information about
14314         // what is required from this methods.
14315         $.extend( DataTable.ext.type.detect, [
14316                 // Plain numbers - first since V8 detects some plain numbers as dates
14317                 // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14318                 function ( d, settings )
14319                 {
14320                         var decimal = settings.oLanguage.sDecimal;
14321                         return _isNumber( d, decimal ) ? 'num'+decimal : null;
14322                 },
14323         
14324                 // Dates (only those recognised by the browser's Date.parse)
14325                 function ( d, settings )
14326                 {
14327                         // V8 will remove any unknown characters at the start and end of the
14328                         // expression, leading to false matches such as `$245.12` or `10%` being
14329                         // a valid date. See forum thread 18941 for detail.
14330                         if ( d && !(d instanceof Date) && ( ! _re_date_start.test(d) || ! _re_date_end.test(d) ) ) {
14331                                 return null;
14332                         }
14333                         var parsed = Date.parse(d);
14334                         return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14335                 },
14336         
14337                 // Formatted numbers
14338                 function ( d, settings )
14339                 {
14340                         var decimal = settings.oLanguage.sDecimal;
14341                         return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14342                 },
14343         
14344                 // HTML numeric
14345                 function ( d, settings )
14346                 {
14347                         var decimal = settings.oLanguage.sDecimal;
14348                         return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14349                 },
14350         
14351                 // HTML numeric, formatted
14352                 function ( d, settings )
14353                 {
14354                         var decimal = settings.oLanguage.sDecimal;
14355                         return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14356                 },
14357         
14358                 // HTML (this is strict checking - there must be html)
14359                 function ( d, settings )
14360                 {
14361                         return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14362                                 'html' : null;
14363                 }
14364         ] );
14365         
14366         
14367         
14368         // Filter formatting functions. See model.ext.ofnSearch for information about
14369         // what is required from these methods.
14370         // 
14371         // Note that additional search methods are added for the html numbers and
14372         // html formatted numbers by `_addNumericSort()` when we know what the decimal
14373         // place is
14374         
14375         
14376         $.extend( DataTable.ext.type.search, {
14377                 html: function ( data ) {
14378                         return _empty(data) ?
14379                                 data :
14380                                 typeof data === 'string' ?
14381                                         data
14382                                                 .replace( _re_new_lines, " " )
14383                                                 .replace( _re_html, "" ) :
14384                                         '';
14385                 },
14386         
14387                 string: function ( data ) {
14388                         return _empty(data) ?
14389                                 data :
14390                                 typeof data === 'string' ?
14391                                         data.replace( _re_new_lines, " " ) :
14392                                         data;
14393                 }
14394         } );
14395         
14396         
14397         
14398         var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14399                 if ( d !== 0 && (!d || d === '-') ) {
14400                         return -Infinity;
14401                 }
14402         
14403                 // If a decimal place other than `.` is used, it needs to be given to the
14404                 // function so we can detect it and replace with a `.` which is the only
14405                 // decimal place Javascript recognises - it is not locale aware.
14406                 if ( decimalPlace ) {
14407                         d = _numToDecimal( d, decimalPlace );
14408                 }
14409         
14410                 if ( d.replace ) {
14411                         if ( re1 ) {
14412                                 d = d.replace( re1, '' );
14413                         }
14414         
14415                         if ( re2 ) {
14416                                 d = d.replace( re2, '' );
14417                         }
14418                 }
14419         
14420                 return d * 1;
14421         };
14422         
14423         
14424         // Add the numeric 'deformatting' functions for sorting and search. This is done
14425         // in a function to provide an easy ability for the language options to add
14426         // additional methods if a non-period decimal place is used.
14427         function _addNumericSort ( decimalPlace ) {
14428                 $.each(
14429                         {
14430                                 // Plain numbers
14431                                 "num": function ( d ) {
14432                                         return __numericReplace( d, decimalPlace );
14433                                 },
14434         
14435                                 // Formatted numbers
14436                                 "num-fmt": function ( d ) {
14437                                         return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14438                                 },
14439         
14440                                 // HTML numeric
14441                                 "html-num": function ( d ) {
14442                                         return __numericReplace( d, decimalPlace, _re_html );
14443                                 },
14444         
14445                                 // HTML numeric, formatted
14446                                 "html-num-fmt": function ( d ) {
14447                                         return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14448                                 }
14449                         },
14450                         function ( key, fn ) {
14451                                 // Add the ordering method
14452                                 _ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14453         
14454                                 // For HTML types add a search formatter that will strip the HTML
14455                                 if ( key.match(/^html\-/) ) {
14456                                         _ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
14457                                 }
14458                         }
14459                 );
14460         }
14461         
14462         
14463         // Default sort methods
14464         $.extend( _ext.type.order, {
14465                 // Dates
14466                 "date-pre": function ( d ) {
14467                         return Date.parse( d ) || 0;
14468                 },
14469         
14470                 // html
14471                 "html-pre": function ( a ) {
14472                         return _empty(a) ?
14473                                 '' :
14474                                 a.replace ?
14475                                         a.replace( /<.*?>/g, "" ).toLowerCase() :
14476                                         a+'';
14477                 },
14478         
14479                 // string
14480                 "string-pre": function ( a ) {
14481                         // This is a little complex, but faster than always calling toString,
14482                         // http://jsperf.com/tostring-v-check
14483                         return _empty(a) ?
14484                                 '' :
14485                                 typeof a === 'string' ?
14486                                         a.toLowerCase() :
14487                                         ! a.toString ?
14488                                                 '' :
14489                                                 a.toString();
14490                 },
14491         
14492                 // string-asc and -desc are retained only for compatibility with the old
14493                 // sort methods
14494                 "string-asc": function ( x, y ) {
14495                         return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14496                 },
14497         
14498                 "string-desc": function ( x, y ) {
14499                         return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14500                 }
14501         } );
14502         
14503         
14504         // Numeric sorting types - order doesn't matter here
14505         _addNumericSort( '' );
14506         
14507         
14508         $.extend( true, DataTable.ext.renderer, {
14509                 header: {
14510                         _: function ( settings, cell, column, classes ) {
14511                                 // No additional mark-up required
14512                                 // Attach a sort listener to update on sort - note that using the
14513                                 // `DT` namespace will allow the event to be removed automatically
14514                                 // on destroy, while the `dt` namespaced event is the one we are
14515                                 // listening for
14516                                 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14517                                         if ( settings !== ctx ) { // need to check this this is the host
14518                                                 return;               // table, not a nested one
14519                                         }
14520         
14521                                         var colIdx = column.idx;
14522         
14523                                         cell
14524                                                 .removeClass(
14525                                                         column.sSortingClass +' '+
14526                                                         classes.sSortAsc +' '+
14527                                                         classes.sSortDesc
14528                                                 )
14529                                                 .addClass( columns[ colIdx ] == 'asc' ?
14530                                                         classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14531                                                                 classes.sSortDesc :
14532                                                                 column.sSortingClass
14533                                                 );
14534                                 } );
14535                         },
14536         
14537                         jqueryui: function ( settings, cell, column, classes ) {
14538                                 $('<div/>')
14539                                         .addClass( classes.sSortJUIWrapper )
14540                                         .append( cell.contents() )
14541                                         .append( $('<span/>')
14542                                                 .addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
14543                                         )
14544                                         .appendTo( cell );
14545         
14546                                 // Attach a sort listener to update on sort
14547                                 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14548                                         if ( settings !== ctx ) {
14549                                                 return;
14550                                         }
14551         
14552                                         var colIdx = column.idx;
14553         
14554                                         cell
14555                                                 .removeClass( classes.sSortAsc +" "+classes.sSortDesc )
14556                                                 .addClass( columns[ colIdx ] == 'asc' ?
14557                                                         classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14558                                                                 classes.sSortDesc :
14559                                                                 column.sSortingClass
14560                                                 );
14561         
14562                                         cell
14563                                                 .find( 'span.'+classes.sSortIcon )
14564                                                 .removeClass(
14565                                                         classes.sSortJUIAsc +" "+
14566                                                         classes.sSortJUIDesc +" "+
14567                                                         classes.sSortJUI +" "+
14568                                                         classes.sSortJUIAscAllowed +" "+
14569                                                         classes.sSortJUIDescAllowed
14570                                                 )
14571                                                 .addClass( columns[ colIdx ] == 'asc' ?
14572                                                         classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14573                                                                 classes.sSortJUIDesc :
14574                                                                 column.sSortingClassJUI
14575                                                 );
14576                                 } );
14577                         }
14578                 }
14579         } );
14580         
14581         /*
14582          * Public helper functions. These aren't used internally by DataTables, or
14583          * called by any of the options passed into DataTables, but they can be used
14584          * externally by developers working with DataTables. They are helper functions
14585          * to make working with DataTables a little bit easier.
14586          */
14587         
14588         /**
14589          * Helpers for `columns.render`.
14590          *
14591          * The options defined here can be used with the `columns.render` initialisation
14592          * option to provide a display renderer. The following functions are defined:
14593          *
14594          * * `number` - Will format numeric data (defined by `columns.data`) for
14595          *   display, retaining the original unformatted data for sorting and filtering.
14596          *   It takes 4 parameters:
14597          *   * `string` - Thousands grouping separator
14598          *   * `string` - Decimal point indicator
14599          *   * `integer` - Number of decimal points to show
14600          *   * `string` (optional) - Prefix.
14601          *
14602          * @example
14603          *   // Column definition using the number renderer
14604          *   {
14605          *     data: "salary",
14606          *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14607          *   }
14608          *
14609          * @namespace
14610          */
14611         DataTable.render = {
14612                 number: function ( thousands, decimal, precision, prefix ) {
14613                         return {
14614                                 display: function ( d ) {
14615                                         if ( typeof d !== 'number' && typeof d !== 'string' ) {
14616                                                 return d;
14617                                         }
14618         
14619                                         var negative = d < 0 ? '-' : '';
14620                                         d = Math.abs( parseFloat( d ) );
14621         
14622                                         var intPart = parseInt( d, 10 );
14623                                         var floatPart = precision ?
14624                                                 decimal+(d - intPart).toFixed( precision ).substring( 2 ):
14625                                                 '';
14626         
14627                                         return negative + (prefix||'') +
14628                                                 intPart.toString().replace(
14629                                                         /\B(?=(\d{3})+(?!\d))/g, thousands
14630                                                 ) +
14631                                                 floatPart;
14632                                 }
14633                         };
14634                 }
14635         };
14636         
14637         
14638         /*
14639          * This is really a good bit rubbish this method of exposing the internal methods
14640          * publicly... - To be fixed in 2.0 using methods on the prototype
14641          */
14642         
14643         
14644         /**
14645          * Create a wrapper function for exporting an internal functions to an external API.
14646          *  @param {string} fn API function name
14647          *  @returns {function} wrapped function
14648          *  @memberof DataTable#internal
14649          */
14650         function _fnExternApiFunc (fn)
14651         {
14652                 return function() {
14653                         var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
14654                                 Array.prototype.slice.call(arguments)
14655                         );
14656                         return DataTable.ext.internal[fn].apply( this, args );
14657                 };
14658         }
14659         
14660         
14661         /**
14662          * Reference to internal functions for use by plug-in developers. Note that
14663          * these methods are references to internal functions and are considered to be
14664          * private. If you use these methods, be aware that they are liable to change
14665          * between versions.
14666          *  @namespace
14667          */
14668         $.extend( DataTable.ext.internal, {
14669                 _fnExternApiFunc: _fnExternApiFunc,
14670                 _fnBuildAjax: _fnBuildAjax,
14671                 _fnAjaxUpdate: _fnAjaxUpdate,
14672                 _fnAjaxParameters: _fnAjaxParameters,
14673                 _fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
14674                 _fnAjaxDataSrc: _fnAjaxDataSrc,
14675                 _fnAddColumn: _fnAddColumn,
14676                 _fnColumnOptions: _fnColumnOptions,
14677                 _fnAdjustColumnSizing: _fnAdjustColumnSizing,
14678                 _fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
14679                 _fnColumnIndexToVisible: _fnColumnIndexToVisible,
14680                 _fnVisbleColumns: _fnVisbleColumns,
14681                 _fnGetColumns: _fnGetColumns,
14682                 _fnColumnTypes: _fnColumnTypes,
14683                 _fnApplyColumnDefs: _fnApplyColumnDefs,
14684                 _fnHungarianMap: _fnHungarianMap,
14685                 _fnCamelToHungarian: _fnCamelToHungarian,
14686                 _fnLanguageCompat: _fnLanguageCompat,
14687                 _fnBrowserDetect: _fnBrowserDetect,
14688                 _fnAddData: _fnAddData,
14689                 _fnAddTr: _fnAddTr,
14690                 _fnNodeToDataIndex: _fnNodeToDataIndex,
14691                 _fnNodeToColumnIndex: _fnNodeToColumnIndex,
14692                 _fnGetCellData: _fnGetCellData,
14693                 _fnSetCellData: _fnSetCellData,
14694                 _fnSplitObjNotation: _fnSplitObjNotation,
14695                 _fnGetObjectDataFn: _fnGetObjectDataFn,
14696                 _fnSetObjectDataFn: _fnSetObjectDataFn,
14697                 _fnGetDataMaster: _fnGetDataMaster,
14698                 _fnClearTable: _fnClearTable,
14699                 _fnDeleteIndex: _fnDeleteIndex,
14700                 _fnInvalidate: _fnInvalidate,
14701                 _fnGetRowElements: _fnGetRowElements,
14702                 _fnCreateTr: _fnCreateTr,
14703                 _fnBuildHead: _fnBuildHead,
14704                 _fnDrawHead: _fnDrawHead,
14705                 _fnDraw: _fnDraw,
14706                 _fnReDraw: _fnReDraw,
14707                 _fnAddOptionsHtml: _fnAddOptionsHtml,
14708                 _fnDetectHeader: _fnDetectHeader,
14709                 _fnGetUniqueThs: _fnGetUniqueThs,
14710                 _fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
14711                 _fnFilterComplete: _fnFilterComplete,
14712                 _fnFilterCustom: _fnFilterCustom,
14713                 _fnFilterColumn: _fnFilterColumn,
14714                 _fnFilter: _fnFilter,
14715                 _fnFilterCreateSearch: _fnFilterCreateSearch,
14716                 _fnEscapeRegex: _fnEscapeRegex,
14717                 _fnFilterData: _fnFilterData,
14718                 _fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
14719                 _fnUpdateInfo: _fnUpdateInfo,
14720                 _fnInfoMacros: _fnInfoMacros,
14721                 _fnInitialise: _fnInitialise,
14722                 _fnInitComplete: _fnInitComplete,
14723                 _fnLengthChange: _fnLengthChange,
14724                 _fnFeatureHtmlLength: _fnFeatureHtmlLength,
14725                 _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
14726                 _fnPageChange: _fnPageChange,
14727                 _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
14728                 _fnProcessingDisplay: _fnProcessingDisplay,
14729                 _fnFeatureHtmlTable: _fnFeatureHtmlTable,
14730                 _fnScrollDraw: _fnScrollDraw,
14731                 _fnApplyToChildren: _fnApplyToChildren,
14732                 _fnCalculateColumnWidths: _fnCalculateColumnWidths,
14733                 _fnThrottle: _fnThrottle,
14734                 _fnConvertToWidth: _fnConvertToWidth,
14735                 _fnScrollingWidthAdjust: _fnScrollingWidthAdjust,
14736                 _fnGetWidestNode: _fnGetWidestNode,
14737                 _fnGetMaxLenString: _fnGetMaxLenString,
14738                 _fnStringToCss: _fnStringToCss,
14739                 _fnScrollBarWidth: _fnScrollBarWidth,
14740                 _fnSortFlatten: _fnSortFlatten,
14741                 _fnSort: _fnSort,
14742                 _fnSortAria: _fnSortAria,
14743                 _fnSortListener: _fnSortListener,
14744                 _fnSortAttachListener: _fnSortAttachListener,
14745                 _fnSortingClasses: _fnSortingClasses,
14746                 _fnSortData: _fnSortData,
14747                 _fnSaveState: _fnSaveState,
14748                 _fnLoadState: _fnLoadState,
14749                 _fnSettingsFromNode: _fnSettingsFromNode,
14750                 _fnLog: _fnLog,
14751                 _fnMap: _fnMap,
14752                 _fnBindAction: _fnBindAction,
14753                 _fnCallbackReg: _fnCallbackReg,
14754                 _fnCallbackFire: _fnCallbackFire,
14755                 _fnLengthOverflow: _fnLengthOverflow,
14756                 _fnRenderer: _fnRenderer,
14757                 _fnDataSource: _fnDataSource,
14758                 _fnRowAttributes: _fnRowAttributes,
14759                 _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
14760                                                 // in 1.10, so this dead-end function is
14761                                                 // added to prevent errors
14762         } );
14763         
14764
14765         // jQuery access
14766         $.fn.dataTable = DataTable;
14767
14768         // Legacy aliases
14769         $.fn.dataTableSettings = DataTable.settings;
14770         $.fn.dataTableExt = DataTable.ext;
14771
14772         // With a capital `D` we return a DataTables API instance rather than a
14773         // jQuery object
14774         $.fn.DataTable = function ( opts ) {
14775                 return $(this).dataTable( opts ).api();
14776         };
14777
14778         // All properties that are available to $.fn.dataTable should also be
14779         // available on $.fn.DataTable
14780         $.each( DataTable, function ( prop, val ) {
14781                 $.fn.DataTable[ prop ] = val;
14782         } );
14783
14784
14785         // Information about events fired by DataTables - for documentation.
14786         /**
14787          * Draw event, fired whenever the table is redrawn on the page, at the same
14788          * point as fnDrawCallback. This may be useful for binding events or
14789          * performing calculations when the table is altered at all.
14790          *  @name DataTable#draw.dt
14791          *  @event
14792          *  @param {event} e jQuery event object
14793          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14794          */
14795
14796         /**
14797          * Search event, fired when the searching applied to the table (using the
14798          * built-in global search, or column filters) is altered.
14799          *  @name DataTable#search.dt
14800          *  @event
14801          *  @param {event} e jQuery event object
14802          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14803          */
14804
14805         /**
14806          * Page change event, fired when the paging of the table is altered.
14807          *  @name DataTable#page.dt
14808          *  @event
14809          *  @param {event} e jQuery event object
14810          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14811          */
14812
14813         /**
14814          * Order event, fired when the ordering applied to the table is altered.
14815          *  @name DataTable#order.dt
14816          *  @event
14817          *  @param {event} e jQuery event object
14818          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14819          */
14820
14821         /**
14822          * DataTables initialisation complete event, fired when the table is fully
14823          * drawn, including Ajax data loaded, if Ajax data is required.
14824          *  @name DataTable#init.dt
14825          *  @event
14826          *  @param {event} e jQuery event object
14827          *  @param {object} oSettings DataTables settings object
14828          *  @param {object} json The JSON object request from the server - only
14829          *    present if client-side Ajax sourced data is used</li></ol>
14830          */
14831
14832         /**
14833          * State save event, fired when the table has changed state a new state save
14834          * is required. This event allows modification of the state saving object
14835          * prior to actually doing the save, including addition or other state
14836          * properties (for plug-ins) or modification of a DataTables core property.
14837          *  @name DataTable#stateSaveParams.dt
14838          *  @event
14839          *  @param {event} e jQuery event object
14840          *  @param {object} oSettings DataTables settings object
14841          *  @param {object} json The state information to be saved
14842          */
14843
14844         /**
14845          * State load event, fired when the table is loading state from the stored
14846          * data, but prior to the settings object being modified by the saved state
14847          * - allowing modification of the saved state is required or loading of
14848          * state for a plug-in.
14849          *  @name DataTable#stateLoadParams.dt
14850          *  @event
14851          *  @param {event} e jQuery event object
14852          *  @param {object} oSettings DataTables settings object
14853          *  @param {object} json The saved state information
14854          */
14855
14856         /**
14857          * State loaded event, fired when state has been loaded from stored data and
14858          * the settings object has been modified by the loaded data.
14859          *  @name DataTable#stateLoaded.dt
14860          *  @event
14861          *  @param {event} e jQuery event object
14862          *  @param {object} oSettings DataTables settings object
14863          *  @param {object} json The saved state information
14864          */
14865
14866         /**
14867          * Processing event, fired when DataTables is doing some kind of processing
14868          * (be it, order, searcg or anything else). It can be used to indicate to
14869          * the end user that there is something happening, or that something has
14870          * finished.
14871          *  @name DataTable#processing.dt
14872          *  @event
14873          *  @param {event} e jQuery event object
14874          *  @param {object} oSettings DataTables settings object
14875          *  @param {boolean} bShow Flag for if DataTables is doing processing or not
14876          */
14877
14878         /**
14879          * Ajax (XHR) event, fired whenever an Ajax request is completed from a
14880          * request to made to the server for new data. This event is called before
14881          * DataTables processed the returned data, so it can also be used to pre-
14882          * process the data returned from the server, if needed.
14883          *
14884          * Note that this trigger is called in `fnServerData`, if you override
14885          * `fnServerData` and which to use this event, you need to trigger it in you
14886          * success function.
14887          *  @name DataTable#xhr.dt
14888          *  @event
14889          *  @param {event} e jQuery event object
14890          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14891          *  @param {object} json JSON returned from the server
14892          *
14893          *  @example
14894          *     // Use a custom property returned from the server in another DOM element
14895          *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
14896          *       $('#status').html( json.status );
14897          *     } );
14898          *
14899          *  @example
14900          *     // Pre-process the data returned from the server
14901          *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
14902          *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
14903          *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
14904          *       }
14905          *       // Note no return - manipulate the data directly in the JSON object.
14906          *     } );
14907          */
14908
14909         /**
14910          * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
14911          * or passing the bDestroy:true parameter in the initialisation object. This
14912          * can be used to remove bound events, added DOM nodes, etc.
14913          *  @name DataTable#destroy.dt
14914          *  @event
14915          *  @param {event} e jQuery event object
14916          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14917          */
14918
14919         /**
14920          * Page length change event, fired when number of records to show on each
14921          * page (the length) is changed.
14922          *  @name DataTable#length.dt
14923          *  @event
14924          *  @param {event} e jQuery event object
14925          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14926          *  @param {integer} len New length
14927          */
14928
14929         /**
14930          * Column sizing has changed.
14931          *  @name DataTable#column-sizing.dt
14932          *  @event
14933          *  @param {event} e jQuery event object
14934          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14935          */
14936
14937         /**
14938          * Column visibility has changed.
14939          *  @name DataTable#column-visibility.dt
14940          *  @event
14941          *  @param {event} e jQuery event object
14942          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14943          *  @param {int} column Column index
14944          *  @param {bool} vis `false` if column now hidden, or `true` if visible
14945          */
14946
14947         return $.fn.dataTable;
14948 }));
14949
14950 }(window, document));
14951