Merge pull request #5205 from solgenomics/topic/generic_trial_upload
[sgn.git] / js / source / legacy / jquery / dataTables.js
blob5b032aeec272270510b8608e62c1080280a8c560
1 /*! DataTables 1.10.12
2  * ©2008-2015 SpryMedia Ltd - datatables.net/license
3  */
5 /**
6  * @summary     DataTables
7  * @description Paginate, search and order HTML tables
8  * @version     1.10.12
9  * @file        jquery.dataTables.js
10  * @author      SpryMedia Ltd (www.sprymedia.co.uk)
11  * @contact     www.sprymedia.co.uk/contact
12  * @copyright   Copyright 2008-2015 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  */
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,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
27 (function( factory ) {
28         "use strict";
30         if ( typeof define === 'function' && define.amd ) {
31                 // AMD
32                 define( ['jquery'], function ( $ ) {
33                         return factory( $, window, document );
34                 } );
35         }
36         else if ( typeof exports === 'object' ) {
37                 // CommonJS
38                 module.exports = function (root, $) {
39                         if ( ! root ) {
40                                 // CommonJS environments without a window global must pass a
41                                 // root. This will give an error otherwise
42                                 root = window;
43                         }
45                         if ( ! $ ) {
46                                 $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
47                                         require('jquery') :
48                                         require('jquery')( root );
49                         }
51                         return factory( $, root, root.document );
52                 };
53         }
54         else {
55                 // Browser
56                 factory( jQuery, window, document );
57         }
59 (function( $, window, document, undefined ) {
60         "use strict";
62         /**
63          * DataTables is a plug-in for the jQuery Javascript library. It is a highly
64          * flexible tool, based upon the foundations of progressive enhancement,
65          * which will add advanced interaction controls to any HTML table. For a
66          * full list of features please refer to
67          * [DataTables.net](href="http://datatables.net).
68          *
69          * Note that the `DataTable` object is not a global variable but is aliased
70          * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
71          * be  accessed.
72          *
73          *  @class
74          *  @param {object} [init={}] Configuration object for DataTables. Options
75          *    are defined by {@link DataTable.defaults}
76          *  @requires jQuery 1.7+
77          *
78          *  @example
79          *    // Basic initialisation
80          *    $(document).ready( function {
81          *      $('#example').dataTable();
82          *    } );
83          *
84          *  @example
85          *    // Initialisation with configuration options - in this case, disable
86          *    // pagination and sorting.
87          *    $(document).ready( function {
88          *      $('#example').dataTable( {
89          *        "paginate": false,
90          *        "sort": false
91          *      } );
92          *    } );
93          */
94         var DataTable = function ( options )
95         {
96                 /**
97                  * Perform a jQuery selector action on the table's TR elements (from the tbody) and
98                  * return the resulting jQuery object.
99                  *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
100                  *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
101                  *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
102                  *    criterion ("applied") or all TR elements (i.e. no filter).
103                  *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
104                  *    Can be either 'current', whereby the current sorting of the table is used, or
105                  *    'original' whereby the original order the data was read into the table is used.
106                  *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
107                  *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
108                  *    'current' and filter is 'applied', regardless of what they might be given as.
109                  *  @returns {object} jQuery object, filtered by the given selector.
110                  *  @dtopt API
111                  *  @deprecated Since v1.10
112                  *
113                  *  @example
114                  *    $(document).ready(function() {
115                  *      var oTable = $('#example').dataTable();
116                  *
117                  *      // Highlight every second row
118                  *      oTable.$('tr:odd').css('backgroundColor', 'blue');
119                  *    } );
120                  *
121                  *  @example
122                  *    $(document).ready(function() {
123                  *      var oTable = $('#example').dataTable();
124                  *
125                  *      // Filter to rows with 'Webkit' in them, add a background colour and then
126                  *      // remove the filter, thus highlighting the 'Webkit' rows only.
127                  *      oTable.fnFilter('Webkit');
128                  *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
129                  *      oTable.fnFilter('');
130                  *    } );
131                  */
132                 this.$ = function ( sSelector, oOpts )
133                 {
134                         return this.api(true).$( sSelector, oOpts );
135                 };
136                 
137                 
138                 /**
139                  * Almost identical to $ in operation, but in this case returns the data for the matched
140                  * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
141                  * rather than any descendants, so the data can be obtained for the row/cell. If matching
142                  * rows are found, the data returned is the original data array/object that was used to
143                  * create the row (or a generated array if from a DOM source).
144                  *
145                  * This method is often useful in-combination with $ where both functions are given the
146                  * same parameters and the array indexes will match identically.
147                  *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
148                  *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
149                  *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
150                  *    criterion ("applied") or all elements (i.e. no filter).
151                  *  @param {string} [oOpts.order=current] Order of the data in the processed array.
152                  *    Can be either 'current', whereby the current sorting of the table is used, or
153                  *    'original' whereby the original order the data was read into the table is used.
154                  *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
155                  *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
156                  *    'current' and filter is 'applied', regardless of what they might be given as.
157                  *  @returns {array} Data for the matched elements. If any elements, as a result of the
158                  *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
159                  *    entry in the array.
160                  *  @dtopt API
161                  *  @deprecated Since v1.10
162                  *
163                  *  @example
164                  *    $(document).ready(function() {
165                  *      var oTable = $('#example').dataTable();
166                  *
167                  *      // Get the data from the first row in the table
168                  *      var data = oTable._('tr:first');
169                  *
170                  *      // Do something useful with the data
171                  *      alert( "First cell is: "+data[0] );
172                  *    } );
173                  *
174                  *  @example
175                  *    $(document).ready(function() {
176                  *      var oTable = $('#example').dataTable();
177                  *
178                  *      // Filter to 'Webkit' and get all data for
179                  *      oTable.fnFilter('Webkit');
180                  *      var data = oTable._('tr', {"search": "applied"});
181                  *
182                  *      // Do something with the data
183                  *      alert( data.length+" rows matched the search" );
184                  *    } );
185                  */
186                 this._ = function ( sSelector, oOpts )
187                 {
188                         return this.api(true).rows( sSelector, oOpts ).data();
189                 };
190                 
191                 
192                 /**
193                  * Create a DataTables Api instance, with the currently selected tables for
194                  * the Api's context.
195                  * @param {boolean} [traditional=false] Set the API instance's context to be
196                  *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
197                  *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
198                  *   or if all tables captured in the jQuery object should be used.
199                  * @return {DataTables.Api}
200                  */
201                 this.api = function ( traditional )
202                 {
203                         return traditional ?
204                                 new _Api(
205                                         _fnSettingsFromNode( this[ _ext.iApiIndex ] )
206                                 ) :
207                                 new _Api( this );
208                 };
209                 
210                 
211                 /**
212                  * Add a single new row or multiple rows of data to the table. Please note
213                  * that this is suitable for client-side processing only - if you are using
214                  * server-side processing (i.e. "bServerSide": true), then to add data, you
215                  * must add it to the data source, i.e. the server-side, through an Ajax call.
216                  *  @param {array|object} data The data to be added to the table. This can be:
217                  *    <ul>
218                  *      <li>1D array of data - add a single row with the data provided</li>
219                  *      <li>2D array of arrays - add multiple rows in a single call</li>
220                  *      <li>object - data object when using <i>mData</i></li>
221                  *      <li>array of objects - multiple data objects when using <i>mData</i></li>
222                  *    </ul>
223                  *  @param {bool} [redraw=true] redraw the table or not
224                  *  @returns {array} An array of integers, representing the list of indexes in
225                  *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
226                  *    the table.
227                  *  @dtopt API
228                  *  @deprecated Since v1.10
229                  *
230                  *  @example
231                  *    // Global var for counter
232                  *    var giCount = 2;
233                  *
234                  *    $(document).ready(function() {
235                  *      $('#example').dataTable();
236                  *    } );
237                  *
238                  *    function fnClickAddRow() {
239                  *      $('#example').dataTable().fnAddData( [
240                  *        giCount+".1",
241                  *        giCount+".2",
242                  *        giCount+".3",
243                  *        giCount+".4" ]
244                  *      );
245                  *
246                  *      giCount++;
247                  *    }
248                  */
249                 this.fnAddData = function( data, redraw )
250                 {
251                         var api = this.api( true );
252                 
253                         /* Check if we want to add multiple rows or not */
254                         var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
255                                 api.rows.add( data ) :
256                                 api.row.add( data );
257                 
258                         if ( redraw === undefined || redraw ) {
259                                 api.draw();
260                         }
261                 
262                         return rows.flatten().toArray();
263                 };
264                 
265                 
266                 /**
267                  * This function will make DataTables recalculate the column sizes, based on the data
268                  * contained in the table and the sizes applied to the columns (in the DOM, CSS or
269                  * through the sWidth parameter). This can be useful when the width of the table's
270                  * parent element changes (for example a window resize).
271                  *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
272                  *  @dtopt API
273                  *  @deprecated Since v1.10
274                  *
275                  *  @example
276                  *    $(document).ready(function() {
277                  *      var oTable = $('#example').dataTable( {
278                  *        "sScrollY": "200px",
279                  *        "bPaginate": false
280                  *      } );
281                  *
282                  *      $(window).bind('resize', function () {
283                  *        oTable.fnAdjustColumnSizing();
284                  *      } );
285                  *    } );
286                  */
287                 this.fnAdjustColumnSizing = function ( bRedraw )
288                 {
289                         var api = this.api( true ).columns.adjust();
290                         var settings = api.settings()[0];
291                         var scroll = settings.oScroll;
292                 
293                         if ( bRedraw === undefined || bRedraw ) {
294                                 api.draw( false );
295                         }
296                         else if ( scroll.sX !== "" || scroll.sY !== "" ) {
297                                 /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
298                                 _fnScrollDraw( settings );
299                         }
300                 };
301                 
302                 
303                 /**
304                  * Quickly and simply clear a table
305                  *  @param {bool} [bRedraw=true] redraw the table or not
306                  *  @dtopt API
307                  *  @deprecated Since v1.10
308                  *
309                  *  @example
310                  *    $(document).ready(function() {
311                  *      var oTable = $('#example').dataTable();
312                  *
313                  *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
314                  *      oTable.fnClearTable();
315                  *    } );
316                  */
317                 this.fnClearTable = function( bRedraw )
318                 {
319                         var api = this.api( true ).clear();
320                 
321                         if ( bRedraw === undefined || bRedraw ) {
322                                 api.draw();
323                         }
324                 };
325                 
326                 
327                 /**
328                  * The exact opposite of 'opening' a row, this function will close any rows which
329                  * are currently 'open'.
330                  *  @param {node} nTr the table row to 'close'
331                  *  @returns {int} 0 on success, or 1 if failed (can't find the row)
332                  *  @dtopt API
333                  *  @deprecated Since v1.10
334                  *
335                  *  @example
336                  *    $(document).ready(function() {
337                  *      var oTable;
338                  *
339                  *      // 'open' an information row when a row is clicked on
340                  *      $('#example tbody tr').click( function () {
341                  *        if ( oTable.fnIsOpen(this) ) {
342                  *          oTable.fnClose( this );
343                  *        } else {
344                  *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
345                  *        }
346                  *      } );
347                  *
348                  *      oTable = $('#example').dataTable();
349                  *    } );
350                  */
351                 this.fnClose = function( nTr )
352                 {
353                         this.api( true ).row( nTr ).child.hide();
354                 };
355                 
356                 
357                 /**
358                  * Remove a row for the table
359                  *  @param {mixed} target The index of the row from aoData to be deleted, or
360                  *    the TR element you want to delete
361                  *  @param {function|null} [callBack] Callback function
362                  *  @param {bool} [redraw=true] Redraw the table or not
363                  *  @returns {array} The row that was deleted
364                  *  @dtopt API
365                  *  @deprecated Since v1.10
366                  *
367                  *  @example
368                  *    $(document).ready(function() {
369                  *      var oTable = $('#example').dataTable();
370                  *
371                  *      // Immediately remove the first row
372                  *      oTable.fnDeleteRow( 0 );
373                  *    } );
374                  */
375                 this.fnDeleteRow = function( target, callback, redraw )
376                 {
377                         var api = this.api( true );
378                         var rows = api.rows( target );
379                         var settings = rows.settings()[0];
380                         var data = settings.aoData[ rows[0][0] ];
381                 
382                         rows.remove();
383                 
384                         if ( callback ) {
385                                 callback.call( this, settings, data );
386                         }
387                 
388                         if ( redraw === undefined || redraw ) {
389                                 api.draw();
390                         }
391                 
392                         return data;
393                 };
394                 
395                 
396                 /**
397                  * Restore the table to it's original state in the DOM by removing all of DataTables
398                  * enhancements, alterations to the DOM structure of the table and event listeners.
399                  *  @param {boolean} [remove=false] Completely remove the table from the DOM
400                  *  @dtopt API
401                  *  @deprecated Since v1.10
402                  *
403                  *  @example
404                  *    $(document).ready(function() {
405                  *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
406                  *      var oTable = $('#example').dataTable();
407                  *      oTable.fnDestroy();
408                  *    } );
409                  */
410                 this.fnDestroy = function ( remove )
411                 {
412                         this.api( true ).destroy( remove );
413                 };
414                 
415                 
416                 /**
417                  * Redraw the table
418                  *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
419                  *  @dtopt API
420                  *  @deprecated Since v1.10
421                  *
422                  *  @example
423                  *    $(document).ready(function() {
424                  *      var oTable = $('#example').dataTable();
425                  *
426                  *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
427                  *      oTable.fnDraw();
428                  *    } );
429                  */
430                 this.fnDraw = function( complete )
431                 {
432                         // Note that this isn't an exact match to the old call to _fnDraw - it takes
433                         // into account the new data, but can hold position.
434                         this.api( true ).draw( complete );
435                 };
436                 
437                 
438                 /**
439                  * Filter the input based on data
440                  *  @param {string} sInput String to filter the table on
441                  *  @param {int|null} [iColumn] Column to limit filtering to
442                  *  @param {bool} [bRegex=false] Treat as regular expression or not
443                  *  @param {bool} [bSmart=true] Perform smart filtering or not
444                  *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
445                  *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
446                  *  @dtopt API
447                  *  @deprecated Since v1.10
448                  *
449                  *  @example
450                  *    $(document).ready(function() {
451                  *      var oTable = $('#example').dataTable();
452                  *
453                  *      // Sometime later - filter...
454                  *      oTable.fnFilter( 'test string' );
455                  *    } );
456                  */
457                 this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
458                 {
459                         var api = this.api( true );
460                 
461                         if ( iColumn === null || iColumn === undefined ) {
462                                 api.search( sInput, bRegex, bSmart, bCaseInsensitive );
463                         }
464                         else {
465                                 api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
466                         }
467                 
468                         api.draw();
469                 };
470                 
471                 
472                 /**
473                  * Get the data for the whole table, an individual row or an individual cell based on the
474                  * provided parameters.
475                  *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
476                  *    a TR node then the data source for the whole row will be returned. If given as a
477                  *    TD/TH cell node then iCol will be automatically calculated and the data for the
478                  *    cell returned. If given as an integer, then this is treated as the aoData internal
479                  *    data index for the row (see fnGetPosition) and the data for that row used.
480                  *  @param {int} [col] Optional column index that you want the data of.
481                  *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
482                  *    returned. If mRow is defined, just data for that row, and is iCol is
483                  *    defined, only data for the designated cell is returned.
484                  *  @dtopt API
485                  *  @deprecated Since v1.10
486                  *
487                  *  @example
488                  *    // Row data
489                  *    $(document).ready(function() {
490                  *      oTable = $('#example').dataTable();
491                  *
492                  *      oTable.$('tr').click( function () {
493                  *        var data = oTable.fnGetData( this );
494                  *        // ... do something with the array / object of data for the row
495                  *      } );
496                  *    } );
497                  *
498                  *  @example
499                  *    // Individual cell data
500                  *    $(document).ready(function() {
501                  *      oTable = $('#example').dataTable();
502                  *
503                  *      oTable.$('td').click( function () {
504                  *        var sData = oTable.fnGetData( this );
505                  *        alert( 'The cell clicked on had the value of '+sData );
506                  *      } );
507                  *    } );
508                  */
509                 this.fnGetData = function( src, col )
510                 {
511                         var api = this.api( true );
512                 
513                         if ( src !== undefined ) {
514                                 var type = src.nodeName ? src.nodeName.toLowerCase() : '';
515                 
516                                 return col !== undefined || type == 'td' || type == 'th' ?
517                                         api.cell( src, col ).data() :
518                                         api.row( src ).data() || null;
519                         }
520                 
521                         return api.data().toArray();
522                 };
523                 
524                 
525                 /**
526                  * Get an array of the TR nodes that are used in the table's body. Note that you will
527                  * typically want to use the '$' API method in preference to this as it is more
528                  * flexible.
529                  *  @param {int} [iRow] Optional row index for the TR element you want
530                  *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
531                  *    in the table's body, or iRow is defined, just the TR element requested.
532                  *  @dtopt API
533                  *  @deprecated Since v1.10
534                  *
535                  *  @example
536                  *    $(document).ready(function() {
537                  *      var oTable = $('#example').dataTable();
538                  *
539                  *      // Get the nodes from the table
540                  *      var nNodes = oTable.fnGetNodes( );
541                  *    } );
542                  */
543                 this.fnGetNodes = function( iRow )
544                 {
545                         var api = this.api( true );
546                 
547                         return iRow !== undefined ?
548                                 api.row( iRow ).node() :
549                                 api.rows().nodes().flatten().toArray();
550                 };
551                 
552                 
553                 /**
554                  * Get the array indexes of a particular cell from it's DOM element
555                  * and column index including hidden columns
556                  *  @param {node} node this can either be a TR, TD or TH in the table's body
557                  *  @returns {int} If nNode is given as a TR, then a single index is returned, or
558                  *    if given as a cell, an array of [row index, column index (visible),
559                  *    column index (all)] is given.
560                  *  @dtopt API
561                  *  @deprecated Since v1.10
562                  *
563                  *  @example
564                  *    $(document).ready(function() {
565                  *      $('#example tbody td').click( function () {
566                  *        // Get the position of the current data from the node
567                  *        var aPos = oTable.fnGetPosition( this );
568                  *
569                  *        // Get the data array for this row
570                  *        var aData = oTable.fnGetData( aPos[0] );
571                  *
572                  *        // Update the data array and return the value
573                  *        aData[ aPos[1] ] = 'clicked';
574                  *        this.innerHTML = 'clicked';
575                  *      } );
576                  *
577                  *      // Init DataTables
578                  *      oTable = $('#example').dataTable();
579                  *    } );
580                  */
581                 this.fnGetPosition = function( node )
582                 {
583                         var api = this.api( true );
584                         var nodeName = node.nodeName.toUpperCase();
585                 
586                         if ( nodeName == 'TR' ) {
587                                 return api.row( node ).index();
588                         }
589                         else if ( nodeName == 'TD' || nodeName == 'TH' ) {
590                                 var cell = api.cell( node ).index();
591                 
592                                 return [
593                                         cell.row,
594                                         cell.columnVisible,
595                                         cell.column
596                                 ];
597                         }
598                         return null;
599                 };
600                 
601                 
602                 /**
603                  * Check to see if a row is 'open' or not.
604                  *  @param {node} nTr the table row to check
605                  *  @returns {boolean} true if the row is currently open, false otherwise
606                  *  @dtopt API
607                  *  @deprecated Since v1.10
608                  *
609                  *  @example
610                  *    $(document).ready(function() {
611                  *      var oTable;
612                  *
613                  *      // 'open' an information row when a row is clicked on
614                  *      $('#example tbody tr').click( function () {
615                  *        if ( oTable.fnIsOpen(this) ) {
616                  *          oTable.fnClose( this );
617                  *        } else {
618                  *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
619                  *        }
620                  *      } );
621                  *
622                  *      oTable = $('#example').dataTable();
623                  *    } );
624                  */
625                 this.fnIsOpen = function( nTr )
626                 {
627                         return this.api( true ).row( nTr ).child.isShown();
628                 };
629                 
630                 
631                 /**
632                  * This function will place a new row directly after a row which is currently
633                  * on display on the page, with the HTML contents that is passed into the
634                  * function. This can be used, for example, to ask for confirmation that a
635                  * particular record should be deleted.
636                  *  @param {node} nTr The table row to 'open'
637                  *  @param {string|node|jQuery} mHtml The HTML to put into the row
638                  *  @param {string} sClass Class to give the new TD cell
639                  *  @returns {node} The row opened. Note that if the table row passed in as the
640                  *    first parameter, is not found in the table, this method will silently
641                  *    return.
642                  *  @dtopt API
643                  *  @deprecated Since v1.10
644                  *
645                  *  @example
646                  *    $(document).ready(function() {
647                  *      var oTable;
648                  *
649                  *      // 'open' an information row when a row is clicked on
650                  *      $('#example tbody tr').click( function () {
651                  *        if ( oTable.fnIsOpen(this) ) {
652                  *          oTable.fnClose( this );
653                  *        } else {
654                  *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
655                  *        }
656                  *      } );
657                  *
658                  *      oTable = $('#example').dataTable();
659                  *    } );
660                  */
661                 this.fnOpen = function( nTr, mHtml, sClass )
662                 {
663                         return this.api( true )
664                                 .row( nTr )
665                                 .child( mHtml, sClass )
666                                 .show()
667                                 .child()[0];
668                 };
669                 
670                 
671                 /**
672                  * Change the pagination - provides the internal logic for pagination in a simple API
673                  * function. With this function you can have a DataTables table go to the next,
674                  * previous, first or last pages.
675                  *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
676                  *    or page number to jump to (integer), note that page 0 is the first page.
677                  *  @param {bool} [bRedraw=true] Redraw the table or not
678                  *  @dtopt API
679                  *  @deprecated Since v1.10
680                  *
681                  *  @example
682                  *    $(document).ready(function() {
683                  *      var oTable = $('#example').dataTable();
684                  *      oTable.fnPageChange( 'next' );
685                  *    } );
686                  */
687                 this.fnPageChange = function ( mAction, bRedraw )
688                 {
689                         var api = this.api( true ).page( mAction );
690                 
691                         if ( bRedraw === undefined || bRedraw ) {
692                                 api.draw(false);
693                         }
694                 };
695                 
696                 
697                 /**
698                  * Show a particular column
699                  *  @param {int} iCol The column whose display should be changed
700                  *  @param {bool} bShow Show (true) or hide (false) the column
701                  *  @param {bool} [bRedraw=true] Redraw the table or not
702                  *  @dtopt API
703                  *  @deprecated Since v1.10
704                  *
705                  *  @example
706                  *    $(document).ready(function() {
707                  *      var oTable = $('#example').dataTable();
708                  *
709                  *      // Hide the second column after initialisation
710                  *      oTable.fnSetColumnVis( 1, false );
711                  *    } );
712                  */
713                 this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
714                 {
715                         var api = this.api( true ).column( iCol ).visible( bShow );
716                 
717                         if ( bRedraw === undefined || bRedraw ) {
718                                 api.columns.adjust().draw();
719                         }
720                 };
721                 
722                 
723                 /**
724                  * Get the settings for a particular table for external manipulation
725                  *  @returns {object} DataTables settings object. See
726                  *    {@link DataTable.models.oSettings}
727                  *  @dtopt API
728                  *  @deprecated Since v1.10
729                  *
730                  *  @example
731                  *    $(document).ready(function() {
732                  *      var oTable = $('#example').dataTable();
733                  *      var oSettings = oTable.fnSettings();
734                  *
735                  *      // Show an example parameter from the settings
736                  *      alert( oSettings._iDisplayStart );
737                  *    } );
738                  */
739                 this.fnSettings = function()
740                 {
741                         return _fnSettingsFromNode( this[_ext.iApiIndex] );
742                 };
743                 
744                 
745                 /**
746                  * Sort the table by a particular column
747                  *  @param {int} iCol the data index to sort on. Note that this will not match the
748                  *    'display index' if you have hidden data entries
749                  *  @dtopt API
750                  *  @deprecated Since v1.10
751                  *
752                  *  @example
753                  *    $(document).ready(function() {
754                  *      var oTable = $('#example').dataTable();
755                  *
756                  *      // Sort immediately with columns 0 and 1
757                  *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
758                  *    } );
759                  */
760                 this.fnSort = function( aaSort )
761                 {
762                         this.api( true ).order( aaSort ).draw();
763                 };
764                 
765                 
766                 /**
767                  * Attach a sort listener to an element for a given column
768                  *  @param {node} nNode the element to attach the sort listener to
769                  *  @param {int} iColumn the column that a click on this node will sort on
770                  *  @param {function} [fnCallback] callback function when sort is run
771                  *  @dtopt API
772                  *  @deprecated Since v1.10
773                  *
774                  *  @example
775                  *    $(document).ready(function() {
776                  *      var oTable = $('#example').dataTable();
777                  *
778                  *      // Sort on column 1, when 'sorter' is clicked on
779                  *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
780                  *    } );
781                  */
782                 this.fnSortListener = function( nNode, iColumn, fnCallback )
783                 {
784                         this.api( true ).order.listener( nNode, iColumn, fnCallback );
785                 };
786                 
787                 
788                 /**
789                  * Update a table cell or row - this method will accept either a single value to
790                  * update the cell with, an array of values with one element for each column or
791                  * an object in the same format as the original data source. The function is
792                  * self-referencing in order to make the multi column updates easier.
793                  *  @param {object|array|string} mData Data to update the cell/row with
794                  *  @param {node|int} mRow TR element you want to update or the aoData index
795                  *  @param {int} [iColumn] The column to update, give as null or undefined to
796                  *    update a whole row.
797                  *  @param {bool} [bRedraw=true] Redraw the table or not
798                  *  @param {bool} [bAction=true] Perform pre-draw actions or not
799                  *  @returns {int} 0 on success, 1 on error
800                  *  @dtopt API
801                  *  @deprecated Since v1.10
802                  *
803                  *  @example
804                  *    $(document).ready(function() {
805                  *      var oTable = $('#example').dataTable();
806                  *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
807                  *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
808                  *    } );
809                  */
810                 this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
811                 {
812                         var api = this.api( true );
813                 
814                         if ( iColumn === undefined || iColumn === null ) {
815                                 api.row( mRow ).data( mData );
816                         }
817                         else {
818                                 api.cell( mRow, iColumn ).data( mData );
819                         }
820                 
821                         if ( bAction === undefined || bAction ) {
822                                 api.columns.adjust();
823                         }
824                 
825                         if ( bRedraw === undefined || bRedraw ) {
826                                 api.draw();
827                         }
828                         return 0;
829                 };
830                 
831                 
832                 /**
833                  * Provide a common method for plug-ins to check the version of DataTables being used, in order
834                  * to ensure compatibility.
835                  *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
836                  *    formats "X" and "X.Y" are also acceptable.
837                  *  @returns {boolean} true if this version of DataTables is greater or equal to the required
838                  *    version, or false if this version of DataTales is not suitable
839                  *  @method
840                  *  @dtopt API
841                  *  @deprecated Since v1.10
842                  *
843                  *  @example
844                  *    $(document).ready(function() {
845                  *      var oTable = $('#example').dataTable();
846                  *      alert( oTable.fnVersionCheck( '1.9.0' ) );
847                  *    } );
848                  */
849                 this.fnVersionCheck = _ext.fnVersionCheck;
850                 
852                 var _that = this;
853                 var emptyInit = options === undefined;
854                 var len = this.length;
856                 if ( emptyInit ) {
857                         options = {};
858                 }
860                 this.oApi = this.internal = _ext.internal;
862                 // Extend with old style plug-in API methods
863                 for ( var fn in DataTable.ext.internal ) {
864                         if ( fn ) {
865                                 this[fn] = _fnExternApiFunc(fn);
866                         }
867                 }
869                 this.each(function() {
870                         // For each initialisation we want to give it a clean initialisation
871                         // object that can be bashed around
872                         var o = {};
873                         var oInit = len > 1 ? // optimisation for single table case
874                                 _fnExtend( o, options, true ) :
875                                 options;
877                         /*global oInit,_that,emptyInit*/
878                         var i=0, iLen, j, jLen, k, kLen;
879                         var sId = this.getAttribute( 'id' );
880                         var bInitHandedOff = false;
881                         var defaults = DataTable.defaults;
882                         var $this = $(this);
883                         
884                         
885                         /* Sanity check */
886                         if ( this.nodeName.toLowerCase() != 'table' )
887                         {
888                                 _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
889                                 return;
890                         }
891                         
892                         /* Backwards compatibility for the defaults */
893                         _fnCompatOpts( defaults );
894                         _fnCompatCols( defaults.column );
895                         
896                         /* Convert the camel-case defaults to Hungarian */
897                         _fnCamelToHungarian( defaults, defaults, true );
898                         _fnCamelToHungarian( defaults.column, defaults.column, true );
899                         
900                         /* Setting up the initialisation object */
901                         _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );
902                         
903                         
904                         
905                         /* Check to see if we are re-initialising a table */
906                         var allSettings = DataTable.settings;
907                         for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
908                         {
909                                 var s = allSettings[i];
910                         
911                                 /* Base check on table node */
912                                 if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) )
913                                 {
914                                         var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
915                                         var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
916                         
917                                         if ( emptyInit || bRetrieve )
918                                         {
919                                                 return s.oInstance;
920                                         }
921                                         else if ( bDestroy )
922                                         {
923                                                 s.oInstance.fnDestroy();
924                                                 break;
925                                         }
926                                         else
927                                         {
928                                                 _fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );
929                                                 return;
930                                         }
931                                 }
932                         
933                                 /* If the element we are initialising has the same ID as a table which was previously
934                                  * initialised, but the table nodes don't match (from before) then we destroy the old
935                                  * instance by simply deleting it. This is under the assumption that the table has been
936                                  * destroyed by other methods. Anyone using non-id selectors will need to do this manually
937                                  */
938                                 if ( s.sTableId == this.id )
939                                 {
940                                         allSettings.splice( i, 1 );
941                                         break;
942                                 }
943                         }
944                         
945                         /* Ensure the table has an ID - required for accessibility */
946                         if ( sId === null || sId === "" )
947                         {
948                                 sId = "DataTables_Table_"+(DataTable.ext._unique++);
949                                 this.id = sId;
950                         }
951                         
952                         /* Create the settings object for this table and set some of the default parameters */
953                         var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
954                                 "sDestroyWidth": $this[0].style.width,
955                                 "sInstance":     sId,
956                                 "sTableId":      sId
957                         } );
958                         oSettings.nTable = this;
959                         oSettings.oApi   = _that.internal;
960                         oSettings.oInit  = oInit;
961                         
962                         allSettings.push( oSettings );
963                         
964                         // Need to add the instance after the instance after the settings object has been added
965                         // to the settings array, so we can self reference the table instance if more than one
966                         oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();
967                         
968                         // Backwards compatibility, before we apply all the defaults
969                         _fnCompatOpts( oInit );
970                         
971                         if ( oInit.oLanguage )
972                         {
973                                 _fnLanguageCompat( oInit.oLanguage );
974                         }
975                         
976                         // If the length menu is given, but the init display length is not, use the length menu
977                         if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
978                         {
979                                 oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
980                                         oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
981                         }
982                         
983                         // Apply the defaults and init options to make a single init object will all
984                         // options defined from defaults and instance options.
985                         oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
986                         
987                         
988                         // Map the initialisation options onto the settings object
989                         _fnMap( oSettings.oFeatures, oInit, [
990                                 "bPaginate",
991                                 "bLengthChange",
992                                 "bFilter",
993                                 "bSort",
994                                 "bSortMulti",
995                                 "bInfo",
996                                 "bProcessing",
997                                 "bAutoWidth",
998                                 "bSortClasses",
999                                 "bServerSide",
1000                                 "bDeferRender"
1001                         ] );
1002                         _fnMap( oSettings, oInit, [
1003                                 "asStripeClasses",
1004                                 "ajax",
1005                                 "fnServerData",
1006                                 "fnFormatNumber",
1007                                 "sServerMethod",
1008                                 "aaSorting",
1009                                 "aaSortingFixed",
1010                                 "aLengthMenu",
1011                                 "sPaginationType",
1012                                 "sAjaxSource",
1013                                 "sAjaxDataProp",
1014                                 "iStateDuration",
1015                                 "sDom",
1016                                 "bSortCellsTop",
1017                                 "iTabIndex",
1018                                 "fnStateLoadCallback",
1019                                 "fnStateSaveCallback",
1020                                 "renderer",
1021                                 "searchDelay",
1022                                 "rowId",
1023                                 [ "iCookieDuration", "iStateDuration" ], // backwards compat
1024                                 [ "oSearch", "oPreviousSearch" ],
1025                                 [ "aoSearchCols", "aoPreSearchCols" ],
1026                                 [ "iDisplayLength", "_iDisplayLength" ],
1027                                 [ "bJQueryUI", "bJUI" ]
1028                         ] );
1029                         _fnMap( oSettings.oScroll, oInit, [
1030                                 [ "sScrollX", "sX" ],
1031                                 [ "sScrollXInner", "sXInner" ],
1032                                 [ "sScrollY", "sY" ],
1033                                 [ "bScrollCollapse", "bCollapse" ]
1034                         ] );
1035                         _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
1036                         
1037                         /* Callback functions which are array driven */
1038                         _fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
1039                         _fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
1040                         _fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
1041                         _fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
1042                         _fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
1043                         _fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
1044                         _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
1045                         _fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
1046                         _fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
1047                         _fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
1048                         _fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
1049                         
1050                         oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );
1051                         
1052                         /* Browser support detection */
1053                         _fnBrowserDetect( oSettings );
1054                         
1055                         var oClasses = oSettings.oClasses;
1056                         
1057                         // @todo Remove in 1.11
1058                         if ( oInit.bJQueryUI )
1059                         {
1060                                 /* Use the JUI classes object for display. You could clone the oStdClasses object if
1061                                  * you want to have multiple tables with multiple independent classes
1062                                  */
1063                                 $.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses );
1064                         
1065                                 if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" )
1066                                 {
1067                                         /* Set the DOM to use a layout suitable for jQuery UI's theming */
1068                                         oSettings.sDom = '<"H"lfr>t<"F"ip>';
1069                                 }
1070                         
1071                                 if ( ! oSettings.renderer ) {
1072                                         oSettings.renderer = 'jqueryui';
1073                                 }
1074                                 else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) {
1075                                         oSettings.renderer.header = 'jqueryui';
1076                                 }
1077                         }
1078                         else
1079                         {
1080                                 $.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
1081                         }
1082                         $this.addClass( oClasses.sTable );
1083                         
1084                         
1085                         if ( oSettings.iInitDisplayStart === undefined )
1086                         {
1087                                 /* Display start point, taking into account the save saving */
1088                                 oSettings.iInitDisplayStart = oInit.iDisplayStart;
1089                                 oSettings._iDisplayStart = oInit.iDisplayStart;
1090                         }
1091                         
1092                         if ( oInit.iDeferLoading !== null )
1093                         {
1094                                 oSettings.bDeferLoading = true;
1095                                 var tmp = $.isArray( oInit.iDeferLoading );
1096                                 oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
1097                                 oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
1098                         }
1099                         
1100                         /* Language definitions */
1101                         var oLanguage = oSettings.oLanguage;
1102                         $.extend( true, oLanguage, oInit.oLanguage );
1103                         
1104                         if ( oLanguage.sUrl !== "" )
1105                         {
1106                                 /* Get the language definitions from a file - because this Ajax call makes the language
1107                                  * get async to the remainder of this function we use bInitHandedOff to indicate that
1108                                  * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
1109                                  */
1110                                 $.ajax( {
1111                                         dataType: 'json',
1112                                         url: oLanguage.sUrl,
1113                                         success: function ( json ) {
1114                                                 _fnLanguageCompat( json );
1115                                                 _fnCamelToHungarian( defaults.oLanguage, json );
1116                                                 $.extend( true, oLanguage, json );
1117                                                 _fnInitialise( oSettings );
1118                                         },
1119                                         error: function () {
1120                                                 // Error occurred loading language file, continue on as best we can
1121                                                 _fnInitialise( oSettings );
1122                                         }
1123                                 } );
1124                                 bInitHandedOff = true;
1125                         }
1126                         
1127                         /*
1128                          * Stripes
1129                          */
1130                         if ( oInit.asStripeClasses === null )
1131                         {
1132                                 oSettings.asStripeClasses =[
1133                                         oClasses.sStripeOdd,
1134                                         oClasses.sStripeEven
1135                                 ];
1136                         }
1137                         
1138                         /* Remove row stripe classes if they are already on the table row */
1139                         var stripeClasses = oSettings.asStripeClasses;
1140                         var rowOne = $this.children('tbody').find('tr').eq(0);
1141                         if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
1142                                 return rowOne.hasClass(el);
1143                         } ) ) !== -1 ) {
1144                                 $('tbody tr', this).removeClass( stripeClasses.join(' ') );
1145                                 oSettings.asDestroyStripes = stripeClasses.slice();
1146                         }
1147                         
1148                         /*
1149                          * Columns
1150                          * See if we should load columns automatically or use defined ones
1151                          */
1152                         var anThs = [];
1153                         var aoColumnsInit;
1154                         var nThead = this.getElementsByTagName('thead');
1155                         if ( nThead.length !== 0 )
1156                         {
1157                                 _fnDetectHeader( oSettings.aoHeader, nThead[0] );
1158                                 anThs = _fnGetUniqueThs( oSettings );
1159                         }
1160                         
1161                         /* If not given a column array, generate one with nulls */
1162                         if ( oInit.aoColumns === null )
1163                         {
1164                                 aoColumnsInit = [];
1165                                 for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
1166                                 {
1167                                         aoColumnsInit.push( null );
1168                                 }
1169                         }
1170                         else
1171                         {
1172                                 aoColumnsInit = oInit.aoColumns;
1173                         }
1174                         
1175                         /* Add the columns */
1176                         for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
1177                         {
1178                                 _fnAddColumn( oSettings, anThs ? anThs[i] : null );
1179                         }
1180                         
1181                         /* Apply the column definitions */
1182                         _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
1183                                 _fnColumnOptions( oSettings, iCol, oDef );
1184                         } );
1185                         
1186                         /* HTML5 attribute detection - build an mData object automatically if the
1187                          * attributes are found
1188                          */
1189                         if ( rowOne.length ) {
1190                                 var a = function ( cell, name ) {
1191                                         return cell.getAttribute( 'data-'+name ) !== null ? name : null;
1192                                 };
1193                         
1194                                 $( rowOne[0] ).children('th, td').each( function (i, cell) {
1195                                         var col = oSettings.aoColumns[i];
1196                         
1197                                         if ( col.mData === i ) {
1198                                                 var sort = a( cell, 'sort' ) || a( cell, 'order' );
1199                                                 var filter = a( cell, 'filter' ) || a( cell, 'search' );
1200                         
1201                                                 if ( sort !== null || filter !== null ) {
1202                                                         col.mData = {
1203                                                                 _:      i+'.display',
1204                                                                 sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
1205                                                                 type:   sort !== null   ? i+'.@data-'+sort   : undefined,
1206                                                                 filter: filter !== null ? i+'.@data-'+filter : undefined
1207                                                         };
1208                         
1209                                                         _fnColumnOptions( oSettings, i );
1210                                                 }
1211                                         }
1212                                 } );
1213                         }
1214                         
1215                         var features = oSettings.oFeatures;
1216                         
1217                         /* Must be done after everything which can be overridden by the state saving! */
1218                         if ( oInit.bStateSave )
1219                         {
1220                                 features.bStateSave = true;
1221                                 _fnLoadState( oSettings, oInit );
1222                                 _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
1223                         }
1224                         
1225                         
1226                         /*
1227                          * Sorting
1228                          * @todo For modularisation (1.11) this needs to do into a sort start up handler
1229                          */
1230                         
1231                         // If aaSorting is not defined, then we use the first indicator in asSorting
1232                         // in case that has been altered, so the default sort reflects that option
1233                         if ( oInit.aaSorting === undefined )
1234                         {
1235                                 var sorting = oSettings.aaSorting;
1236                                 for ( i=0, iLen=sorting.length ; i<iLen ; i++ )
1237                                 {
1238                                         sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
1239                                 }
1240                         }
1241                         
1242                         /* Do a first pass on the sorting classes (allows any size changes to be taken into
1243                          * account, and also will apply sorting disabled classes if disabled
1244                          */
1245                         _fnSortingClasses( oSettings );
1246                         
1247                         if ( features.bSort )
1248                         {
1249                                 _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1250                                         if ( oSettings.bSorted ) {
1251                                                 var aSort = _fnSortFlatten( oSettings );
1252                                                 var sortedColumns = {};
1253                         
1254                                                 $.each( aSort, function (i, val) {
1255                                                         sortedColumns[ val.src ] = val.dir;
1256                                                 } );
1257                         
1258                                                 _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
1259                                                 _fnSortAria( oSettings );
1260                                         }
1261                                 } );
1262                         }
1263                         
1264                         _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1265                                 if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
1266                                         _fnSortingClasses( oSettings );
1267                                 }
1268                         }, 'sc' );
1269                         
1270                         
1271                         /*
1272                          * Final init
1273                          * Cache the header, body and footer as required, creating them if needed
1274                          */
1275                         
1276                         // Work around for Webkit bug 83867 - store the caption-side before removing from doc
1277                         var captions = $this.children('caption').each( function () {
1278                                 this._captionSide = $this.css('caption-side');
1279                         } );
1280                         
1281                         var thead = $this.children('thead');
1282                         if ( thead.length === 0 )
1283                         {
1284                                 thead = $('<thead/>').appendTo(this);
1285                         }
1286                         oSettings.nTHead = thead[0];
1287                         
1288                         var tbody = $this.children('tbody');
1289                         if ( tbody.length === 0 )
1290                         {
1291                                 tbody = $('<tbody/>').appendTo(this);
1292                         }
1293                         oSettings.nTBody = tbody[0];
1294                         
1295                         var tfoot = $this.children('tfoot');
1296                         if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
1297                         {
1298                                 // If we are a scrolling table, and no footer has been given, then we need to create
1299                                 // a tfoot element for the caption element to be appended to
1300                                 tfoot = $('<tfoot/>').appendTo(this);
1301                         }
1302                         
1303                         if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
1304                                 $this.addClass( oClasses.sNoFooter );
1305                         }
1306                         else if ( tfoot.length > 0 ) {
1307                                 oSettings.nTFoot = tfoot[0];
1308                                 _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
1309                         }
1310                         
1311                         /* Check if there is data passing into the constructor */
1312                         if ( oInit.aaData )
1313                         {
1314                                 for ( i=0 ; i<oInit.aaData.length ; i++ )
1315                                 {
1316                                         _fnAddData( oSettings, oInit.aaData[ i ] );
1317                                 }
1318                         }
1319                         else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' )
1320                         {
1321                                 /* Grab the data from the page - only do this when deferred loading or no Ajax
1322                                  * source since there is no point in reading the DOM data if we are then going
1323                                  * to replace it with Ajax data
1324                                  */
1325                                 _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
1326                         }
1327                         
1328                         /* Copy the data index array */
1329                         oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
1330                         
1331                         /* Initialisation complete - table can be drawn */
1332                         oSettings.bInitialised = true;
1333                         
1334                         /* Check if we need to initialise the table (it might not have been handed off to the
1335                          * language processor)
1336                          */
1337                         if ( bInitHandedOff === false )
1338                         {
1339                                 _fnInitialise( oSettings );
1340                         }
1341                 } );
1342                 _that = null;
1343                 return this;
1344         };
1346         
1347         /*
1348          * It is useful to have variables which are scoped locally so only the
1349          * DataTables functions can access them and they don't leak into global space.
1350          * At the same time these functions are often useful over multiple files in the
1351          * core and API, so we list, or at least document, all variables which are used
1352          * by DataTables as private variables here. This also ensures that there is no
1353          * clashing of variable names and that they can easily referenced for reuse.
1354          */
1355         
1356         
1357         // Defined else where
1358         //  _selector_run
1359         //  _selector_opts
1360         //  _selector_first
1361         //  _selector_row_indexes
1362         
1363         var _ext; // DataTable.ext
1364         var _Api; // DataTable.Api
1365         var _api_register; // DataTable.Api.register
1366         var _api_registerPlural; // DataTable.Api.registerPlural
1367         
1368         var _re_dic = {};
1369         var _re_new_lines = /[\r\n]/g;
1370         var _re_html = /<.*?>/g;
1371         var _re_date_start = /^[\w\+\-]/;
1372         var _re_date_end = /[\w\+\-]$/;
1373         
1374         // Escape regular expression special characters
1375         var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
1376         
1377         // http://en.wikipedia.org/wiki/Foreign_exchange_market
1378         // - \u20BD - Russian ruble.
1379         // - \u20a9 - South Korean Won
1380         // - \u20BA - Turkish Lira
1381         // - \u20B9 - Indian Rupee
1382         // - R - Brazil (R$) and South Africa
1383         // - fr - Swiss Franc
1384         // - kr - Swedish krona, Norwegian krone and Danish krone
1385         // - \u2009 is thin space and \u202F is narrow no-break space, both used in many
1386         //   standards as thousands separators.
1387         var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi;
1388         
1389         
1390         var _empty = function ( d ) {
1391                 return !d || d === true || d === '-' ? true : false;
1392         };
1393         
1394         
1395         var _intVal = function ( s ) {
1396                 var integer = parseInt( s, 10 );
1397                 return !isNaN(integer) && isFinite(s) ? integer : null;
1398         };
1399         
1400         // Convert from a formatted number with characters other than `.` as the
1401         // decimal place, to a Javascript number
1402         var _numToDecimal = function ( num, decimalPoint ) {
1403                 // Cache created regular expressions for speed as this function is called often
1404                 if ( ! _re_dic[ decimalPoint ] ) {
1405                         _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
1406                 }
1407                 return typeof num === 'string' && decimalPoint !== '.' ?
1408                         num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
1409                         num;
1410         };
1411         
1412         
1413         var _isNumber = function ( d, decimalPoint, formatted ) {
1414                 var strType = typeof d === 'string';
1415         
1416                 // If empty return immediately so there must be a number if it is a
1417                 // formatted string (this stops the string "k", or "kr", etc being detected
1418                 // as a formatted number for currency
1419                 if ( _empty( d ) ) {
1420                         return true;
1421                 }
1422         
1423                 if ( decimalPoint && strType ) {
1424                         d = _numToDecimal( d, decimalPoint );
1425                 }
1426         
1427                 if ( formatted && strType ) {
1428                         d = d.replace( _re_formatted_numeric, '' );
1429                 }
1430         
1431                 return !isNaN( parseFloat(d) ) && isFinite( d );
1432         };
1433         
1434         
1435         // A string without HTML in it can be considered to be HTML still
1436         var _isHtml = function ( d ) {
1437                 return _empty( d ) || typeof d === 'string';
1438         };
1439         
1440         
1441         var _htmlNumeric = function ( d, decimalPoint, formatted ) {
1442                 if ( _empty( d ) ) {
1443                         return true;
1444                 }
1445         
1446                 var html = _isHtml( d );
1447                 return ! html ?
1448                         null :
1449                         _isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
1450                                 true :
1451                                 null;
1452         };
1453         
1454         
1455         var _pluck = function ( a, prop, prop2 ) {
1456                 var out = [];
1457                 var i=0, ien=a.length;
1458         
1459                 // Could have the test in the loop for slightly smaller code, but speed
1460                 // is essential here
1461                 if ( prop2 !== undefined ) {
1462                         for ( ; i<ien ; i++ ) {
1463                                 if ( a[i] && a[i][ prop ] ) {
1464                                         out.push( a[i][ prop ][ prop2 ] );
1465                                 }
1466                         }
1467                 }
1468                 else {
1469                         for ( ; i<ien ; i++ ) {
1470                                 if ( a[i] ) {
1471                                         out.push( a[i][ prop ] );
1472                                 }
1473                         }
1474                 }
1475         
1476                 return out;
1477         };
1478         
1479         
1480         // Basically the same as _pluck, but rather than looping over `a` we use `order`
1481         // as the indexes to pick from `a`
1482         var _pluck_order = function ( a, order, prop, prop2 )
1483         {
1484                 var out = [];
1485                 var i=0, ien=order.length;
1486         
1487                 // Could have the test in the loop for slightly smaller code, but speed
1488                 // is essential here
1489                 if ( prop2 !== undefined ) {
1490                         for ( ; i<ien ; i++ ) {
1491                                 if ( a[ order[i] ][ prop ] ) {
1492                                         out.push( a[ order[i] ][ prop ][ prop2 ] );
1493                                 }
1494                         }
1495                 }
1496                 else {
1497                         for ( ; i<ien ; i++ ) {
1498                                 out.push( a[ order[i] ][ prop ] );
1499                         }
1500                 }
1501         
1502                 return out;
1503         };
1504         
1505         
1506         var _range = function ( len, start )
1507         {
1508                 var out = [];
1509                 var end;
1510         
1511                 if ( start === undefined ) {
1512                         start = 0;
1513                         end = len;
1514                 }
1515                 else {
1516                         end = start;
1517                         start = len;
1518                 }
1519         
1520                 for ( var i=start ; i<end ; i++ ) {
1521                         out.push( i );
1522                 }
1523         
1524                 return out;
1525         };
1526         
1527         
1528         var _removeEmpty = function ( a )
1529         {
1530                 var out = [];
1531         
1532                 for ( var i=0, ien=a.length ; i<ien ; i++ ) {
1533                         if ( a[i] ) { // careful - will remove all falsy values!
1534                                 out.push( a[i] );
1535                         }
1536                 }
1537         
1538                 return out;
1539         };
1540         
1541         
1542         var _stripHtml = function ( d ) {
1543                 return d.replace( _re_html, '' );
1544         };
1545         
1546         
1547         /**
1548          * Find the unique elements in a source array.
1549          *
1550          * @param  {array} src Source array
1551          * @return {array} Array of unique items
1552          * @ignore
1553          */
1554         var _unique = function ( src )
1555         {
1556                 // A faster unique method is to use object keys to identify used values,
1557                 // but this doesn't work with arrays or objects, which we must also
1558                 // consider. See jsperf.com/compare-array-unique-versions/4 for more
1559                 // information.
1560                 var
1561                         out = [],
1562                         val,
1563                         i, ien=src.length,
1564                         j, k=0;
1565         
1566                 again: for ( i=0 ; i<ien ; i++ ) {
1567                         val = src[i];
1568         
1569                         for ( j=0 ; j<k ; j++ ) {
1570                                 if ( out[j] === val ) {
1571                                         continue again;
1572                                 }
1573                         }
1574         
1575                         out.push( val );
1576                         k++;
1577                 }
1578         
1579                 return out;
1580         };
1581         
1582         
1583         /**
1584          * DataTables utility methods
1585          * 
1586          * This namespace provides helper methods that DataTables uses internally to
1587          * create a DataTable, but which are not exclusively used only for DataTables.
1588          * These methods can be used by extension authors to save the duplication of
1589          * code.
1590          *
1591          *  @namespace
1592          */
1593         DataTable.util = {
1594                 /**
1595                  * Throttle the calls to a function. Arguments and context are maintained
1596                  * for the throttled function.
1597                  *
1598                  * @param {function} fn Function to be called
1599                  * @param {integer} freq Call frequency in mS
1600                  * @return {function} Wrapped function
1601                  */
1602                 throttle: function ( fn, freq ) {
1603                         var
1604                                 frequency = freq !== undefined ? freq : 200,
1605                                 last,
1606                                 timer;
1607         
1608                         return function () {
1609                                 var
1610                                         that = this,
1611                                         now  = +new Date(),
1612                                         args = arguments;
1613         
1614                                 if ( last && now < last + frequency ) {
1615                                         clearTimeout( timer );
1616         
1617                                         timer = setTimeout( function () {
1618                                                 last = undefined;
1619                                                 fn.apply( that, args );
1620                                         }, frequency );
1621                                 }
1622                                 else {
1623                                         last = now;
1624                                         fn.apply( that, args );
1625                                 }
1626                         };
1627                 },
1628         
1629         
1630                 /**
1631                  * Escape a string such that it can be used in a regular expression
1632                  *
1633                  *  @param {string} val string to escape
1634                  *  @returns {string} escaped string
1635                  */
1636                 escapeRegex: function ( val ) {
1637                         return val.replace( _re_escape_regex, '\\$1' );
1638                 }
1639         };
1640         
1641         
1642         
1643         /**
1644          * Create a mapping object that allows camel case parameters to be looked up
1645          * for their Hungarian counterparts. The mapping is stored in a private
1646          * parameter called `_hungarianMap` which can be accessed on the source object.
1647          *  @param {object} o
1648          *  @memberof DataTable#oApi
1649          */
1650         function _fnHungarianMap ( o )
1651         {
1652                 var
1653                         hungarian = 'a aa ai ao as b fn i m o s ',
1654                         match,
1655                         newKey,
1656                         map = {};
1657         
1658                 $.each( o, function (key, val) {
1659                         match = key.match(/^([^A-Z]+?)([A-Z])/);
1660         
1661                         if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
1662                         {
1663                                 newKey = key.replace( match[0], match[2].toLowerCase() );
1664                                 map[ newKey ] = key;
1665         
1666                                 if ( match[1] === 'o' )
1667                                 {
1668                                         _fnHungarianMap( o[key] );
1669                                 }
1670                         }
1671                 } );
1672         
1673                 o._hungarianMap = map;
1674         }
1675         
1676         
1677         /**
1678          * Convert from camel case parameters to Hungarian, based on a Hungarian map
1679          * created by _fnHungarianMap.
1680          *  @param {object} src The model object which holds all parameters that can be
1681          *    mapped.
1682          *  @param {object} user The object to convert from camel case to Hungarian.
1683          *  @param {boolean} force When set to `true`, properties which already have a
1684          *    Hungarian value in the `user` object will be overwritten. Otherwise they
1685          *    won't be.
1686          *  @memberof DataTable#oApi
1687          */
1688         function _fnCamelToHungarian ( src, user, force )
1689         {
1690                 if ( ! src._hungarianMap ) {
1691                         _fnHungarianMap( src );
1692                 }
1693         
1694                 var hungarianKey;
1695         
1696                 $.each( user, function (key, val) {
1697                         hungarianKey = src._hungarianMap[ key ];
1698         
1699                         if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
1700                         {
1701                                 // For objects, we need to buzz down into the object to copy parameters
1702                                 if ( hungarianKey.charAt(0) === 'o' )
1703                                 {
1704                                         // Copy the camelCase options over to the hungarian
1705                                         if ( ! user[ hungarianKey ] ) {
1706                                                 user[ hungarianKey ] = {};
1707                                         }
1708                                         $.extend( true, user[hungarianKey], user[key] );
1709         
1710                                         _fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
1711                                 }
1712                                 else {
1713                                         user[hungarianKey] = user[ key ];
1714                                 }
1715                         }
1716                 } );
1717         }
1718         
1719         
1720         /**
1721          * Language compatibility - when certain options are given, and others aren't, we
1722          * need to duplicate the values over, in order to provide backwards compatibility
1723          * with older language files.
1724          *  @param {object} oSettings dataTables settings object
1725          *  @memberof DataTable#oApi
1726          */
1727         function _fnLanguageCompat( lang )
1728         {
1729                 var defaults = DataTable.defaults.oLanguage;
1730                 var zeroRecords = lang.sZeroRecords;
1731         
1732                 /* Backwards compatibility - if there is no sEmptyTable given, then use the same as
1733                  * sZeroRecords - assuming that is given.
1734                  */
1735                 if ( ! lang.sEmptyTable && zeroRecords &&
1736                         defaults.sEmptyTable === "No data available in table" )
1737                 {
1738                         _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
1739                 }
1740         
1741                 /* Likewise with loading records */
1742                 if ( ! lang.sLoadingRecords && zeroRecords &&
1743                         defaults.sLoadingRecords === "Loading..." )
1744                 {
1745                         _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
1746                 }
1747         
1748                 // Old parameter name of the thousands separator mapped onto the new
1749                 if ( lang.sInfoThousands ) {
1750                         lang.sThousands = lang.sInfoThousands;
1751                 }
1752         
1753                 var decimal = lang.sDecimal;
1754                 if ( decimal ) {
1755                         _addNumericSort( decimal );
1756                 }
1757         }
1758         
1759         
1760         /**
1761          * Map one parameter onto another
1762          *  @param {object} o Object to map
1763          *  @param {*} knew The new parameter name
1764          *  @param {*} old The old parameter name
1765          */
1766         var _fnCompatMap = function ( o, knew, old ) {
1767                 if ( o[ knew ] !== undefined ) {
1768                         o[ old ] = o[ knew ];
1769                 }
1770         };
1771         
1772         
1773         /**
1774          * Provide backwards compatibility for the main DT options. Note that the new
1775          * options are mapped onto the old parameters, so this is an external interface
1776          * change only.
1777          *  @param {object} init Object to map
1778          */
1779         function _fnCompatOpts ( init )
1780         {
1781                 _fnCompatMap( init, 'ordering',      'bSort' );
1782                 _fnCompatMap( init, 'orderMulti',    'bSortMulti' );
1783                 _fnCompatMap( init, 'orderClasses',  'bSortClasses' );
1784                 _fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
1785                 _fnCompatMap( init, 'order',         'aaSorting' );
1786                 _fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
1787                 _fnCompatMap( init, 'paging',        'bPaginate' );
1788                 _fnCompatMap( init, 'pagingType',    'sPaginationType' );
1789                 _fnCompatMap( init, 'pageLength',    'iDisplayLength' );
1790                 _fnCompatMap( init, 'searching',     'bFilter' );
1791         
1792                 // Boolean initialisation of x-scrolling
1793                 if ( typeof init.sScrollX === 'boolean' ) {
1794                         init.sScrollX = init.sScrollX ? '100%' : '';
1795                 }
1796                 if ( typeof init.scrollX === 'boolean' ) {
1797                         init.scrollX = init.scrollX ? '100%' : '';
1798                 }
1799         
1800                 // Column search objects are in an array, so it needs to be converted
1801                 // element by element
1802                 var searchCols = init.aoSearchCols;
1803         
1804                 if ( searchCols ) {
1805                         for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
1806                                 if ( searchCols[i] ) {
1807                                         _fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
1808                                 }
1809                         }
1810                 }
1811         }
1812         
1813         
1814         /**
1815          * Provide backwards compatibility for column options. Note that the new options
1816          * are mapped onto the old parameters, so this is an external interface change
1817          * only.
1818          *  @param {object} init Object to map
1819          */
1820         function _fnCompatCols ( init )
1821         {
1822                 _fnCompatMap( init, 'orderable',     'bSortable' );
1823                 _fnCompatMap( init, 'orderData',     'aDataSort' );
1824                 _fnCompatMap( init, 'orderSequence', 'asSorting' );
1825                 _fnCompatMap( init, 'orderDataType', 'sortDataType' );
1826         
1827                 // orderData can be given as an integer
1828                 var dataSort = init.aDataSort;
1829                 if ( dataSort && ! $.isArray( dataSort ) ) {
1830                         init.aDataSort = [ dataSort ];
1831                 }
1832         }
1833         
1834         
1835         /**
1836          * Browser feature detection for capabilities, quirks
1837          *  @param {object} settings dataTables settings object
1838          *  @memberof DataTable#oApi
1839          */
1840         function _fnBrowserDetect( settings )
1841         {
1842                 // We don't need to do this every time DataTables is constructed, the values
1843                 // calculated are specific to the browser and OS configuration which we
1844                 // don't expect to change between initialisations
1845                 if ( ! DataTable.__browser ) {
1846                         var browser = {};
1847                         DataTable.__browser = browser;
1848         
1849                         // Scrolling feature / quirks detection
1850                         var n = $('<div/>')
1851                                 .css( {
1852                                         position: 'fixed',
1853                                         top: 0,
1854                                         left: 0,
1855                                         height: 1,
1856                                         width: 1,
1857                                         overflow: 'hidden'
1858                                 } )
1859                                 .append(
1860                                         $('<div/>')
1861                                                 .css( {
1862                                                         position: 'absolute',
1863                                                         top: 1,
1864                                                         left: 1,
1865                                                         width: 100,
1866                                                         overflow: 'scroll'
1867                                                 } )
1868                                                 .append(
1869                                                         $('<div/>')
1870                                                                 .css( {
1871                                                                         width: '100%',
1872                                                                         height: 10
1873                                                                 } )
1874                                                 )
1875                                 )
1876                                 .appendTo( 'body' );
1877         
1878                         var outer = n.children();
1879                         var inner = outer.children();
1880         
1881                         // Numbers below, in order, are:
1882                         // inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
1883                         //
1884                         // IE6 XP:                           100 100 100  83
1885                         // IE7 Vista:                        100 100 100  83
1886                         // IE 8+ Windows:                     83  83 100  83
1887                         // Evergreen Windows:                 83  83 100  83
1888                         // Evergreen Mac with scrollbars:     85  85 100  85
1889                         // Evergreen Mac without scrollbars: 100 100 100 100
1890         
1891                         // Get scrollbar width
1892                         browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
1893         
1894                         // IE6/7 will oversize a width 100% element inside a scrolling element, to
1895                         // include the width of the scrollbar, while other browsers ensure the inner
1896                         // element is contained without forcing scrolling
1897                         browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
1898         
1899                         // In rtl text layout, some browsers (most, but not all) will place the
1900                         // scrollbar on the left, rather than the right.
1901                         browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
1902         
1903                         // IE8- don't provide height and width for getBoundingClientRect
1904                         browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
1905         
1906                         n.remove();
1907                 }
1908         
1909                 $.extend( settings.oBrowser, DataTable.__browser );
1910                 settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
1911         }
1912         
1913         
1914         /**
1915          * Array.prototype reduce[Right] method, used for browsers which don't support
1916          * JS 1.6. Done this way to reduce code size, since we iterate either way
1917          *  @param {object} settings dataTables settings object
1918          *  @memberof DataTable#oApi
1919          */
1920         function _fnReduce ( that, fn, init, start, end, inc )
1921         {
1922                 var
1923                         i = start,
1924                         value,
1925                         isSet = false;
1926         
1927                 if ( init !== undefined ) {
1928                         value = init;
1929                         isSet = true;
1930                 }
1931         
1932                 while ( i !== end ) {
1933                         if ( ! that.hasOwnProperty(i) ) {
1934                                 continue;
1935                         }
1936         
1937                         value = isSet ?
1938                                 fn( value, that[i], i, that ) :
1939                                 that[i];
1940         
1941                         isSet = true;
1942                         i += inc;
1943                 }
1944         
1945                 return value;
1946         }
1947         
1948         /**
1949          * Add a column to the list used for the table with default values
1950          *  @param {object} oSettings dataTables settings object
1951          *  @param {node} nTh The th element for this column
1952          *  @memberof DataTable#oApi
1953          */
1954         function _fnAddColumn( oSettings, nTh )
1955         {
1956                 // Add column to aoColumns array
1957                 var oDefaults = DataTable.defaults.column;
1958                 var iCol = oSettings.aoColumns.length;
1959                 var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
1960                         "nTh": nTh ? nTh : document.createElement('th'),
1961                         "sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
1962                         "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
1963                         "mData": oDefaults.mData ? oDefaults.mData : iCol,
1964                         idx: iCol
1965                 } );
1966                 oSettings.aoColumns.push( oCol );
1967         
1968                 // Add search object for column specific search. Note that the `searchCols[ iCol ]`
1969                 // passed into extend can be undefined. This allows the user to give a default
1970                 // with only some of the parameters defined, and also not give a default
1971                 var searchCols = oSettings.aoPreSearchCols;
1972                 searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
1973         
1974                 // Use the default column options function to initialise classes etc
1975                 _fnColumnOptions( oSettings, iCol, $(nTh).data() );
1976         }
1977         
1978         
1979         /**
1980          * Apply options for a column
1981          *  @param {object} oSettings dataTables settings object
1982          *  @param {int} iCol column index to consider
1983          *  @param {object} oOptions object with sType, bVisible and bSearchable etc
1984          *  @memberof DataTable#oApi
1985          */
1986         function _fnColumnOptions( oSettings, iCol, oOptions )
1987         {
1988                 var oCol = oSettings.aoColumns[ iCol ];
1989                 var oClasses = oSettings.oClasses;
1990                 var th = $(oCol.nTh);
1991         
1992                 // Try to get width information from the DOM. We can't get it from CSS
1993                 // as we'd need to parse the CSS stylesheet. `width` option can override
1994                 if ( ! oCol.sWidthOrig ) {
1995                         // Width attribute
1996                         oCol.sWidthOrig = th.attr('width') || null;
1997         
1998                         // Style attribute
1999                         var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
2000                         if ( t ) {
2001                                 oCol.sWidthOrig = t[1];
2002                         }
2003                 }
2004         
2005                 /* User specified column options */
2006                 if ( oOptions !== undefined && oOptions !== null )
2007                 {
2008                         // Backwards compatibility
2009                         _fnCompatCols( oOptions );
2010         
2011                         // Map camel case parameters to their Hungarian counterparts
2012                         _fnCamelToHungarian( DataTable.defaults.column, oOptions );
2013         
2014                         /* Backwards compatibility for mDataProp */
2015                         if ( oOptions.mDataProp !== undefined && !oOptions.mData )
2016                         {
2017                                 oOptions.mData = oOptions.mDataProp;
2018                         }
2019         
2020                         if ( oOptions.sType )
2021                         {
2022                                 oCol._sManualType = oOptions.sType;
2023                         }
2024         
2025                         // `class` is a reserved word in Javascript, so we need to provide
2026                         // the ability to use a valid name for the camel case input
2027                         if ( oOptions.className && ! oOptions.sClass )
2028                         {
2029                                 oOptions.sClass = oOptions.className;
2030                         }
2031         
2032                         $.extend( oCol, oOptions );
2033                         _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
2034         
2035                         /* iDataSort to be applied (backwards compatibility), but aDataSort will take
2036                          * priority if defined
2037                          */
2038                         if ( oOptions.iDataSort !== undefined )
2039                         {
2040                                 oCol.aDataSort = [ oOptions.iDataSort ];
2041                         }
2042                         _fnMap( oCol, oOptions, "aDataSort" );
2043                 }
2044         
2045                 /* Cache the data get and set functions for speed */
2046                 var mDataSrc = oCol.mData;
2047                 var mData = _fnGetObjectDataFn( mDataSrc );
2048                 var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
2049         
2050                 var attrTest = function( src ) {
2051                         return typeof src === 'string' && src.indexOf('@') !== -1;
2052                 };
2053                 oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
2054                         attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
2055                 );
2056                 oCol._setter = null;
2057         
2058                 oCol.fnGetData = function (rowData, type, meta) {
2059                         var innerData = mData( rowData, type, undefined, meta );
2060         
2061                         return mRender && type ?
2062                                 mRender( innerData, type, rowData, meta ) :
2063                                 innerData;
2064                 };
2065                 oCol.fnSetData = function ( rowData, val, meta ) {
2066                         return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
2067                 };
2068         
2069                 // Indicate if DataTables should read DOM data as an object or array
2070                 // Used in _fnGetRowElements
2071                 if ( typeof mDataSrc !== 'number' ) {
2072                         oSettings._rowReadObject = true;
2073                 }
2074         
2075                 /* Feature sorting overrides column specific when off */
2076                 if ( !oSettings.oFeatures.bSort )
2077                 {
2078                         oCol.bSortable = false;
2079                         th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
2080                 }
2081         
2082                 /* Check that the class assignment is correct for sorting */
2083                 var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
2084                 var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
2085                 if ( !oCol.bSortable || (!bAsc && !bDesc) )
2086                 {
2087                         oCol.sSortingClass = oClasses.sSortableNone;
2088                         oCol.sSortingClassJUI = "";
2089                 }
2090                 else if ( bAsc && !bDesc )
2091                 {
2092                         oCol.sSortingClass = oClasses.sSortableAsc;
2093                         oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
2094                 }
2095                 else if ( !bAsc && bDesc )
2096                 {
2097                         oCol.sSortingClass = oClasses.sSortableDesc;
2098                         oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
2099                 }
2100                 else
2101                 {
2102                         oCol.sSortingClass = oClasses.sSortable;
2103                         oCol.sSortingClassJUI = oClasses.sSortJUI;
2104                 }
2105         }
2106         
2107         
2108         /**
2109          * Adjust the table column widths for new data. Note: you would probably want to
2110          * do a redraw after calling this function!
2111          *  @param {object} settings dataTables settings object
2112          *  @memberof DataTable#oApi
2113          */
2114         function _fnAdjustColumnSizing ( settings )
2115         {
2116                 /* Not interested in doing column width calculation if auto-width is disabled */
2117                 if ( settings.oFeatures.bAutoWidth !== false )
2118                 {
2119                         var columns = settings.aoColumns;
2120         
2121                         _fnCalculateColumnWidths( settings );
2122                         for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
2123                         {
2124                                 columns[i].nTh.style.width = columns[i].sWidth;
2125                         }
2126                 }
2127         
2128                 var scroll = settings.oScroll;
2129                 if ( scroll.sY !== '' || scroll.sX !== '')
2130                 {
2131                         _fnScrollDraw( settings );
2132                 }
2133         
2134                 _fnCallbackFire( settings, null, 'column-sizing', [settings] );
2135         }
2136         
2137         
2138         /**
2139          * Covert the index of a visible column to the index in the data array (take account
2140          * of hidden columns)
2141          *  @param {object} oSettings dataTables settings object
2142          *  @param {int} iMatch Visible column index to lookup
2143          *  @returns {int} i the data index
2144          *  @memberof DataTable#oApi
2145          */
2146         function _fnVisibleToColumnIndex( oSettings, iMatch )
2147         {
2148                 var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2149         
2150                 return typeof aiVis[iMatch] === 'number' ?
2151                         aiVis[iMatch] :
2152                         null;
2153         }
2154         
2155         
2156         /**
2157          * Covert the index of an index in the data array and convert it to the visible
2158          *   column index (take account of hidden columns)
2159          *  @param {int} iMatch Column index to lookup
2160          *  @param {object} oSettings dataTables settings object
2161          *  @returns {int} i the data index
2162          *  @memberof DataTable#oApi
2163          */
2164         function _fnColumnIndexToVisible( oSettings, iMatch )
2165         {
2166                 var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2167                 var iPos = $.inArray( iMatch, aiVis );
2168         
2169                 return iPos !== -1 ? iPos : null;
2170         }
2171         
2172         
2173         /**
2174          * Get the number of visible columns
2175          *  @param {object} oSettings dataTables settings object
2176          *  @returns {int} i the number of visible columns
2177          *  @memberof DataTable#oApi
2178          */
2179         function _fnVisbleColumns( oSettings )
2180         {
2181                 var vis = 0;
2182         
2183                 // No reduce in IE8, use a loop for now
2184                 $.each( oSettings.aoColumns, function ( i, col ) {
2185                         if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
2186                                 vis++;
2187                         }
2188                 } );
2189         
2190                 return vis;
2191         }
2192         
2193         
2194         /**
2195          * Get an array of column indexes that match a given property
2196          *  @param {object} oSettings dataTables settings object
2197          *  @param {string} sParam Parameter in aoColumns to look for - typically
2198          *    bVisible or bSearchable
2199          *  @returns {array} Array of indexes with matched properties
2200          *  @memberof DataTable#oApi
2201          */
2202         function _fnGetColumns( oSettings, sParam )
2203         {
2204                 var a = [];
2205         
2206                 $.map( oSettings.aoColumns, function(val, i) {
2207                         if ( val[sParam] ) {
2208                                 a.push( i );
2209                         }
2210                 } );
2211         
2212                 return a;
2213         }
2214         
2215         
2216         /**
2217          * Calculate the 'type' of a column
2218          *  @param {object} settings dataTables settings object
2219          *  @memberof DataTable#oApi
2220          */
2221         function _fnColumnTypes ( settings )
2222         {
2223                 var columns = settings.aoColumns;
2224                 var data = settings.aoData;
2225                 var types = DataTable.ext.type.detect;
2226                 var i, ien, j, jen, k, ken;
2227                 var col, cell, detectedType, cache;
2228         
2229                 // For each column, spin over the 
2230                 for ( i=0, ien=columns.length ; i<ien ; i++ ) {
2231                         col = columns[i];
2232                         cache = [];
2233         
2234                         if ( ! col.sType && col._sManualType ) {
2235                                 col.sType = col._sManualType;
2236                         }
2237                         else if ( ! col.sType ) {
2238                                 for ( j=0, jen=types.length ; j<jen ; j++ ) {
2239                                         for ( k=0, ken=data.length ; k<ken ; k++ ) {
2240                                                 // Use a cache array so we only need to get the type data
2241                                                 // from the formatter once (when using multiple detectors)
2242                                                 if ( cache[k] === undefined ) {
2243                                                         cache[k] = _fnGetCellData( settings, k, i, 'type' );
2244                                                 }
2245         
2246                                                 detectedType = types[j]( cache[k], settings );
2247         
2248                                                 // If null, then this type can't apply to this column, so
2249                                                 // rather than testing all cells, break out. There is an
2250                                                 // exception for the last type which is `html`. We need to
2251                                                 // scan all rows since it is possible to mix string and HTML
2252                                                 // types
2253                                                 if ( ! detectedType && j !== types.length-1 ) {
2254                                                         break;
2255                                                 }
2256         
2257                                                 // Only a single match is needed for html type since it is
2258                                                 // bottom of the pile and very similar to string
2259                                                 if ( detectedType === 'html' ) {
2260                                                         break;
2261                                                 }
2262                                         }
2263         
2264                                         // Type is valid for all data points in the column - use this
2265                                         // type
2266                                         if ( detectedType ) {
2267                                                 col.sType = detectedType;
2268                                                 break;
2269                                         }
2270                                 }
2271         
2272                                 // Fall back - if no type was detected, always use string
2273                                 if ( ! col.sType ) {
2274                                         col.sType = 'string';
2275                                 }
2276                         }
2277                 }
2278         }
2279         
2280         
2281         /**
2282          * Take the column definitions and static columns arrays and calculate how
2283          * they relate to column indexes. The callback function will then apply the
2284          * definition found for a column to a suitable configuration object.
2285          *  @param {object} oSettings dataTables settings object
2286          *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
2287          *  @param {array} aoCols The aoColumns array that defines columns individually
2288          *  @param {function} fn Callback function - takes two parameters, the calculated
2289          *    column index and the definition for that column.
2290          *  @memberof DataTable#oApi
2291          */
2292         function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
2293         {
2294                 var i, iLen, j, jLen, k, kLen, def;
2295                 var columns = oSettings.aoColumns;
2296         
2297                 // Column definitions with aTargets
2298                 if ( aoColDefs )
2299                 {
2300                         /* Loop over the definitions array - loop in reverse so first instance has priority */
2301                         for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
2302                         {
2303                                 def = aoColDefs[i];
2304         
2305                                 /* Each definition can target multiple columns, as it is an array */
2306                                 var aTargets = def.targets !== undefined ?
2307                                         def.targets :
2308                                         def.aTargets;
2309         
2310                                 if ( ! $.isArray( aTargets ) )
2311                                 {
2312                                         aTargets = [ aTargets ];
2313                                 }
2314         
2315                                 for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
2316                                 {
2317                                         if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
2318                                         {
2319                                                 /* Add columns that we don't yet know about */
2320                                                 while( columns.length <= aTargets[j] )
2321                                                 {
2322                                                         _fnAddColumn( oSettings );
2323                                                 }
2324         
2325                                                 /* Integer, basic index */
2326                                                 fn( aTargets[j], def );
2327                                         }
2328                                         else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
2329                                         {
2330                                                 /* Negative integer, right to left column counting */
2331                                                 fn( columns.length+aTargets[j], def );
2332                                         }
2333                                         else if ( typeof aTargets[j] === 'string' )
2334                                         {
2335                                                 /* Class name matching on TH element */
2336                                                 for ( k=0, kLen=columns.length ; k<kLen ; k++ )
2337                                                 {
2338                                                         if ( aTargets[j] == "_all" ||
2339                                                              $(columns[k].nTh).hasClass( aTargets[j] ) )
2340                                                         {
2341                                                                 fn( k, def );
2342                                                         }
2343                                                 }
2344                                         }
2345                                 }
2346                         }
2347                 }
2348         
2349                 // Statically defined columns array
2350                 if ( aoCols )
2351                 {
2352                         for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
2353                         {
2354                                 fn( i, aoCols[i] );
2355                         }
2356                 }
2357         }
2358         
2359         /**
2360          * Add a data array to the table, creating DOM node etc. This is the parallel to
2361          * _fnGatherData, but for adding rows from a Javascript source, rather than a
2362          * DOM source.
2363          *  @param {object} oSettings dataTables settings object
2364          *  @param {array} aData data array to be added
2365          *  @param {node} [nTr] TR element to add to the table - optional. If not given,
2366          *    DataTables will create a row automatically
2367          *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
2368          *    if nTr is.
2369          *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
2370          *  @memberof DataTable#oApi
2371          */
2372         function _fnAddData ( oSettings, aDataIn, nTr, anTds )
2373         {
2374                 /* Create the object for storing information about this new row */
2375                 var iRow = oSettings.aoData.length;
2376                 var oData = $.extend( true, {}, DataTable.models.oRow, {
2377                         src: nTr ? 'dom' : 'data',
2378                         idx: iRow
2379                 } );
2380         
2381                 oData._aData = aDataIn;
2382                 oSettings.aoData.push( oData );
2383         
2384                 /* Create the cells */
2385                 var nTd, sThisType;
2386                 var columns = oSettings.aoColumns;
2387         
2388                 // Invalidate the column types as the new data needs to be revalidated
2389                 for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
2390                 {
2391                         columns[i].sType = null;
2392                 }
2393         
2394                 /* Add to the display array */
2395                 oSettings.aiDisplayMaster.push( iRow );
2396         
2397                 var id = oSettings.rowIdFn( aDataIn );
2398                 if ( id !== undefined ) {
2399                         oSettings.aIds[ id ] = oData;
2400                 }
2401         
2402                 /* Create the DOM information, or register it if already present */
2403                 if ( nTr || ! oSettings.oFeatures.bDeferRender )
2404                 {
2405                         _fnCreateTr( oSettings, iRow, nTr, anTds );
2406                 }
2407         
2408                 return iRow;
2409         }
2410         
2411         
2412         /**
2413          * Add one or more TR elements to the table. Generally we'd expect to
2414          * use this for reading data from a DOM sourced table, but it could be
2415          * used for an TR element. Note that if a TR is given, it is used (i.e.
2416          * it is not cloned).
2417          *  @param {object} settings dataTables settings object
2418          *  @param {array|node|jQuery} trs The TR element(s) to add to the table
2419          *  @returns {array} Array of indexes for the added rows
2420          *  @memberof DataTable#oApi
2421          */
2422         function _fnAddTr( settings, trs )
2423         {
2424                 var row;
2425         
2426                 // Allow an individual node to be passed in
2427                 if ( ! (trs instanceof $) ) {
2428                         trs = $(trs);
2429                 }
2430         
2431                 return trs.map( function (i, el) {
2432                         row = _fnGetRowElements( settings, el );
2433                         return _fnAddData( settings, row.data, el, row.cells );
2434                 } );
2435         }
2436         
2437         
2438         /**
2439          * Take a TR element and convert it to an index in aoData
2440          *  @param {object} oSettings dataTables settings object
2441          *  @param {node} n the TR element to find
2442          *  @returns {int} index if the node is found, null if not
2443          *  @memberof DataTable#oApi
2444          */
2445         function _fnNodeToDataIndex( oSettings, n )
2446         {
2447                 return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
2448         }
2449         
2450         
2451         /**
2452          * Take a TD element and convert it into a column data index (not the visible index)
2453          *  @param {object} oSettings dataTables settings object
2454          *  @param {int} iRow The row number the TD/TH can be found in
2455          *  @param {node} n The TD/TH element to find
2456          *  @returns {int} index if the node is found, -1 if not
2457          *  @memberof DataTable#oApi
2458          */
2459         function _fnNodeToColumnIndex( oSettings, iRow, n )
2460         {
2461                 return $.inArray( n, oSettings.aoData[ iRow ].anCells );
2462         }
2463         
2464         
2465         /**
2466          * Get the data for a given cell from the internal cache, taking into account data mapping
2467          *  @param {object} settings dataTables settings object
2468          *  @param {int} rowIdx aoData row id
2469          *  @param {int} colIdx Column index
2470          *  @param {string} type data get type ('display', 'type' 'filter' 'sort')
2471          *  @returns {*} Cell data
2472          *  @memberof DataTable#oApi
2473          */
2474         function _fnGetCellData( settings, rowIdx, colIdx, type )
2475         {
2476                 var draw           = settings.iDraw;
2477                 var col            = settings.aoColumns[colIdx];
2478                 var rowData        = settings.aoData[rowIdx]._aData;
2479                 var defaultContent = col.sDefaultContent;
2480                 var cellData       = col.fnGetData( rowData, type, {
2481                         settings: settings,
2482                         row:      rowIdx,
2483                         col:      colIdx
2484                 } );
2485         
2486                 if ( cellData === undefined ) {
2487                         if ( settings.iDrawError != draw && defaultContent === null ) {
2488                                 _fnLog( settings, 0, "Requested unknown parameter "+
2489                                         (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
2490                                         " for row "+rowIdx+", column "+colIdx, 4 );
2491                                 settings.iDrawError = draw;
2492                         }
2493                         return defaultContent;
2494                 }
2495         
2496                 // When the data source is null and a specific data type is requested (i.e.
2497                 // not the original data), we can use default column data
2498                 if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
2499                         cellData = defaultContent;
2500                 }
2501                 else if ( typeof cellData === 'function' ) {
2502                         // If the data source is a function, then we run it and use the return,
2503                         // executing in the scope of the data object (for instances)
2504                         return cellData.call( rowData );
2505                 }
2506         
2507                 if ( cellData === null && type == 'display' ) {
2508                         return '';
2509                 }
2510                 return cellData;
2511         }
2512         
2513         
2514         /**
2515          * Set the value for a specific cell, into the internal data cache
2516          *  @param {object} settings dataTables settings object
2517          *  @param {int} rowIdx aoData row id
2518          *  @param {int} colIdx Column index
2519          *  @param {*} val Value to set
2520          *  @memberof DataTable#oApi
2521          */
2522         function _fnSetCellData( settings, rowIdx, colIdx, val )
2523         {
2524                 var col     = settings.aoColumns[colIdx];
2525                 var rowData = settings.aoData[rowIdx]._aData;
2526         
2527                 col.fnSetData( rowData, val, {
2528                         settings: settings,
2529                         row:      rowIdx,
2530                         col:      colIdx
2531                 }  );
2532         }
2533         
2534         
2535         // Private variable that is used to match action syntax in the data property object
2536         var __reArray = /\[.*?\]$/;
2537         var __reFn = /\(\)$/;
2538         
2539         /**
2540          * Split string on periods, taking into account escaped periods
2541          * @param  {string} str String to split
2542          * @return {array} Split string
2543          */
2544         function _fnSplitObjNotation( str )
2545         {
2546                 return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
2547                         return s.replace(/\\./g, '.');
2548                 } );
2549         }
2550         
2551         
2552         /**
2553          * Return a function that can be used to get data from a source object, taking
2554          * into account the ability to use nested objects as a source
2555          *  @param {string|int|function} mSource The data source for the object
2556          *  @returns {function} Data get function
2557          *  @memberof DataTable#oApi
2558          */
2559         function _fnGetObjectDataFn( mSource )
2560         {
2561                 if ( $.isPlainObject( mSource ) )
2562                 {
2563                         /* Build an object of get functions, and wrap them in a single call */
2564                         var o = {};
2565                         $.each( mSource, function (key, val) {
2566                                 if ( val ) {
2567                                         o[key] = _fnGetObjectDataFn( val );
2568                                 }
2569                         } );
2570         
2571                         return function (data, type, row, meta) {
2572                                 var t = o[type] || o._;
2573                                 return t !== undefined ?
2574                                         t(data, type, row, meta) :
2575                                         data;
2576                         };
2577                 }
2578                 else if ( mSource === null )
2579                 {
2580                         /* Give an empty string for rendering / sorting etc */
2581                         return function (data) { // type, row and meta also passed, but not used
2582                                 return data;
2583                         };
2584                 }
2585                 else if ( typeof mSource === 'function' )
2586                 {
2587                         return function (data, type, row, meta) {
2588                                 return mSource( data, type, row, meta );
2589                         };
2590                 }
2591                 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2592                               mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2593                 {
2594                         /* If there is a . in the source string then the data source is in a
2595                          * nested object so we loop over the data for each level to get the next
2596                          * level down. On each loop we test for undefined, and if found immediately
2597                          * return. This allows entire objects to be missing and sDefaultContent to
2598                          * be used if defined, rather than throwing an error
2599                          */
2600                         var fetchData = function (data, type, src) {
2601                                 var arrayNotation, funcNotation, out, innerSrc;
2602         
2603                                 if ( src !== "" )
2604                                 {
2605                                         var a = _fnSplitObjNotation( src );
2606         
2607                                         for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2608                                         {
2609                                                 // Check if we are dealing with special notation
2610                                                 arrayNotation = a[i].match(__reArray);
2611                                                 funcNotation = a[i].match(__reFn);
2612         
2613                                                 if ( arrayNotation )
2614                                                 {
2615                                                         // Array notation
2616                                                         a[i] = a[i].replace(__reArray, '');
2617         
2618                                                         // Condition allows simply [] to be passed in
2619                                                         if ( a[i] !== "" ) {
2620                                                                 data = data[ a[i] ];
2621                                                         }
2622                                                         out = [];
2623         
2624                                                         // Get the remainder of the nested object to get
2625                                                         a.splice( 0, i+1 );
2626                                                         innerSrc = a.join('.');
2627         
2628                                                         // Traverse each entry in the array getting the properties requested
2629                                                         if ( $.isArray( data ) ) {
2630                                                                 for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
2631                                                                         out.push( fetchData( data[j], type, innerSrc ) );
2632                                                                 }
2633                                                         }
2634         
2635                                                         // If a string is given in between the array notation indicators, that
2636                                                         // is used to join the strings together, otherwise an array is returned
2637                                                         var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
2638                                                         data = (join==="") ? out : out.join(join);
2639         
2640                                                         // The inner call to fetchData has already traversed through the remainder
2641                                                         // of the source requested, so we exit from the loop
2642                                                         break;
2643                                                 }
2644                                                 else if ( funcNotation )
2645                                                 {
2646                                                         // Function call
2647                                                         a[i] = a[i].replace(__reFn, '');
2648                                                         data = data[ a[i] ]();
2649                                                         continue;
2650                                                 }
2651         
2652                                                 if ( data === null || data[ a[i] ] === undefined )
2653                                                 {
2654                                                         return undefined;
2655                                                 }
2656                                                 data = data[ a[i] ];
2657                                         }
2658                                 }
2659         
2660                                 return data;
2661                         };
2662         
2663                         return function (data, type) { // row and meta also passed, but not used
2664                                 return fetchData( data, type, mSource );
2665                         };
2666                 }
2667                 else
2668                 {
2669                         /* Array or flat object mapping */
2670                         return function (data, type) { // row and meta also passed, but not used
2671                                 return data[mSource];
2672                         };
2673                 }
2674         }
2675         
2676         
2677         /**
2678          * Return a function that can be used to set data from a source object, taking
2679          * into account the ability to use nested objects as a source
2680          *  @param {string|int|function} mSource The data source for the object
2681          *  @returns {function} Data set function
2682          *  @memberof DataTable#oApi
2683          */
2684         function _fnSetObjectDataFn( mSource )
2685         {
2686                 if ( $.isPlainObject( mSource ) )
2687                 {
2688                         /* Unlike get, only the underscore (global) option is used for for
2689                          * setting data since we don't know the type here. This is why an object
2690                          * option is not documented for `mData` (which is read/write), but it is
2691                          * for `mRender` which is read only.
2692                          */
2693                         return _fnSetObjectDataFn( mSource._ );
2694                 }
2695                 else if ( mSource === null )
2696                 {
2697                         /* Nothing to do when the data source is null */
2698                         return function () {};
2699                 }
2700                 else if ( typeof mSource === 'function' )
2701                 {
2702                         return function (data, val, meta) {
2703                                 mSource( data, 'set', val, meta );
2704                         };
2705                 }
2706                 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2707                               mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2708                 {
2709                         /* Like the get, we need to get data from a nested object */
2710                         var setData = function (data, val, src) {
2711                                 var a = _fnSplitObjNotation( src ), b;
2712                                 var aLast = a[a.length-1];
2713                                 var arrayNotation, funcNotation, o, innerSrc;
2714         
2715                                 for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
2716                                 {
2717                                         // Check if we are dealing with an array notation request
2718                                         arrayNotation = a[i].match(__reArray);
2719                                         funcNotation = a[i].match(__reFn);
2720         
2721                                         if ( arrayNotation )
2722                                         {
2723                                                 a[i] = a[i].replace(__reArray, '');
2724                                                 data[ a[i] ] = [];
2725         
2726                                                 // Get the remainder of the nested object to set so we can recurse
2727                                                 b = a.slice();
2728                                                 b.splice( 0, i+1 );
2729                                                 innerSrc = b.join('.');
2730         
2731                                                 // Traverse each entry in the array setting the properties requested
2732                                                 if ( $.isArray( val ) )
2733                                                 {
2734                                                         for ( var j=0, jLen=val.length ; j<jLen ; j++ )
2735                                                         {
2736                                                                 o = {};
2737                                                                 setData( o, val[j], innerSrc );
2738                                                                 data[ a[i] ].push( o );
2739                                                         }
2740                                                 }
2741                                                 else
2742                                                 {
2743                                                         // We've been asked to save data to an array, but it
2744                                                         // isn't array data to be saved. Best that can be done
2745                                                         // is to just save the value.
2746                                                         data[ a[i] ] = val;
2747                                                 }
2748         
2749                                                 // The inner call to setData has already traversed through the remainder
2750                                                 // of the source and has set the data, thus we can exit here
2751                                                 return;
2752                                         }
2753                                         else if ( funcNotation )
2754                                         {
2755                                                 // Function call
2756                                                 a[i] = a[i].replace(__reFn, '');
2757                                                 data = data[ a[i] ]( val );
2758                                         }
2759         
2760                                         // If the nested object doesn't currently exist - since we are
2761                                         // trying to set the value - create it
2762                                         if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
2763                                         {
2764                                                 data[ a[i] ] = {};
2765                                         }
2766                                         data = data[ a[i] ];
2767                                 }
2768         
2769                                 // Last item in the input - i.e, the actual set
2770                                 if ( aLast.match(__reFn ) )
2771                                 {
2772                                         // Function call
2773                                         data = data[ aLast.replace(__reFn, '') ]( val );
2774                                 }
2775                                 else
2776                                 {
2777                                         // If array notation is used, we just want to strip it and use the property name
2778                                         // and assign the value. If it isn't used, then we get the result we want anyway
2779                                         data[ aLast.replace(__reArray, '') ] = val;
2780                                 }
2781                         };
2782         
2783                         return function (data, val) { // meta is also passed in, but not used
2784                                 return setData( data, val, mSource );
2785                         };
2786                 }
2787                 else
2788                 {
2789                         /* Array or flat object mapping */
2790                         return function (data, val) { // meta is also passed in, but not used
2791                                 data[mSource] = val;
2792                         };
2793                 }
2794         }
2795         
2796         
2797         /**
2798          * Return an array with the full table data
2799          *  @param {object} oSettings dataTables settings object
2800          *  @returns array {array} aData Master data array
2801          *  @memberof DataTable#oApi
2802          */
2803         function _fnGetDataMaster ( settings )
2804         {
2805                 return _pluck( settings.aoData, '_aData' );
2806         }
2807         
2808         
2809         /**
2810          * Nuke the table
2811          *  @param {object} oSettings dataTables settings object
2812          *  @memberof DataTable#oApi
2813          */
2814         function _fnClearTable( settings )
2815         {
2816                 settings.aoData.length = 0;
2817                 settings.aiDisplayMaster.length = 0;
2818                 settings.aiDisplay.length = 0;
2819                 settings.aIds = {};
2820         }
2821         
2822         
2823          /**
2824          * Take an array of integers (index array) and remove a target integer (value - not
2825          * the key!)
2826          *  @param {array} a Index array to target
2827          *  @param {int} iTarget value to find
2828          *  @memberof DataTable#oApi
2829          */
2830         function _fnDeleteIndex( a, iTarget, splice )
2831         {
2832                 var iTargetIndex = -1;
2833         
2834                 for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2835                 {
2836                         if ( a[i] == iTarget )
2837                         {
2838                                 iTargetIndex = i;
2839                         }
2840                         else if ( a[i] > iTarget )
2841                         {
2842                                 a[i]--;
2843                         }
2844                 }
2845         
2846                 if ( iTargetIndex != -1 && splice === undefined )
2847                 {
2848                         a.splice( iTargetIndex, 1 );
2849                 }
2850         }
2851         
2852         
2853         /**
2854          * Mark cached data as invalid such that a re-read of the data will occur when
2855          * the cached data is next requested. Also update from the data source object.
2856          *
2857          * @param {object} settings DataTables settings object
2858          * @param {int}    rowIdx   Row index to invalidate
2859          * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
2860          *     or 'data'
2861          * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
2862          *     row will be invalidated
2863          * @memberof DataTable#oApi
2864          *
2865          * @todo For the modularisation of v1.11 this will need to become a callback, so
2866          *   the sort and filter methods can subscribe to it. That will required
2867          *   initialisation options for sorting, which is why it is not already baked in
2868          */
2869         function _fnInvalidate( settings, rowIdx, src, colIdx )
2870         {
2871                 var row = settings.aoData[ rowIdx ];
2872                 var i, ien;
2873                 var cellWrite = function ( cell, col ) {
2874                         // This is very frustrating, but in IE if you just write directly
2875                         // to innerHTML, and elements that are overwritten are GC'ed,
2876                         // even if there is a reference to them elsewhere
2877                         while ( cell.childNodes.length ) {
2878                                 cell.removeChild( cell.firstChild );
2879                         }
2880         
2881                         cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
2882                 };
2883         
2884                 // Are we reading last data from DOM or the data object?
2885                 if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
2886                         // Read the data from the DOM
2887                         row._aData = _fnGetRowElements(
2888                                         settings, row, colIdx, colIdx === undefined ? undefined : row._aData
2889                                 )
2890                                 .data;
2891                 }
2892                 else {
2893                         // Reading from data object, update the DOM
2894                         var cells = row.anCells;
2895         
2896                         if ( cells ) {
2897                                 if ( colIdx !== undefined ) {
2898                                         cellWrite( cells[colIdx], colIdx );
2899                                 }
2900                                 else {
2901                                         for ( i=0, ien=cells.length ; i<ien ; i++ ) {
2902                                                 cellWrite( cells[i], i );
2903                                         }
2904                                 }
2905                         }
2906                 }
2907         
2908                 // For both row and cell invalidation, the cached data for sorting and
2909                 // filtering is nulled out
2910                 row._aSortData = null;
2911                 row._aFilterData = null;
2912         
2913                 // Invalidate the type for a specific column (if given) or all columns since
2914                 // the data might have changed
2915                 var cols = settings.aoColumns;
2916                 if ( colIdx !== undefined ) {
2917                         cols[ colIdx ].sType = null;
2918                 }
2919                 else {
2920                         for ( i=0, ien=cols.length ; i<ien ; i++ ) {
2921                                 cols[i].sType = null;
2922                         }
2923         
2924                         // Update DataTables special `DT_*` attributes for the row
2925                         _fnRowAttributes( settings, row );
2926                 }
2927         }
2928         
2929         
2930         /**
2931          * Build a data source object from an HTML row, reading the contents of the
2932          * cells that are in the row.
2933          *
2934          * @param {object} settings DataTables settings object
2935          * @param {node|object} TR element from which to read data or existing row
2936          *   object from which to re-read the data from the cells
2937          * @param {int} [colIdx] Optional column index
2938          * @param {array|object} [d] Data source object. If `colIdx` is given then this
2939          *   parameter should also be given and will be used to write the data into.
2940          *   Only the column in question will be written
2941          * @returns {object} Object with two parameters: `data` the data read, in
2942          *   document order, and `cells` and array of nodes (they can be useful to the
2943          *   caller, so rather than needing a second traversal to get them, just return
2944          *   them from here).
2945          * @memberof DataTable#oApi
2946          */
2947         function _fnGetRowElements( settings, row, colIdx, d )
2948         {
2949                 var
2950                         tds = [],
2951                         td = row.firstChild,
2952                         name, col, o, i=0, contents,
2953                         columns = settings.aoColumns,
2954                         objectRead = settings._rowReadObject;
2955         
2956                 // Allow the data object to be passed in, or construct
2957                 d = d !== undefined ?
2958                         d :
2959                         objectRead ?
2960                                 {} :
2961                                 [];
2962         
2963                 var attr = function ( str, td  ) {
2964                         if ( typeof str === 'string' ) {
2965                                 var idx = str.indexOf('@');
2966         
2967                                 if ( idx !== -1 ) {
2968                                         var attr = str.substring( idx+1 );
2969                                         var setter = _fnSetObjectDataFn( str );
2970                                         setter( d, td.getAttribute( attr ) );
2971                                 }
2972                         }
2973                 };
2974         
2975                 // Read data from a cell and store into the data object
2976                 var cellProcess = function ( cell ) {
2977                         if ( colIdx === undefined || colIdx === i ) {
2978                                 col = columns[i];
2979                                 contents = $.trim(cell.innerHTML);
2980         
2981                                 if ( col && col._bAttrSrc ) {
2982                                         var setter = _fnSetObjectDataFn( col.mData._ );
2983                                         setter( d, contents );
2984         
2985                                         attr( col.mData.sort, cell );
2986                                         attr( col.mData.type, cell );
2987                                         attr( col.mData.filter, cell );
2988                                 }
2989                                 else {
2990                                         // Depending on the `data` option for the columns the data can
2991                                         // be read to either an object or an array.
2992                                         if ( objectRead ) {
2993                                                 if ( ! col._setter ) {
2994                                                         // Cache the setter function
2995                                                         col._setter = _fnSetObjectDataFn( col.mData );
2996                                                 }
2997                                                 col._setter( d, contents );
2998                                         }
2999                                         else {
3000                                                 d[i] = contents;
3001                                         }
3002                                 }
3003                         }
3004         
3005                         i++;
3006                 };
3007         
3008                 if ( td ) {
3009                         // `tr` element was passed in
3010                         while ( td ) {
3011                                 name = td.nodeName.toUpperCase();
3012         
3013                                 if ( name == "TD" || name == "TH" ) {
3014                                         cellProcess( td );
3015                                         tds.push( td );
3016                                 }
3017         
3018                                 td = td.nextSibling;
3019                         }
3020                 }
3021                 else {
3022                         // Existing row object passed in
3023                         tds = row.anCells;
3024         
3025                         for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
3026                                 cellProcess( tds[j] );
3027                         }
3028                 }
3029         
3030                 // Read the ID from the DOM if present
3031                 var rowNode = row.firstChild ? row : row.nTr;
3032         
3033                 if ( rowNode ) {
3034                         var id = rowNode.getAttribute( 'id' );
3035         
3036                         if ( id ) {
3037                                 _fnSetObjectDataFn( settings.rowId )( d, id );
3038                         }
3039                 }
3040         
3041                 return {
3042                         data: d,
3043                         cells: tds
3044                 };
3045         }
3046         /**
3047          * Create a new TR element (and it's TD children) for a row
3048          *  @param {object} oSettings dataTables settings object
3049          *  @param {int} iRow Row to consider
3050          *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
3051          *    DataTables will create a row automatically
3052          *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
3053          *    if nTr is.
3054          *  @memberof DataTable#oApi
3055          */
3056         function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
3057         {
3058                 var
3059                         row = oSettings.aoData[iRow],
3060                         rowData = row._aData,
3061                         cells = [],
3062                         nTr, nTd, oCol,
3063                         i, iLen;
3064         
3065                 if ( row.nTr === null )
3066                 {
3067                         nTr = nTrIn || document.createElement('tr');
3068         
3069                         row.nTr = nTr;
3070                         row.anCells = cells;
3071         
3072                         /* Use a private property on the node to allow reserve mapping from the node
3073                          * to the aoData array for fast look up
3074                          */
3075                         nTr._DT_RowIndex = iRow;
3076         
3077                         /* Special parameters can be given by the data source to be used on the row */
3078                         _fnRowAttributes( oSettings, row );
3079         
3080                         /* Process each column */
3081                         for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
3082                         {
3083                                 oCol = oSettings.aoColumns[i];
3084         
3085                                 nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
3086                                 nTd._DT_CellIndex = {
3087                                         row: iRow,
3088                                         column: i
3089                                 };
3090                                 
3091                                 cells.push( nTd );
3092         
3093                                 // Need to create the HTML if new, or if a rendering function is defined
3094                                 if ( (!nTrIn || oCol.mRender || oCol.mData !== i) &&
3095                                          (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
3096                                 ) {
3097                                         nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
3098                                 }
3099         
3100                                 /* Add user defined class */
3101                                 if ( oCol.sClass )
3102                                 {
3103                                         nTd.className += ' '+oCol.sClass;
3104                                 }
3105         
3106                                 // Visibility - add or remove as required
3107                                 if ( oCol.bVisible && ! nTrIn )
3108                                 {
3109                                         nTr.appendChild( nTd );
3110                                 }
3111                                 else if ( ! oCol.bVisible && nTrIn )
3112                                 {
3113                                         nTd.parentNode.removeChild( nTd );
3114                                 }
3115         
3116                                 if ( oCol.fnCreatedCell )
3117                                 {
3118                                         oCol.fnCreatedCell.call( oSettings.oInstance,
3119                                                 nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
3120                                         );
3121                                 }
3122                         }
3123         
3124                         _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
3125                 }
3126         
3127                 // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
3128                 // and deployed
3129                 row.nTr.setAttribute( 'role', 'row' );
3130         }
3131         
3132         
3133         /**
3134          * Add attributes to a row based on the special `DT_*` parameters in a data
3135          * source object.
3136          *  @param {object} settings DataTables settings object
3137          *  @param {object} DataTables row object for the row to be modified
3138          *  @memberof DataTable#oApi
3139          */
3140         function _fnRowAttributes( settings, row )
3141         {
3142                 var tr = row.nTr;
3143                 var data = row._aData;
3144         
3145                 if ( tr ) {
3146                         var id = settings.rowIdFn( data );
3147         
3148                         if ( id ) {
3149                                 tr.id = id;
3150                         }
3151         
3152                         if ( data.DT_RowClass ) {
3153                                 // Remove any classes added by DT_RowClass before
3154                                 var a = data.DT_RowClass.split(' ');
3155                                 row.__rowc = row.__rowc ?
3156                                         _unique( row.__rowc.concat( a ) ) :
3157                                         a;
3158         
3159                                 $(tr)
3160                                         .removeClass( row.__rowc.join(' ') )
3161                                         .addClass( data.DT_RowClass );
3162                         }
3163         
3164                         if ( data.DT_RowAttr ) {
3165                                 $(tr).attr( data.DT_RowAttr );
3166                         }
3167         
3168                         if ( data.DT_RowData ) {
3169                                 $(tr).data( data.DT_RowData );
3170                         }
3171                 }
3172         }
3173         
3174         
3175         /**
3176          * Create the HTML header for the table
3177          *  @param {object} oSettings dataTables settings object
3178          *  @memberof DataTable#oApi
3179          */
3180         function _fnBuildHead( oSettings )
3181         {
3182                 var i, ien, cell, row, column;
3183                 var thead = oSettings.nTHead;
3184                 var tfoot = oSettings.nTFoot;
3185                 var createHeader = $('th, td', thead).length === 0;
3186                 var classes = oSettings.oClasses;
3187                 var columns = oSettings.aoColumns;
3188         
3189                 if ( createHeader ) {
3190                         row = $('<tr/>').appendTo( thead );
3191                 }
3192         
3193                 for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3194                         column = columns[i];
3195                         cell = $( column.nTh ).addClass( column.sClass );
3196         
3197                         if ( createHeader ) {
3198                                 cell.appendTo( row );
3199                         }
3200         
3201                         // 1.11 move into sorting
3202                         if ( oSettings.oFeatures.bSort ) {
3203                                 cell.addClass( column.sSortingClass );
3204         
3205                                 if ( column.bSortable !== false ) {
3206                                         cell
3207                                                 .attr( 'tabindex', oSettings.iTabIndex )
3208                                                 .attr( 'aria-controls', oSettings.sTableId );
3209         
3210                                         _fnSortAttachListener( oSettings, column.nTh, i );
3211                                 }
3212                         }
3213         
3214                         if ( column.sTitle != cell[0].innerHTML ) {
3215                                 cell.html( column.sTitle );
3216                         }
3217         
3218                         _fnRenderer( oSettings, 'header' )(
3219                                 oSettings, cell, column, classes
3220                         );
3221                 }
3222         
3223                 if ( createHeader ) {
3224                         _fnDetectHeader( oSettings.aoHeader, thead );
3225                 }
3226                 
3227                 /* ARIA role for the rows */
3228                 $(thead).find('>tr').attr('role', 'row');
3229         
3230                 /* Deal with the footer - add classes if required */
3231                 $(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
3232                 $(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
3233         
3234                 // Cache the footer cells. Note that we only take the cells from the first
3235                 // row in the footer. If there is more than one row the user wants to
3236                 // interact with, they need to use the table().foot() method. Note also this
3237                 // allows cells to be used for multiple columns using colspan
3238                 if ( tfoot !== null ) {
3239                         var cells = oSettings.aoFooter[0];
3240         
3241                         for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3242                                 column = columns[i];
3243                                 column.nTf = cells[i].cell;
3244         
3245                                 if ( column.sClass ) {
3246                                         $(column.nTf).addClass( column.sClass );
3247                                 }
3248                         }
3249                 }
3250         }
3251         
3252         
3253         /**
3254          * Draw the header (or footer) element based on the column visibility states. The
3255          * methodology here is to use the layout array from _fnDetectHeader, modified for
3256          * the instantaneous column visibility, to construct the new layout. The grid is
3257          * traversed over cell at a time in a rows x columns grid fashion, although each
3258          * cell insert can cover multiple elements in the grid - which is tracks using the
3259          * aApplied array. Cell inserts in the grid will only occur where there isn't
3260          * already a cell in that position.
3261          *  @param {object} oSettings dataTables settings object
3262          *  @param array {objects} aoSource Layout array from _fnDetectHeader
3263          *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3264          *  @memberof DataTable#oApi
3265          */
3266         function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
3267         {
3268                 var i, iLen, j, jLen, k, kLen, n, nLocalTr;
3269                 var aoLocal = [];
3270                 var aApplied = [];
3271                 var iColumns = oSettings.aoColumns.length;
3272                 var iRowspan, iColspan;
3273         
3274                 if ( ! aoSource )
3275                 {
3276                         return;
3277                 }
3278         
3279                 if (  bIncludeHidden === undefined )
3280                 {
3281                         bIncludeHidden = false;
3282                 }
3283         
3284                 /* Make a copy of the master layout array, but without the visible columns in it */
3285                 for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
3286                 {
3287                         aoLocal[i] = aoSource[i].slice();
3288                         aoLocal[i].nTr = aoSource[i].nTr;
3289         
3290                         /* Remove any columns which are currently hidden */
3291                         for ( j=iColumns-1 ; j>=0 ; j-- )
3292                         {
3293                                 if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
3294                                 {
3295                                         aoLocal[i].splice( j, 1 );
3296                                 }
3297                         }
3298         
3299                         /* Prep the applied array - it needs an element for each row */
3300                         aApplied.push( [] );
3301                 }
3302         
3303                 for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
3304                 {
3305                         nLocalTr = aoLocal[i].nTr;
3306         
3307                         /* All cells are going to be replaced, so empty out the row */
3308                         if ( nLocalTr )
3309                         {
3310                                 while( (n = nLocalTr.firstChild) )
3311                                 {
3312                                         nLocalTr.removeChild( n );
3313                                 }
3314                         }
3315         
3316                         for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
3317                         {
3318                                 iRowspan = 1;
3319                                 iColspan = 1;
3320         
3321                                 /* Check to see if there is already a cell (row/colspan) covering our target
3322                                  * insert point. If there is, then there is nothing to do.
3323                                  */
3324                                 if ( aApplied[i][j] === undefined )
3325                                 {
3326                                         nLocalTr.appendChild( aoLocal[i][j].cell );
3327                                         aApplied[i][j] = 1;
3328         
3329                                         /* Expand the cell to cover as many rows as needed */
3330                                         while ( aoLocal[i+iRowspan] !== undefined &&
3331                                                 aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
3332                                         {
3333                                                 aApplied[i+iRowspan][j] = 1;
3334                                                 iRowspan++;
3335                                         }
3336         
3337                                         /* Expand the cell to cover as many columns as needed */
3338                                         while ( aoLocal[i][j+iColspan] !== undefined &&
3339                                                 aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
3340                                         {
3341                                                 /* Must update the applied array over the rows for the columns */
3342                                                 for ( k=0 ; k<iRowspan ; k++ )
3343                                                 {
3344                                                         aApplied[i+k][j+iColspan] = 1;
3345                                                 }
3346                                                 iColspan++;
3347                                         }
3348         
3349                                         /* Do the actual expansion in the DOM */
3350                                         $(aoLocal[i][j].cell)
3351                                                 .attr('rowspan', iRowspan)
3352                                                 .attr('colspan', iColspan);
3353                                 }
3354                         }
3355                 }
3356         }
3357         
3358         
3359         /**
3360          * Insert the required TR nodes into the table for display
3361          *  @param {object} oSettings dataTables settings object
3362          *  @memberof DataTable#oApi
3363          */
3364         function _fnDraw( oSettings )
3365         {
3366                 /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
3367                 var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
3368                 if ( $.inArray( false, aPreDraw ) !== -1 )
3369                 {
3370                         _fnProcessingDisplay( oSettings, false );
3371                         return;
3372                 }
3373         
3374                 var i, iLen, n;
3375                 var anRows = [];
3376                 var iRowCount = 0;
3377                 var asStripeClasses = oSettings.asStripeClasses;
3378                 var iStripes = asStripeClasses.length;
3379                 var iOpenRows = oSettings.aoOpenRows.length;
3380                 var oLang = oSettings.oLanguage;
3381                 var iInitDisplayStart = oSettings.iInitDisplayStart;
3382                 var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3383                 var aiDisplay = oSettings.aiDisplay;
3384         
3385                 oSettings.bDrawing = true;
3386         
3387                 /* Check and see if we have an initial draw position from state saving */
3388                 if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
3389                 {
3390                         oSettings._iDisplayStart = bServerSide ?
3391                                 iInitDisplayStart :
3392                                 iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
3393                                         0 :
3394                                         iInitDisplayStart;
3395         
3396                         oSettings.iInitDisplayStart = -1;
3397                 }
3398         
3399                 var iDisplayStart = oSettings._iDisplayStart;
3400                 var iDisplayEnd = oSettings.fnDisplayEnd();
3401         
3402                 /* Server-side processing draw intercept */
3403                 if ( oSettings.bDeferLoading )
3404                 {
3405                         oSettings.bDeferLoading = false;
3406                         oSettings.iDraw++;
3407                         _fnProcessingDisplay( oSettings, false );
3408                 }
3409                 else if ( !bServerSide )
3410                 {
3411                         oSettings.iDraw++;
3412                 }
3413                 else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
3414                 {
3415                         return;
3416                 }
3417         
3418                 if ( aiDisplay.length !== 0 )
3419                 {
3420                         var iStart = bServerSide ? 0 : iDisplayStart;
3421                         var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
3422         
3423                         for ( var j=iStart ; j<iEnd ; j++ )
3424                         {
3425                                 var iDataIndex = aiDisplay[j];
3426                                 var aoData = oSettings.aoData[ iDataIndex ];
3427                                 if ( aoData.nTr === null )
3428                                 {
3429                                         _fnCreateTr( oSettings, iDataIndex );
3430                                 }
3431         
3432                                 var nRow = aoData.nTr;
3433         
3434                                 /* Remove the old striping classes and then add the new one */
3435                                 if ( iStripes !== 0 )
3436                                 {
3437                                         var sStripe = asStripeClasses[ iRowCount % iStripes ];
3438                                         if ( aoData._sRowStripe != sStripe )
3439                                         {
3440                                                 $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
3441                                                 aoData._sRowStripe = sStripe;
3442                                         }
3443                                 }
3444         
3445                                 // Row callback functions - might want to manipulate the row
3446                                 // iRowCount and j are not currently documented. Are they at all
3447                                 // useful?
3448                                 _fnCallbackFire( oSettings, 'aoRowCallback', null,
3449                                         [nRow, aoData._aData, iRowCount, j] );
3450         
3451                                 anRows.push( nRow );
3452                                 iRowCount++;
3453                         }
3454                 }
3455                 else
3456                 {
3457                         /* Table is empty - create a row with an empty message in it */
3458                         var sZero = oLang.sZeroRecords;
3459                         if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
3460                         {
3461                                 sZero = oLang.sLoadingRecords;
3462                         }
3463                         else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
3464                         {
3465                                 sZero = oLang.sEmptyTable;
3466                         }
3467         
3468                         anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
3469                                 .append( $('<td />', {
3470                                         'valign':  'top',
3471                                         'colSpan': _fnVisbleColumns( oSettings ),
3472                                         'class':   oSettings.oClasses.sRowEmpty
3473                                 } ).html( sZero ) )[0];
3474                 }
3475         
3476                 /* Header and footer callbacks */
3477                 _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
3478                         _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3479         
3480                 _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
3481                         _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3482         
3483                 var body = $(oSettings.nTBody);
3484         
3485                 body.children().detach();
3486                 body.append( $(anRows) );
3487         
3488                 /* Call all required callback functions for the end of a draw */
3489                 _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
3490         
3491                 /* Draw is complete, sorting and filtering must be as well */
3492                 oSettings.bSorted = false;
3493                 oSettings.bFiltered = false;
3494                 oSettings.bDrawing = false;
3495         }
3496         
3497         
3498         /**
3499          * Redraw the table - taking account of the various features which are enabled
3500          *  @param {object} oSettings dataTables settings object
3501          *  @param {boolean} [holdPosition] Keep the current paging position. By default
3502          *    the paging is reset to the first page
3503          *  @memberof DataTable#oApi
3504          */
3505         function _fnReDraw( settings, holdPosition )
3506         {
3507                 var
3508                         features = settings.oFeatures,
3509                         sort     = features.bSort,
3510                         filter   = features.bFilter;
3511         
3512                 if ( sort ) {
3513                         _fnSort( settings );
3514                 }
3515         
3516                 if ( filter ) {
3517                         _fnFilterComplete( settings, settings.oPreviousSearch );
3518                 }
3519                 else {
3520                         // No filtering, so we want to just use the display master
3521                         settings.aiDisplay = settings.aiDisplayMaster.slice();
3522                 }
3523         
3524                 if ( holdPosition !== true ) {
3525                         settings._iDisplayStart = 0;
3526                 }
3527         
3528                 // Let any modules know about the draw hold position state (used by
3529                 // scrolling internally)
3530                 settings._drawHold = holdPosition;
3531         
3532                 _fnDraw( settings );
3533         
3534                 settings._drawHold = false;
3535         }
3536         
3537         
3538         /**
3539          * Add the options to the page HTML for the table
3540          *  @param {object} oSettings dataTables settings object
3541          *  @memberof DataTable#oApi
3542          */
3543         function _fnAddOptionsHtml ( oSettings )
3544         {
3545                 var classes = oSettings.oClasses;
3546                 var table = $(oSettings.nTable);
3547                 var holding = $('<div/>').insertBefore( table ); // Holding element for speed
3548                 var features = oSettings.oFeatures;
3549         
3550                 // All DataTables are wrapped in a div
3551                 var insert = $('<div/>', {
3552                         id:      oSettings.sTableId+'_wrapper',
3553                         'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
3554                 } );
3555         
3556                 oSettings.nHolding = holding[0];
3557                 oSettings.nTableWrapper = insert[0];
3558                 oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
3559         
3560                 /* Loop over the user set positioning and place the elements as needed */
3561                 var aDom = oSettings.sDom.split('');
3562                 var featureNode, cOption, nNewNode, cNext, sAttr, j;
3563                 for ( var i=0 ; i<aDom.length ; i++ )
3564                 {
3565                         featureNode = null;
3566                         cOption = aDom[i];
3567         
3568                         if ( cOption == '<' )
3569                         {
3570                                 /* New container div */
3571                                 nNewNode = $('<div/>')[0];
3572         
3573                                 /* Check to see if we should append an id and/or a class name to the container */
3574                                 cNext = aDom[i+1];
3575                                 if ( cNext == "'" || cNext == '"' )
3576                                 {
3577                                         sAttr = "";
3578                                         j = 2;
3579                                         while ( aDom[i+j] != cNext )
3580                                         {
3581                                                 sAttr += aDom[i+j];
3582                                                 j++;
3583                                         }
3584         
3585                                         /* Replace jQuery UI constants @todo depreciated */
3586                                         if ( sAttr == "H" )
3587                                         {
3588                                                 sAttr = classes.sJUIHeader;
3589                                         }
3590                                         else if ( sAttr == "F" )
3591                                         {
3592                                                 sAttr = classes.sJUIFooter;
3593                                         }
3594         
3595                                         /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3596                                          * breaks the string into parts and applies them as needed
3597                                          */
3598                                         if ( sAttr.indexOf('.') != -1 )
3599                                         {
3600                                                 var aSplit = sAttr.split('.');
3601                                                 nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
3602                                                 nNewNode.className = aSplit[1];
3603                                         }
3604                                         else if ( sAttr.charAt(0) == "#" )
3605                                         {
3606                                                 nNewNode.id = sAttr.substr(1, sAttr.length-1);
3607                                         }
3608                                         else
3609                                         {
3610                                                 nNewNode.className = sAttr;
3611                                         }
3612         
3613                                         i += j; /* Move along the position array */
3614                                 }
3615         
3616                                 insert.append( nNewNode );
3617                                 insert = $(nNewNode);
3618                         }
3619                         else if ( cOption == '>' )
3620                         {
3621                                 /* End container div */
3622                                 insert = insert.parent();
3623                         }
3624                         // @todo Move options into their own plugins?
3625                         else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
3626                         {
3627                                 /* Length */
3628                                 featureNode = _fnFeatureHtmlLength( oSettings );
3629                         }
3630                         else if ( cOption == 'f' && features.bFilter )
3631                         {
3632                                 /* Filter */
3633                                 featureNode = _fnFeatureHtmlFilter( oSettings );
3634                         }
3635                         else if ( cOption == 'r' && features.bProcessing )
3636                         {
3637                                 /* pRocessing */
3638                                 featureNode = _fnFeatureHtmlProcessing( oSettings );
3639                         }
3640                         else if ( cOption == 't' )
3641                         {
3642                                 /* Table */
3643                                 featureNode = _fnFeatureHtmlTable( oSettings );
3644                         }
3645                         else if ( cOption ==  'i' && features.bInfo )
3646                         {
3647                                 /* Info */
3648                                 featureNode = _fnFeatureHtmlInfo( oSettings );
3649                         }
3650                         else if ( cOption == 'p' && features.bPaginate )
3651                         {
3652                                 /* Pagination */
3653                                 featureNode = _fnFeatureHtmlPaginate( oSettings );
3654                         }
3655                         else if ( DataTable.ext.feature.length !== 0 )
3656                         {
3657                                 /* Plug-in features */
3658                                 var aoFeatures = DataTable.ext.feature;
3659                                 for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3660                                 {
3661                                         if ( cOption == aoFeatures[k].cFeature )
3662                                         {
3663                                                 featureNode = aoFeatures[k].fnInit( oSettings );
3664                                                 break;
3665                                         }
3666                                 }
3667                         }
3668         
3669                         /* Add to the 2D features array */
3670                         if ( featureNode )
3671                         {
3672                                 var aanFeatures = oSettings.aanFeatures;
3673         
3674                                 if ( ! aanFeatures[cOption] )
3675                                 {
3676                                         aanFeatures[cOption] = [];
3677                                 }
3678         
3679                                 aanFeatures[cOption].push( featureNode );
3680                                 insert.append( featureNode );
3681                         }
3682                 }
3683         
3684                 /* Built our DOM structure - replace the holding div with what we want */
3685                 holding.replaceWith( insert );
3686                 oSettings.nHolding = null;
3687         }
3688         
3689         
3690         /**
3691          * Use the DOM source to create up an array of header cells. The idea here is to
3692          * create a layout grid (array) of rows x columns, which contains a reference
3693          * to the cell that that point in the grid (regardless of col/rowspan), such that
3694          * any column / row could be removed and the new grid constructed
3695          *  @param array {object} aLayout Array to store the calculated layout in
3696          *  @param {node} nThead The header/footer element for the table
3697          *  @memberof DataTable#oApi
3698          */
3699         function _fnDetectHeader ( aLayout, nThead )
3700         {
3701                 var nTrs = $(nThead).children('tr');
3702                 var nTr, nCell;
3703                 var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
3704                 var bUnique;
3705                 var fnShiftCol = function ( a, i, j ) {
3706                         var k = a[i];
3707                         while ( k[j] ) {
3708                                 j++;
3709                         }
3710                         return j;
3711                 };
3712         
3713                 aLayout.splice( 0, aLayout.length );
3714         
3715                 /* We know how many rows there are in the layout - so prep it */
3716                 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3717                 {
3718                         aLayout.push( [] );
3719                 }
3720         
3721                 /* Calculate a layout array */
3722                 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3723                 {
3724                         nTr = nTrs[i];
3725                         iColumn = 0;
3726         
3727                         /* For every cell in the row... */
3728                         nCell = nTr.firstChild;
3729                         while ( nCell ) {
3730                                 if ( nCell.nodeName.toUpperCase() == "TD" ||
3731                                      nCell.nodeName.toUpperCase() == "TH" )
3732                                 {
3733                                         /* Get the col and rowspan attributes from the DOM and sanitise them */
3734                                         iColspan = nCell.getAttribute('colspan') * 1;
3735                                         iRowspan = nCell.getAttribute('rowspan') * 1;
3736                                         iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
3737                                         iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
3738         
3739                                         /* There might be colspan cells already in this row, so shift our target
3740                                          * accordingly
3741                                          */
3742                                         iColShifted = fnShiftCol( aLayout, i, iColumn );
3743         
3744                                         /* Cache calculation for unique columns */
3745                                         bUnique = iColspan === 1 ? true : false;
3746         
3747                                         /* If there is col / rowspan, copy the information into the layout grid */
3748                                         for ( l=0 ; l<iColspan ; l++ )
3749                                         {
3750                                                 for ( k=0 ; k<iRowspan ; k++ )
3751                                                 {
3752                                                         aLayout[i+k][iColShifted+l] = {
3753                                                                 "cell": nCell,
3754                                                                 "unique": bUnique
3755                                                         };
3756                                                         aLayout[i+k].nTr = nTr;
3757                                                 }
3758                                         }
3759                                 }
3760                                 nCell = nCell.nextSibling;
3761                         }
3762                 }
3763         }
3764         
3765         
3766         /**
3767          * Get an array of unique th elements, one for each column
3768          *  @param {object} oSettings dataTables settings object
3769          *  @param {node} nHeader automatically detect the layout from this node - optional
3770          *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3771          *  @returns array {node} aReturn list of unique th's
3772          *  @memberof DataTable#oApi
3773          */
3774         function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
3775         {
3776                 var aReturn = [];
3777                 if ( !aLayout )
3778                 {
3779                         aLayout = oSettings.aoHeader;
3780                         if ( nHeader )
3781                         {
3782                                 aLayout = [];
3783                                 _fnDetectHeader( aLayout, nHeader );
3784                         }
3785                 }
3786         
3787                 for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
3788                 {
3789                         for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
3790                         {
3791                                 if ( aLayout[i][j].unique &&
3792                                          (!aReturn[j] || !oSettings.bSortCellsTop) )
3793                                 {
3794                                         aReturn[j] = aLayout[i][j].cell;
3795                                 }
3796                         }
3797                 }
3798         
3799                 return aReturn;
3800         }
3801         
3802         /**
3803          * Create an Ajax call based on the table's settings, taking into account that
3804          * parameters can have multiple forms, and backwards compatibility.
3805          *
3806          * @param {object} oSettings dataTables settings object
3807          * @param {array} data Data to send to the server, required by
3808          *     DataTables - may be augmented by developer callbacks
3809          * @param {function} fn Callback function to run when data is obtained
3810          */
3811         function _fnBuildAjax( oSettings, data, fn )
3812         {
3813                 // Compatibility with 1.9-, allow fnServerData and event to manipulate
3814                 _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
3815         
3816                 // Convert to object based for 1.10+ if using the old array scheme which can
3817                 // come from server-side processing or serverParams
3818                 if ( data && $.isArray(data) ) {
3819                         var tmp = {};
3820                         var rbracket = /(.*?)\[\]$/;
3821         
3822                         $.each( data, function (key, val) {
3823                                 var match = val.name.match(rbracket);
3824         
3825                                 if ( match ) {
3826                                         // Support for arrays
3827                                         var name = match[0];
3828         
3829                                         if ( ! tmp[ name ] ) {
3830                                                 tmp[ name ] = [];
3831                                         }
3832                                         tmp[ name ].push( val.value );
3833                                 }
3834                                 else {
3835                                         tmp[val.name] = val.value;
3836                                 }
3837                         } );
3838                         data = tmp;
3839                 }
3840         
3841                 var ajaxData;
3842                 var ajax = oSettings.ajax;
3843                 var instance = oSettings.oInstance;
3844                 var callback = function ( json ) {
3845                         _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
3846                         fn( json );
3847                 };
3848         
3849                 if ( $.isPlainObject( ajax ) && ajax.data )
3850                 {
3851                         ajaxData = ajax.data;
3852         
3853                         var newData = $.isFunction( ajaxData ) ?
3854                                 ajaxData( data, oSettings ) :  // fn can manipulate data or return
3855                                 ajaxData;                      // an object object or array to merge
3856         
3857                         // If the function returned something, use that alone
3858                         data = $.isFunction( ajaxData ) && newData ?
3859                                 newData :
3860                                 $.extend( true, data, newData );
3861         
3862                         // Remove the data property as we've resolved it already and don't want
3863                         // jQuery to do it again (it is restored at the end of the function)
3864                         delete ajax.data;
3865                 }
3866         
3867                 var baseAjax = {
3868                         "data": data,
3869                         "success": function (json) {
3870                                 var error = json.error || json.sError;
3871                                 if ( error ) {
3872                                         _fnLog( oSettings, 0, error );
3873                                 }
3874         
3875                                 oSettings.json = json;
3876                                 callback( json );
3877                         },
3878                         "dataType": "json",
3879                         "cache": false,
3880                         "type": oSettings.sServerMethod,
3881                         "error": function (xhr, error, thrown) {
3882                                 var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
3883         
3884                                 if ( $.inArray( true, ret ) === -1 ) {
3885                                         if ( error == "parsererror" ) {
3886                                                 _fnLog( oSettings, 0, 'Invalid JSON response', 1 );
3887                                         }
3888                                         else if ( xhr.readyState === 4 ) {
3889                                                 _fnLog( oSettings, 0, 'Ajax error', 7 );
3890                                         }
3891                                 }
3892         
3893                                 _fnProcessingDisplay( oSettings, false );
3894                         }
3895                 };
3896         
3897                 // Store the data submitted for the API
3898                 oSettings.oAjaxData = data;
3899         
3900                 // Allow plug-ins and external processes to modify the data
3901                 _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
3902         
3903                 if ( oSettings.fnServerData )
3904                 {
3905                         // DataTables 1.9- compatibility
3906                         oSettings.fnServerData.call( instance,
3907                                 oSettings.sAjaxSource,
3908                                 $.map( data, function (val, key) { // Need to convert back to 1.9 trad format
3909                                         return { name: key, value: val };
3910                                 } ),
3911                                 callback,
3912                                 oSettings
3913                         );
3914                 }
3915                 else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
3916                 {
3917                         // DataTables 1.9- compatibility
3918                         oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
3919                                 url: ajax || oSettings.sAjaxSource
3920                         } ) );
3921                 }
3922                 else if ( $.isFunction( ajax ) )
3923                 {
3924                         // Is a function - let the caller define what needs to be done
3925                         oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
3926                 }
3927                 else
3928                 {
3929                         // Object to extend the base settings
3930                         oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
3931         
3932                         // Restore for next time around
3933                         ajax.data = ajaxData;
3934                 }
3935         }
3936         
3937         
3938         /**
3939          * Update the table using an Ajax call
3940          *  @param {object} settings dataTables settings object
3941          *  @returns {boolean} Block the table drawing or not
3942          *  @memberof DataTable#oApi
3943          */
3944         function _fnAjaxUpdate( settings )
3945         {
3946                 if ( settings.bAjaxDataGet ) {
3947                         settings.iDraw++;
3948                         _fnProcessingDisplay( settings, true );
3949         
3950                         _fnBuildAjax(
3951                                 settings,
3952                                 _fnAjaxParameters( settings ),
3953                                 function(json) {
3954                                         _fnAjaxUpdateDraw( settings, json );
3955                                 }
3956                         );
3957         
3958                         return false;
3959                 }
3960                 return true;
3961         }
3962         
3963         
3964         /**
3965          * Build up the parameters in an object needed for a server-side processing
3966          * request. Note that this is basically done twice, is different ways - a modern
3967          * method which is used by default in DataTables 1.10 which uses objects and
3968          * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
3969          * the sAjaxSource option is used in the initialisation, or the legacyAjax
3970          * option is set.
3971          *  @param {object} oSettings dataTables settings object
3972          *  @returns {bool} block the table drawing or not
3973          *  @memberof DataTable#oApi
3974          */
3975         function _fnAjaxParameters( settings )
3976         {
3977                 var
3978                         columns = settings.aoColumns,
3979                         columnCount = columns.length,
3980                         features = settings.oFeatures,
3981                         preSearch = settings.oPreviousSearch,
3982                         preColSearch = settings.aoPreSearchCols,
3983                         i, data = [], dataProp, column, columnSearch,
3984                         sort = _fnSortFlatten( settings ),
3985                         displayStart = settings._iDisplayStart,
3986                         displayLength = features.bPaginate !== false ?
3987                                 settings._iDisplayLength :
3988                                 -1;
3989         
3990                 var param = function ( name, value ) {
3991                         data.push( { 'name': name, 'value': value } );
3992                 };
3993         
3994                 // DataTables 1.9- compatible method
3995                 param( 'sEcho',          settings.iDraw );
3996                 param( 'iColumns',       columnCount );
3997                 param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
3998                 param( 'iDisplayStart',  displayStart );
3999                 param( 'iDisplayLength', displayLength );
4000         
4001                 // DataTables 1.10+ method
4002                 var d = {
4003                         draw:    settings.iDraw,
4004                         columns: [],
4005                         order:   [],
4006                         start:   displayStart,
4007                         length:  displayLength,
4008                         search:  {
4009                                 value: preSearch.sSearch,
4010                                 regex: preSearch.bRegex
4011                         }
4012                 };
4013         
4014                 for ( i=0 ; i<columnCount ; i++ ) {
4015                         column = columns[i];
4016                         columnSearch = preColSearch[i];
4017                         dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
4018         
4019                         d.columns.push( {
4020                                 data:       dataProp,
4021                                 name:       column.sName,
4022                                 searchable: column.bSearchable,
4023                                 orderable:  column.bSortable,
4024                                 search:     {
4025                                         value: columnSearch.sSearch,
4026                                         regex: columnSearch.bRegex
4027                                 }
4028                         } );
4029         
4030                         param( "mDataProp_"+i, dataProp );
4031         
4032                         if ( features.bFilter ) {
4033                                 param( 'sSearch_'+i,     columnSearch.sSearch );
4034                                 param( 'bRegex_'+i,      columnSearch.bRegex );
4035                                 param( 'bSearchable_'+i, column.bSearchable );
4036                         }
4037         
4038                         if ( features.bSort ) {
4039                                 param( 'bSortable_'+i, column.bSortable );
4040                         }
4041                 }
4042         
4043                 if ( features.bFilter ) {
4044                         param( 'sSearch', preSearch.sSearch );
4045                         param( 'bRegex', preSearch.bRegex );
4046                 }
4047         
4048                 if ( features.bSort ) {
4049                         $.each( sort, function ( i, val ) {
4050                                 d.order.push( { column: val.col, dir: val.dir } );
4051         
4052                                 param( 'iSortCol_'+i, val.col );
4053                                 param( 'sSortDir_'+i, val.dir );
4054                         } );
4055         
4056                         param( 'iSortingCols', sort.length );
4057                 }
4058         
4059                 // If the legacy.ajax parameter is null, then we automatically decide which
4060                 // form to use, based on sAjaxSource
4061                 var legacy = DataTable.ext.legacy.ajax;
4062                 if ( legacy === null ) {
4063                         return settings.sAjaxSource ? data : d;
4064                 }
4065         
4066                 // Otherwise, if legacy has been specified then we use that to decide on the
4067                 // form
4068                 return legacy ? data : d;
4069         }
4070         
4071         
4072         /**
4073          * Data the data from the server (nuking the old) and redraw the table
4074          *  @param {object} oSettings dataTables settings object
4075          *  @param {object} json json data return from the server.
4076          *  @param {string} json.sEcho Tracking flag for DataTables to match requests
4077          *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4078          *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4079          *  @param {array} json.aaData The data to display on this page
4080          *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
4081          *  @memberof DataTable#oApi
4082          */
4083         function _fnAjaxUpdateDraw ( settings, json )
4084         {
4085                 // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
4086                 // Support both
4087                 var compat = function ( old, modern ) {
4088                         return json[old] !== undefined ? json[old] : json[modern];
4089                 };
4090         
4091                 var data = _fnAjaxDataSrc( settings, json );
4092                 var draw            = compat( 'sEcho',                'draw' );
4093                 var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
4094                 var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
4095         
4096                 if ( draw ) {
4097                         // Protect against out of sequence returns
4098                         if ( draw*1 < settings.iDraw ) {
4099                                 return;
4100                         }
4101                         settings.iDraw = draw * 1;
4102                 }
4103         
4104                 _fnClearTable( settings );
4105                 settings._iRecordsTotal   = parseInt(recordsTotal, 10);
4106                 settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4107         
4108                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
4109                         _fnAddData( settings, data[i] );
4110                 }
4111                 settings.aiDisplay = settings.aiDisplayMaster.slice();
4112         
4113                 settings.bAjaxDataGet = false;
4114                 _fnDraw( settings );
4115         
4116                 if ( ! settings._bInitComplete ) {
4117                         _fnInitComplete( settings, json );
4118                 }
4119         
4120                 settings.bAjaxDataGet = true;
4121                 _fnProcessingDisplay( settings, false );
4122         }
4123         
4124         
4125         /**
4126          * Get the data from the JSON data source to use for drawing a table. Using
4127          * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4128          * source object, or from a processing function.
4129          *  @param {object} oSettings dataTables settings object
4130          *  @param  {object} json Data source object / array from the server
4131          *  @return {array} Array of data to use
4132          */
4133         function _fnAjaxDataSrc ( oSettings, json )
4134         {
4135                 var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
4136                         oSettings.ajax.dataSrc :
4137                         oSettings.sAjaxDataProp; // Compatibility with 1.9-.
4138         
4139                 // Compatibility with 1.9-. In order to read from aaData, check if the
4140                 // default has been changed, if not, check for aaData
4141                 if ( dataSrc === 'data' ) {
4142                         return json.aaData || json[dataSrc];
4143                 }
4144         
4145                 return dataSrc !== "" ?
4146                         _fnGetObjectDataFn( dataSrc )( json ) :
4147                         json;
4148         }
4149         
4150         /**
4151          * Generate the node required for filtering text
4152          *  @returns {node} Filter control element
4153          *  @param {object} oSettings dataTables settings object
4154          *  @memberof DataTable#oApi
4155          */
4156         function _fnFeatureHtmlFilter ( settings )
4157         {
4158                 var classes = settings.oClasses;
4159                 var tableId = settings.sTableId;
4160                 var language = settings.oLanguage;
4161                 var previousSearch = settings.oPreviousSearch;
4162                 var features = settings.aanFeatures;
4163                 var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
4164         
4165                 var str = language.sSearch;
4166                 str = str.match(/_INPUT_/) ?
4167                         str.replace('_INPUT_', input) :
4168                         str+input;
4169         
4170                 var filter = $('<div/>', {
4171                                 'id': ! features.f ? tableId+'_filter' : null,
4172                                 'class': classes.sFilter
4173                         } )
4174                         .append( $('<label/>' ).append( str ) );
4175         
4176                 var searchFn = function() {
4177                         /* Update all other filter input elements for the new display */
4178                         var n = features.f;
4179                         var val = !this.value ? "" : this.value; // mental IE8 fix :-(
4180         
4181                         /* Now do the filter */
4182                         if ( val != previousSearch.sSearch ) {
4183                                 _fnFilterComplete( settings, {
4184                                         "sSearch": val,
4185                                         "bRegex": previousSearch.bRegex,
4186                                         "bSmart": previousSearch.bSmart ,
4187                                         "bCaseInsensitive": previousSearch.bCaseInsensitive
4188                                 } );
4189         
4190                                 // Need to redraw, without resorting
4191                                 settings._iDisplayStart = 0;
4192                                 _fnDraw( settings );
4193                         }
4194                 };
4195         
4196                 var searchDelay = settings.searchDelay !== null ?
4197                         settings.searchDelay :
4198                         _fnDataSource( settings ) === 'ssp' ?
4199                                 400 :
4200                                 0;
4201         
4202                 var jqFilter = $('input', filter)
4203                         .val( previousSearch.sSearch )
4204                         .attr( 'placeholder', language.sSearchPlaceholder )
4205                         .bind(
4206                                 'keyup.DT search.DT input.DT paste.DT cut.DT',
4207                                 searchDelay ?
4208                                         _fnThrottle( searchFn, searchDelay ) :
4209                                         searchFn
4210                         )
4211                         .bind( 'keypress.DT', function(e) {
4212                                 /* Prevent form submission */
4213                                 if ( e.keyCode == 13 ) {
4214                                         return false;
4215                                 }
4216                         } )
4217                         .attr('aria-controls', tableId);
4218         
4219                 // Update the input elements whenever the table is filtered
4220                 $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
4221                         if ( settings === s ) {
4222                                 // IE9 throws an 'unknown error' if document.activeElement is used
4223                                 // inside an iframe or frame...
4224                                 try {
4225                                         if ( jqFilter[0] !== document.activeElement ) {
4226                                                 jqFilter.val( previousSearch.sSearch );
4227                                         }
4228                                 }
4229                                 catch ( e ) {}
4230                         }
4231                 } );
4232         
4233                 return filter[0];
4234         }
4235         
4236         
4237         /**
4238          * Filter the table using both the global filter and column based filtering
4239          *  @param {object} oSettings dataTables settings object
4240          *  @param {object} oSearch search information
4241          *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4242          *  @memberof DataTable#oApi
4243          */
4244         function _fnFilterComplete ( oSettings, oInput, iForce )
4245         {
4246                 var oPrevSearch = oSettings.oPreviousSearch;
4247                 var aoPrevSearch = oSettings.aoPreSearchCols;
4248                 var fnSaveFilter = function ( oFilter ) {
4249                         /* Save the filtering values */
4250                         oPrevSearch.sSearch = oFilter.sSearch;
4251                         oPrevSearch.bRegex = oFilter.bRegex;
4252                         oPrevSearch.bSmart = oFilter.bSmart;
4253                         oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
4254                 };
4255                 var fnRegex = function ( o ) {
4256                         // Backwards compatibility with the bEscapeRegex option
4257                         return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
4258                 };
4259         
4260                 // Resolve any column types that are unknown due to addition or invalidation
4261                 // @todo As per sort - can this be moved into an event handler?
4262                 _fnColumnTypes( oSettings );
4263         
4264                 /* In server-side processing all filtering is done by the server, so no point hanging around here */
4265                 if ( _fnDataSource( oSettings ) != 'ssp' )
4266                 {
4267                         /* Global filter */
4268                         _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
4269                         fnSaveFilter( oInput );
4270         
4271                         /* Now do the individual column filter */
4272                         for ( var i=0 ; i<aoPrevSearch.length ; i++ )
4273                         {
4274                                 _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
4275                                         aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
4276                         }
4277         
4278                         /* Custom filtering */
4279                         _fnFilterCustom( oSettings );
4280                 }
4281                 else
4282                 {
4283                         fnSaveFilter( oInput );
4284                 }
4285         
4286                 /* Tell the draw function we have been filtering */
4287                 oSettings.bFiltered = true;
4288                 _fnCallbackFire( oSettings, null, 'search', [oSettings] );
4289         }
4290         
4291         
4292         /**
4293          * Apply custom filtering functions
4294          *  @param {object} oSettings dataTables settings object
4295          *  @memberof DataTable#oApi
4296          */
4297         function _fnFilterCustom( settings )
4298         {
4299                 var filters = DataTable.ext.search;
4300                 var displayRows = settings.aiDisplay;
4301                 var row, rowIdx;
4302         
4303                 for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
4304                         var rows = [];
4305         
4306                         // Loop over each row and see if it should be included
4307                         for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
4308                                 rowIdx = displayRows[ j ];
4309                                 row = settings.aoData[ rowIdx ];
4310         
4311                                 if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
4312                                         rows.push( rowIdx );
4313                                 }
4314                         }
4315         
4316                         // So the array reference doesn't break set the results into the
4317                         // existing array
4318                         displayRows.length = 0;
4319                         $.merge( displayRows, rows );
4320                 }
4321         }
4322         
4323         
4324         /**
4325          * Filter the table on a per-column basis
4326          *  @param {object} oSettings dataTables settings object
4327          *  @param {string} sInput string to filter on
4328          *  @param {int} iColumn column to filter
4329          *  @param {bool} bRegex treat search string as a regular expression or not
4330          *  @param {bool} bSmart use smart filtering or not
4331          *  @param {bool} bCaseInsensitive Do case insenstive matching or not
4332          *  @memberof DataTable#oApi
4333          */
4334         function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
4335         {
4336                 if ( searchStr === '' ) {
4337                         return;
4338                 }
4339         
4340                 var data;
4341                 var display = settings.aiDisplay;
4342                 var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4343         
4344                 for ( var i=display.length-1 ; i>=0 ; i-- ) {
4345                         data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4346         
4347                         if ( ! rpSearch.test( data ) ) {
4348                                 display.splice( i, 1 );
4349                         }
4350                 }
4351         }
4352         
4353         
4354         /**
4355          * Filter the data table based on user input and draw the table
4356          *  @param {object} settings dataTables settings object
4357          *  @param {string} input string to filter on
4358          *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4359          *  @param {bool} regex treat as a regular expression or not
4360          *  @param {bool} smart perform smart filtering or not
4361          *  @param {bool} caseInsensitive Do case insenstive matching or not
4362          *  @memberof DataTable#oApi
4363          */
4364         function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
4365         {
4366                 var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
4367                 var prevSearch = settings.oPreviousSearch.sSearch;
4368                 var displayMaster = settings.aiDisplayMaster;
4369                 var display, invalidated, i;
4370         
4371                 // Need to take account of custom filtering functions - always filter
4372                 if ( DataTable.ext.search.length !== 0 ) {
4373                         force = true;
4374                 }
4375         
4376                 // Check if any of the rows were invalidated
4377                 invalidated = _fnFilterData( settings );
4378         
4379                 // If the input is blank - we just want the full data set
4380                 if ( input.length <= 0 ) {
4381                         settings.aiDisplay = displayMaster.slice();
4382                 }
4383                 else {
4384                         // New search - start from the master array
4385                         if ( invalidated ||
4386                                  force ||
4387                                  prevSearch.length > input.length ||
4388                                  input.indexOf(prevSearch) !== 0 ||
4389                                  settings.bSorted // On resort, the display master needs to be
4390                                                   // re-filtered since indexes will have changed
4391                         ) {
4392                                 settings.aiDisplay = displayMaster.slice();
4393                         }
4394         
4395                         // Search the display array
4396                         display = settings.aiDisplay;
4397         
4398                         for ( i=display.length-1 ; i>=0 ; i-- ) {
4399                                 if ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4400                                         display.splice( i, 1 );
4401                                 }
4402                         }
4403                 }
4404         }
4405         
4406         
4407         /**
4408          * Build a regular expression object suitable for searching a table
4409          *  @param {string} sSearch string to search for
4410          *  @param {bool} bRegex treat as a regular expression or not
4411          *  @param {bool} bSmart perform smart filtering or not
4412          *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4413          *  @returns {RegExp} constructed object
4414          *  @memberof DataTable#oApi
4415          */
4416         function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
4417         {
4418                 search = regex ?
4419                         search :
4420                         _fnEscapeRegex( search );
4421                 
4422                 if ( smart ) {
4423                         /* For smart filtering we want to allow the search to work regardless of
4424                          * word order. We also want double quoted text to be preserved, so word
4425                          * order is important - a la google. So this is what we want to
4426                          * generate:
4427                          * 
4428                          * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4429                          */
4430                         var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
4431                                 if ( word.charAt(0) === '"' ) {
4432                                         var m = word.match( /^"(.*)"$/ );
4433                                         word = m ? m[1] : word;
4434                                 }
4435         
4436                                 return word.replace('"', '');
4437                         } );
4438         
4439                         search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
4440                 }
4441         
4442                 return new RegExp( search, caseInsensitive ? 'i' : '' );
4443         }
4444         
4445         
4446         /**
4447          * Escape a string such that it can be used in a regular expression
4448          *  @param {string} sVal string to escape
4449          *  @returns {string} escaped string
4450          *  @memberof DataTable#oApi
4451          */
4452         var _fnEscapeRegex = DataTable.util.escapeRegex;
4453         
4454         var __filter_div = $('<div>')[0];
4455         var __filter_div_textContent = __filter_div.textContent !== undefined;
4456         
4457         // Update the filtering data for each row if needed (by invalidation or first run)
4458         function _fnFilterData ( settings )
4459         {
4460                 var columns = settings.aoColumns;
4461                 var column;
4462                 var i, j, ien, jen, filterData, cellData, row;
4463                 var fomatters = DataTable.ext.type.search;
4464                 var wasInvalidated = false;
4465         
4466                 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4467                         row = settings.aoData[i];
4468         
4469                         if ( ! row._aFilterData ) {
4470                                 filterData = [];
4471         
4472                                 for ( j=0, jen=columns.length ; j<jen ; j++ ) {
4473                                         column = columns[j];
4474         
4475                                         if ( column.bSearchable ) {
4476                                                 cellData = _fnGetCellData( settings, i, j, 'filter' );
4477         
4478                                                 if ( fomatters[ column.sType ] ) {
4479                                                         cellData = fomatters[ column.sType ]( cellData );
4480                                                 }
4481         
4482                                                 // Search in DataTables 1.10 is string based. In 1.11 this
4483                                                 // should be altered to also allow strict type checking.
4484                                                 if ( cellData === null ) {
4485                                                         cellData = '';
4486                                                 }
4487         
4488                                                 if ( typeof cellData !== 'string' && cellData.toString ) {
4489                                                         cellData = cellData.toString();
4490                                                 }
4491                                         }
4492                                         else {
4493                                                 cellData = '';
4494                                         }
4495         
4496                                         // If it looks like there is an HTML entity in the string,
4497                                         // attempt to decode it so sorting works as expected. Note that
4498                                         // we could use a single line of jQuery to do this, but the DOM
4499                                         // method used here is much faster http://jsperf.com/html-decode
4500                                         if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
4501                                                 __filter_div.innerHTML = cellData;
4502                                                 cellData = __filter_div_textContent ?
4503                                                         __filter_div.textContent :
4504                                                         __filter_div.innerText;
4505                                         }
4506         
4507                                         if ( cellData.replace ) {
4508                                                 cellData = cellData.replace(/[\r\n]/g, '');
4509                                         }
4510         
4511                                         filterData.push( cellData );
4512                                 }
4513         
4514                                 row._aFilterData = filterData;
4515                                 row._sFilterRow = filterData.join('  ');
4516                                 wasInvalidated = true;
4517                         }
4518                 }
4519         
4520                 return wasInvalidated;
4521         }
4522         
4523         
4524         /**
4525          * Convert from the internal Hungarian notation to camelCase for external
4526          * interaction
4527          *  @param {object} obj Object to convert
4528          *  @returns {object} Inverted object
4529          *  @memberof DataTable#oApi
4530          */
4531         function _fnSearchToCamel ( obj )
4532         {
4533                 return {
4534                         search:          obj.sSearch,
4535                         smart:           obj.bSmart,
4536                         regex:           obj.bRegex,
4537                         caseInsensitive: obj.bCaseInsensitive
4538                 };
4539         }
4540         
4541         
4542         
4543         /**
4544          * Convert from camelCase notation to the internal Hungarian. We could use the
4545          * Hungarian convert function here, but this is cleaner
4546          *  @param {object} obj Object to convert
4547          *  @returns {object} Inverted object
4548          *  @memberof DataTable#oApi
4549          */
4550         function _fnSearchToHung ( obj )
4551         {
4552                 return {
4553                         sSearch:          obj.search,
4554                         bSmart:           obj.smart,
4555                         bRegex:           obj.regex,
4556                         bCaseInsensitive: obj.caseInsensitive
4557                 };
4558         }
4559         
4560         /**
4561          * Generate the node required for the info display
4562          *  @param {object} oSettings dataTables settings object
4563          *  @returns {node} Information element
4564          *  @memberof DataTable#oApi
4565          */
4566         function _fnFeatureHtmlInfo ( settings )
4567         {
4568                 var
4569                         tid = settings.sTableId,
4570                         nodes = settings.aanFeatures.i,
4571                         n = $('<div/>', {
4572                                 'class': settings.oClasses.sInfo,
4573                                 'id': ! nodes ? tid+'_info' : null
4574                         } );
4575         
4576                 if ( ! nodes ) {
4577                         // Update display on each draw
4578                         settings.aoDrawCallback.push( {
4579                                 "fn": _fnUpdateInfo,
4580                                 "sName": "information"
4581                         } );
4582         
4583                         n
4584                                 .attr( 'role', 'status' )
4585                                 .attr( 'aria-live', 'polite' );
4586         
4587                         // Table is described by our info div
4588                         $(settings.nTable).attr( 'aria-describedby', tid+'_info' );
4589                 }
4590         
4591                 return n[0];
4592         }
4593         
4594         
4595         /**
4596          * Update the information elements in the display
4597          *  @param {object} settings dataTables settings object
4598          *  @memberof DataTable#oApi
4599          */
4600         function _fnUpdateInfo ( settings )
4601         {
4602                 /* Show information about the table */
4603                 var nodes = settings.aanFeatures.i;
4604                 if ( nodes.length === 0 ) {
4605                         return;
4606                 }
4607         
4608                 var
4609                         lang  = settings.oLanguage,
4610                         start = settings._iDisplayStart+1,
4611                         end   = settings.fnDisplayEnd(),
4612                         max   = settings.fnRecordsTotal(),
4613                         total = settings.fnRecordsDisplay(),
4614                         out   = total ?
4615                                 lang.sInfo :
4616                                 lang.sInfoEmpty;
4617         
4618                 if ( total !== max ) {
4619                         /* Record set after filtering */
4620                         out += ' ' + lang.sInfoFiltered;
4621                 }
4622         
4623                 // Convert the macros
4624                 out += lang.sInfoPostFix;
4625                 out = _fnInfoMacros( settings, out );
4626         
4627                 var callback = lang.fnInfoCallback;
4628                 if ( callback !== null ) {
4629                         out = callback.call( settings.oInstance,
4630                                 settings, start, end, max, total, out
4631                         );
4632                 }
4633         
4634                 $(nodes).html( out );
4635         }
4636         
4637         
4638         function _fnInfoMacros ( settings, str )
4639         {
4640                 // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4641                 // internally
4642                 var
4643                         formatter  = settings.fnFormatNumber,
4644                         start      = settings._iDisplayStart+1,
4645                         len        = settings._iDisplayLength,
4646                         vis        = settings.fnRecordsDisplay(),
4647                         all        = len === -1;
4648         
4649                 return str.
4650                         replace(/_START_/g, formatter.call( settings, start ) ).
4651                         replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
4652                         replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
4653                         replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
4654                         replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
4655                         replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
4656         }
4657         
4658         
4659         
4660         /**
4661          * Draw the table for the first time, adding all required features
4662          *  @param {object} settings dataTables settings object
4663          *  @memberof DataTable#oApi
4664          */
4665         function _fnInitialise ( settings )
4666         {
4667                 var i, iLen, iAjaxStart=settings.iInitDisplayStart;
4668                 var columns = settings.aoColumns, column;
4669                 var features = settings.oFeatures;
4670                 var deferLoading = settings.bDeferLoading; // value modified by the draw
4671         
4672                 /* Ensure that the table data is fully initialised */
4673                 if ( ! settings.bInitialised ) {
4674                         setTimeout( function(){ _fnInitialise( settings ); }, 200 );
4675                         return;
4676                 }
4677         
4678                 /* Show the display HTML options */
4679                 _fnAddOptionsHtml( settings );
4680         
4681                 /* Build and draw the header / footer for the table */
4682                 _fnBuildHead( settings );
4683                 _fnDrawHead( settings, settings.aoHeader );
4684                 _fnDrawHead( settings, settings.aoFooter );
4685         
4686                 /* Okay to show that something is going on now */
4687                 _fnProcessingDisplay( settings, true );
4688         
4689                 /* Calculate sizes for columns */
4690                 if ( features.bAutoWidth ) {
4691                         _fnCalculateColumnWidths( settings );
4692                 }
4693         
4694                 for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
4695                         column = columns[i];
4696         
4697                         if ( column.sWidth ) {
4698                                 column.nTh.style.width = _fnStringToCss( column.sWidth );
4699                         }
4700                 }
4701         
4702                 _fnCallbackFire( settings, null, 'preInit', [settings] );
4703         
4704                 // If there is default sorting required - let's do it. The sort function
4705                 // will do the drawing for us. Otherwise we draw the table regardless of the
4706                 // Ajax source - this allows the table to look initialised for Ajax sourcing
4707                 // data (show 'loading' message possibly)
4708                 _fnReDraw( settings );
4709         
4710                 // Server-side processing init complete is done by _fnAjaxUpdateDraw
4711                 var dataSrc = _fnDataSource( settings );
4712                 if ( dataSrc != 'ssp' || deferLoading ) {
4713                         // if there is an ajax source load the data
4714                         if ( dataSrc == 'ajax' ) {
4715                                 _fnBuildAjax( settings, [], function(json) {
4716                                         var aData = _fnAjaxDataSrc( settings, json );
4717         
4718                                         // Got the data - add it to the table
4719                                         for ( i=0 ; i<aData.length ; i++ ) {
4720                                                 _fnAddData( settings, aData[i] );
4721                                         }
4722         
4723                                         // Reset the init display for cookie saving. We've already done
4724                                         // a filter, and therefore cleared it before. So we need to make
4725                                         // it appear 'fresh'
4726                                         settings.iInitDisplayStart = iAjaxStart;
4727         
4728                                         _fnReDraw( settings );
4729         
4730                                         _fnProcessingDisplay( settings, false );
4731                                         _fnInitComplete( settings, json );
4732                                 }, settings );
4733                         }
4734                         else {
4735                                 _fnProcessingDisplay( settings, false );
4736                                 _fnInitComplete( settings );
4737                         }
4738                 }
4739         }
4740         
4741         
4742         /**
4743          * Draw the table for the first time, adding all required features
4744          *  @param {object} oSettings dataTables settings object
4745          *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
4746          *    with client-side processing (optional)
4747          *  @memberof DataTable#oApi
4748          */
4749         function _fnInitComplete ( settings, json )
4750         {
4751                 settings._bInitComplete = true;
4752         
4753                 // When data was added after the initialisation (data or Ajax) we need to
4754                 // calculate the column sizing
4755                 if ( json || settings.oInit.aaData ) {
4756                         _fnAdjustColumnSizing( settings );
4757                 }
4758         
4759                 _fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
4760                 _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
4761         }
4762         
4763         
4764         function _fnLengthChange ( settings, val )
4765         {
4766                 var len = parseInt( val, 10 );
4767                 settings._iDisplayLength = len;
4768         
4769                 _fnLengthOverflow( settings );
4770         
4771                 // Fire length change event
4772                 _fnCallbackFire( settings, null, 'length', [settings, len] );
4773         }
4774         
4775         
4776         /**
4777          * Generate the node required for user display length changing
4778          *  @param {object} settings dataTables settings object
4779          *  @returns {node} Display length feature node
4780          *  @memberof DataTable#oApi
4781          */
4782         function _fnFeatureHtmlLength ( settings )
4783         {
4784                 var
4785                         classes  = settings.oClasses,
4786                         tableId  = settings.sTableId,
4787                         menu     = settings.aLengthMenu,
4788                         d2       = $.isArray( menu[0] ),
4789                         lengths  = d2 ? menu[0] : menu,
4790                         language = d2 ? menu[1] : menu;
4791         
4792                 var select = $('<select/>', {
4793                         'name':          tableId+'_length',
4794                         'aria-controls': tableId,
4795                         'class':         classes.sLengthSelect
4796                 } );
4797         
4798                 for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
4799                         select[0][ i ] = new Option( language[i], lengths[i] );
4800                 }
4801         
4802                 var div = $('<div><label/></div>').addClass( classes.sLength );
4803                 if ( ! settings.aanFeatures.l ) {
4804                         div[0].id = tableId+'_length';
4805                 }
4806         
4807                 div.children().append(
4808                         settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
4809                 );
4810         
4811                 // Can't use `select` variable as user might provide their own and the
4812                 // reference is broken by the use of outerHTML
4813                 $('select', div)
4814                         .val( settings._iDisplayLength )
4815                         .bind( 'change.DT', function(e) {
4816                                 _fnLengthChange( settings, $(this).val() );
4817                                 _fnDraw( settings );
4818                         } );
4819         
4820                 // Update node value whenever anything changes the table's length
4821                 $(settings.nTable).bind( 'length.dt.DT', function (e, s, len) {
4822                         if ( settings === s ) {
4823                                 $('select', div).val( len );
4824                         }
4825                 } );
4826         
4827                 return div[0];
4828         }
4829         
4830         
4831         
4832         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4833          * Note that most of the paging logic is done in
4834          * DataTable.ext.pager
4835          */
4836         
4837         /**
4838          * Generate the node required for default pagination
4839          *  @param {object} oSettings dataTables settings object
4840          *  @returns {node} Pagination feature node
4841          *  @memberof DataTable#oApi
4842          */
4843         function _fnFeatureHtmlPaginate ( settings )
4844         {
4845                 var
4846                         type   = settings.sPaginationType,
4847                         plugin = DataTable.ext.pager[ type ],
4848                         modern = typeof plugin === 'function',
4849                         redraw = function( settings ) {
4850                                 _fnDraw( settings );
4851                         },
4852                         node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
4853                         features = settings.aanFeatures;
4854         
4855                 if ( ! modern ) {
4856                         plugin.fnInit( settings, node, redraw );
4857                 }
4858         
4859                 /* Add a draw callback for the pagination on first instance, to update the paging display */
4860                 if ( ! features.p )
4861                 {
4862                         node.id = settings.sTableId+'_paginate';
4863         
4864                         settings.aoDrawCallback.push( {
4865                                 "fn": function( settings ) {
4866                                         if ( modern ) {
4867                                                 var
4868                                                         start      = settings._iDisplayStart,
4869                                                         len        = settings._iDisplayLength,
4870                                                         visRecords = settings.fnRecordsDisplay(),
4871                                                         all        = len === -1,
4872                                                         page = all ? 0 : Math.ceil( start / len ),
4873                                                         pages = all ? 1 : Math.ceil( visRecords / len ),
4874                                                         buttons = plugin(page, pages),
4875                                                         i, ien;
4876         
4877                                                 for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
4878                                                         _fnRenderer( settings, 'pageButton' )(
4879                                                                 settings, features.p[i], i, buttons, page, pages
4880                                                         );
4881                                                 }
4882                                         }
4883                                         else {
4884                                                 plugin.fnUpdate( settings, redraw );
4885                                         }
4886                                 },
4887                                 "sName": "pagination"
4888                         } );
4889                 }
4890         
4891                 return node;
4892         }
4893         
4894         
4895         /**
4896          * Alter the display settings to change the page
4897          *  @param {object} settings DataTables settings object
4898          *  @param {string|int} action Paging action to take: "first", "previous",
4899          *    "next" or "last" or page number to jump to (integer)
4900          *  @param [bool] redraw Automatically draw the update or not
4901          *  @returns {bool} true page has changed, false - no change
4902          *  @memberof DataTable#oApi
4903          */
4904         function _fnPageChange ( settings, action, redraw )
4905         {
4906                 var
4907                         start     = settings._iDisplayStart,
4908                         len       = settings._iDisplayLength,
4909                         records   = settings.fnRecordsDisplay();
4910         
4911                 if ( records === 0 || len === -1 )
4912                 {
4913                         start = 0;
4914                 }
4915                 else if ( typeof action === "number" )
4916                 {
4917                         start = action * len;
4918         
4919                         if ( start > records )
4920                         {
4921                                 start = 0;
4922                         }
4923                 }
4924                 else if ( action == "first" )
4925                 {
4926                         start = 0;
4927                 }
4928                 else if ( action == "previous" )
4929                 {
4930                         start = len >= 0 ?
4931                                 start - len :
4932                                 0;
4933         
4934                         if ( start < 0 )
4935                         {
4936                           start = 0;
4937                         }
4938                 }
4939                 else if ( action == "next" )
4940                 {
4941                         if ( start + len < records )
4942                         {
4943                                 start += len;
4944                         }
4945                 }
4946                 else if ( action == "last" )
4947                 {
4948                         start = Math.floor( (records-1) / len) * len;
4949                 }
4950                 else
4951                 {
4952                         _fnLog( settings, 0, "Unknown paging action: "+action, 5 );
4953                 }
4954         
4955                 var changed = settings._iDisplayStart !== start;
4956                 settings._iDisplayStart = start;
4957         
4958                 if ( changed ) {
4959                         _fnCallbackFire( settings, null, 'page', [settings] );
4960         
4961                         if ( redraw ) {
4962                                 _fnDraw( settings );
4963                         }
4964                 }
4965         
4966                 return changed;
4967         }
4968         
4969         
4970         
4971         /**
4972          * Generate the node required for the processing node
4973          *  @param {object} settings dataTables settings object
4974          *  @returns {node} Processing element
4975          *  @memberof DataTable#oApi
4976          */
4977         function _fnFeatureHtmlProcessing ( settings )
4978         {
4979                 return $('<div/>', {
4980                                 'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
4981                                 'class': settings.oClasses.sProcessing
4982                         } )
4983                         .html( settings.oLanguage.sProcessing )
4984                         .insertBefore( settings.nTable )[0];
4985         }
4986         
4987         
4988         /**
4989          * Display or hide the processing indicator
4990          *  @param {object} settings dataTables settings object
4991          *  @param {bool} show Show the processing indicator (true) or not (false)
4992          *  @memberof DataTable#oApi
4993          */
4994         function _fnProcessingDisplay ( settings, show )
4995         {
4996                 if ( settings.oFeatures.bProcessing ) {
4997                         $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
4998                 }
4999         
5000                 _fnCallbackFire( settings, null, 'processing', [settings, show] );
5001         }
5002         
5003         /**
5004          * Add any control elements for the table - specifically scrolling
5005          *  @param {object} settings dataTables settings object
5006          *  @returns {node} Node to add to the DOM
5007          *  @memberof DataTable#oApi
5008          */
5009         function _fnFeatureHtmlTable ( settings )
5010         {
5011                 var table = $(settings.nTable);
5012         
5013                 // Add the ARIA grid role to the table
5014                 table.attr( 'role', 'grid' );
5015         
5016                 // Scrolling from here on in
5017                 var scroll = settings.oScroll;
5018         
5019                 if ( scroll.sX === '' && scroll.sY === '' ) {
5020                         return settings.nTable;
5021                 }
5022         
5023                 var scrollX = scroll.sX;
5024                 var scrollY = scroll.sY;
5025                 var classes = settings.oClasses;
5026                 var caption = table.children('caption');
5027                 var captionSide = caption.length ? caption[0]._captionSide : null;
5028                 var headerClone = $( table[0].cloneNode(false) );
5029                 var footerClone = $( table[0].cloneNode(false) );
5030                 var footer = table.children('tfoot');
5031                 var _div = '<div/>';
5032                 var size = function ( s ) {
5033                         return !s ? null : _fnStringToCss( s );
5034                 };
5035         
5036                 if ( ! footer.length ) {
5037                         footer = null;
5038                 }
5039         
5040                 /*
5041                  * The HTML structure that we want to generate in this function is:
5042                  *  div - scroller
5043                  *    div - scroll head
5044                  *      div - scroll head inner
5045                  *        table - scroll head table
5046                  *          thead - thead
5047                  *    div - scroll body
5048                  *      table - table (master table)
5049                  *        thead - thead clone for sizing
5050                  *        tbody - tbody
5051                  *    div - scroll foot
5052                  *      div - scroll foot inner
5053                  *        table - scroll foot table
5054                  *          tfoot - tfoot
5055                  */
5056                 var scroller = $( _div, { 'class': classes.sScrollWrapper } )
5057                         .append(
5058                                 $(_div, { 'class': classes.sScrollHead } )
5059                                         .css( {
5060                                                 overflow: 'hidden',
5061                                                 position: 'relative',
5062                                                 border: 0,
5063                                                 width: scrollX ? size(scrollX) : '100%'
5064                                         } )
5065                                         .append(
5066                                                 $(_div, { 'class': classes.sScrollHeadInner } )
5067                                                         .css( {
5068                                                                 'box-sizing': 'content-box',
5069                                                                 width: scroll.sXInner || '100%'
5070                                                         } )
5071                                                         .append(
5072                                                                 headerClone
5073                                                                         .removeAttr('id')
5074                                                                         .css( 'margin-left', 0 )
5075                                                                         .append( captionSide === 'top' ? caption : null )
5076                                                                         .append(
5077                                                                                 table.children('thead')
5078                                                                         )
5079                                                         )
5080                                         )
5081                         )
5082                         .append(
5083                                 $(_div, { 'class': classes.sScrollBody } )
5084                                         .css( {
5085                                                 position: 'relative',
5086                                                 overflow: 'auto',
5087                                                 width: size( scrollX )
5088                                         } )
5089                                         .append( table )
5090                         );
5091         
5092                 if ( footer ) {
5093                         scroller.append(
5094                                 $(_div, { 'class': classes.sScrollFoot } )
5095                                         .css( {
5096                                                 overflow: 'hidden',
5097                                                 border: 0,
5098                                                 width: scrollX ? size(scrollX) : '100%'
5099                                         } )
5100                                         .append(
5101                                                 $(_div, { 'class': classes.sScrollFootInner } )
5102                                                         .append(
5103                                                                 footerClone
5104                                                                         .removeAttr('id')
5105                                                                         .css( 'margin-left', 0 )
5106                                                                         .append( captionSide === 'bottom' ? caption : null )
5107                                                                         .append(
5108                                                                                 table.children('tfoot')
5109                                                                         )
5110                                                         )
5111                                         )
5112                         );
5113                 }
5114         
5115                 var children = scroller.children();
5116                 var scrollHead = children[0];
5117                 var scrollBody = children[1];
5118                 var scrollFoot = footer ? children[2] : null;
5119         
5120                 // When the body is scrolled, then we also want to scroll the headers
5121                 if ( scrollX ) {
5122                         $(scrollBody).on( 'scroll.DT', function (e) {
5123                                 var scrollLeft = this.scrollLeft;
5124         
5125                                 scrollHead.scrollLeft = scrollLeft;
5126         
5127                                 if ( footer ) {
5128                                         scrollFoot.scrollLeft = scrollLeft;
5129                                 }
5130                         } );
5131                 }
5132         
5133                 $(scrollBody).css(
5134                         scrollY && scroll.bCollapse ? 'max-height' : 'height', 
5135                         scrollY
5136                 );
5137         
5138                 settings.nScrollHead = scrollHead;
5139                 settings.nScrollBody = scrollBody;
5140                 settings.nScrollFoot = scrollFoot;
5141         
5142                 // On redraw - align columns
5143                 settings.aoDrawCallback.push( {
5144                         "fn": _fnScrollDraw,
5145                         "sName": "scrolling"
5146                 } );
5147         
5148                 return scroller[0];
5149         }
5150         
5151         
5152         
5153         /**
5154          * Update the header, footer and body tables for resizing - i.e. column
5155          * alignment.
5156          *
5157          * Welcome to the most horrible function DataTables. The process that this
5158          * function follows is basically:
5159          *   1. Re-create the table inside the scrolling div
5160          *   2. Take live measurements from the DOM
5161          *   3. Apply the measurements to align the columns
5162          *   4. Clean up
5163          *
5164          *  @param {object} settings dataTables settings object
5165          *  @memberof DataTable#oApi
5166          */
5167         function _fnScrollDraw ( settings )
5168         {
5169                 // Given that this is such a monster function, a lot of variables are use
5170                 // to try and keep the minimised size as small as possible
5171                 var
5172                         scroll         = settings.oScroll,
5173                         scrollX        = scroll.sX,
5174                         scrollXInner   = scroll.sXInner,
5175                         scrollY        = scroll.sY,
5176                         barWidth       = scroll.iBarWidth,
5177                         divHeader      = $(settings.nScrollHead),
5178                         divHeaderStyle = divHeader[0].style,
5179                         divHeaderInner = divHeader.children('div'),
5180                         divHeaderInnerStyle = divHeaderInner[0].style,
5181                         divHeaderTable = divHeaderInner.children('table'),
5182                         divBodyEl      = settings.nScrollBody,
5183                         divBody        = $(divBodyEl),
5184                         divBodyStyle   = divBodyEl.style,
5185                         divFooter      = $(settings.nScrollFoot),
5186                         divFooterInner = divFooter.children('div'),
5187                         divFooterTable = divFooterInner.children('table'),
5188                         header         = $(settings.nTHead),
5189                         table          = $(settings.nTable),
5190                         tableEl        = table[0],
5191                         tableStyle     = tableEl.style,
5192                         footer         = settings.nTFoot ? $(settings.nTFoot) : null,
5193                         browser        = settings.oBrowser,
5194                         ie67           = browser.bScrollOversize,
5195                         dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
5196                         headerTrgEls, footerTrgEls,
5197                         headerSrcEls, footerSrcEls,
5198                         headerCopy, footerCopy,
5199                         headerWidths=[], footerWidths=[],
5200                         headerContent=[], footerContent=[],
5201                         idx, correction, sanityWidth,
5202                         zeroOut = function(nSizer) {
5203                                 var style = nSizer.style;
5204                                 style.paddingTop = "0";
5205                                 style.paddingBottom = "0";
5206                                 style.borderTopWidth = "0";
5207                                 style.borderBottomWidth = "0";
5208                                 style.height = 0;
5209                         };
5210         
5211                 // If the scrollbar visibility has changed from the last draw, we need to
5212                 // adjust the column sizes as the table width will have changed to account
5213                 // for the scrollbar
5214                 var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
5215                 
5216                 if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
5217                         settings.scrollBarVis = scrollBarVis;
5218                         _fnAdjustColumnSizing( settings );
5219                         return; // adjust column sizing will call this function again
5220                 }
5221                 else {
5222                         settings.scrollBarVis = scrollBarVis;
5223                 }
5224         
5225                 /*
5226                  * 1. Re-create the table inside the scrolling div
5227                  */
5228         
5229                 // Remove the old minimised thead and tfoot elements in the inner table
5230                 table.children('thead, tfoot').remove();
5231         
5232                 if ( footer ) {
5233                         footerCopy = footer.clone().prependTo( table );
5234                         footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
5235                         footerSrcEls = footerCopy.find('tr');
5236                 }
5237         
5238                 // Clone the current header and footer elements and then place it into the inner table
5239                 headerCopy = header.clone().prependTo( table );
5240                 headerTrgEls = header.find('tr'); // original header is in its own table
5241                 headerSrcEls = headerCopy.find('tr');
5242                 headerCopy.find('th, td').removeAttr('tabindex');
5243         
5244         
5245                 /*
5246                  * 2. Take live measurements from the DOM - do not alter the DOM itself!
5247                  */
5248         
5249                 // Remove old sizing and apply the calculated column widths
5250                 // Get the unique column headers in the newly created (cloned) header. We want to apply the
5251                 // calculated sizes to this header
5252                 if ( ! scrollX )
5253                 {
5254                         divBodyStyle.width = '100%';
5255                         divHeader[0].style.width = '100%';
5256                 }
5257         
5258                 $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
5259                         idx = _fnVisibleToColumnIndex( settings, i );
5260                         el.style.width = settings.aoColumns[idx].sWidth;
5261                 } );
5262         
5263                 if ( footer ) {
5264                         _fnApplyToChildren( function(n) {
5265                                 n.style.width = "";
5266                         }, footerSrcEls );
5267                 }
5268         
5269                 // Size the table as a whole
5270                 sanityWidth = table.outerWidth();
5271                 if ( scrollX === "" ) {
5272                         // No x scrolling
5273                         tableStyle.width = "100%";
5274         
5275                         // IE7 will make the width of the table when 100% include the scrollbar
5276                         // - which is shouldn't. When there is a scrollbar we need to take this
5277                         // into account.
5278                         if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
5279                                 divBody.css('overflow-y') == "scroll")
5280                         ) {
5281                                 tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
5282                         }
5283         
5284                         // Recalculate the sanity width
5285                         sanityWidth = table.outerWidth();
5286                 }
5287                 else if ( scrollXInner !== "" ) {
5288                         // legacy x scroll inner has been given - use it
5289                         tableStyle.width = _fnStringToCss(scrollXInner);
5290         
5291                         // Recalculate the sanity width
5292                         sanityWidth = table.outerWidth();
5293                 }
5294         
5295                 // Hidden header should have zero height, so remove padding and borders. Then
5296                 // set the width based on the real headers
5297         
5298                 // Apply all styles in one pass
5299                 _fnApplyToChildren( zeroOut, headerSrcEls );
5300         
5301                 // Read all widths in next pass
5302                 _fnApplyToChildren( function(nSizer) {
5303                         headerContent.push( nSizer.innerHTML );
5304                         headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5305                 }, headerSrcEls );
5306         
5307                 // Apply all widths in final pass
5308                 _fnApplyToChildren( function(nToSize, i) {
5309                         // Only apply widths to the DataTables detected header cells - this
5310                         // prevents complex headers from having contradictory sizes applied
5311                         if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) {
5312                                 nToSize.style.width = headerWidths[i];
5313                         }
5314                 }, headerTrgEls );
5315         
5316                 $(headerSrcEls).height(0);
5317         
5318                 /* Same again with the footer if we have one */
5319                 if ( footer )
5320                 {
5321                         _fnApplyToChildren( zeroOut, footerSrcEls );
5322         
5323                         _fnApplyToChildren( function(nSizer) {
5324                                 footerContent.push( nSizer.innerHTML );
5325                                 footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5326                         }, footerSrcEls );
5327         
5328                         _fnApplyToChildren( function(nToSize, i) {
5329                                 nToSize.style.width = footerWidths[i];
5330                         }, footerTrgEls );
5331         
5332                         $(footerSrcEls).height(0);
5333                 }
5334         
5335         
5336                 /*
5337                  * 3. Apply the measurements
5338                  */
5339         
5340                 // "Hide" the header and footer that we used for the sizing. We need to keep
5341                 // the content of the cell so that the width applied to the header and body
5342                 // both match, but we want to hide it completely. We want to also fix their
5343                 // width to what they currently are
5344                 _fnApplyToChildren( function(nSizer, i) {
5345                         nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
5346                         nSizer.style.width = headerWidths[i];
5347                 }, headerSrcEls );
5348         
5349                 if ( footer )
5350                 {
5351                         _fnApplyToChildren( function(nSizer, i) {
5352                                 nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+footerContent[i]+'</div>';
5353                                 nSizer.style.width = footerWidths[i];
5354                         }, footerSrcEls );
5355                 }
5356         
5357                 // Sanity check that the table is of a sensible width. If not then we are going to get
5358                 // misalignment - try to prevent this by not allowing the table to shrink below its min width
5359                 if ( table.outerWidth() < sanityWidth )
5360                 {
5361                         // The min width depends upon if we have a vertical scrollbar visible or not */
5362                         correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
5363                                 divBody.css('overflow-y') == "scroll")) ?
5364                                         sanityWidth+barWidth :
5365                                         sanityWidth;
5366         
5367                         // IE6/7 are a law unto themselves...
5368                         if ( ie67 && (divBodyEl.scrollHeight >
5369                                 divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
5370                         ) {
5371                                 tableStyle.width = _fnStringToCss( correction-barWidth );
5372                         }
5373         
5374                         // And give the user a warning that we've stopped the table getting too small
5375                         if ( scrollX === "" || scrollXInner !== "" ) {
5376                                 _fnLog( settings, 1, 'Possible column misalignment', 6 );
5377                         }
5378                 }
5379                 else
5380                 {
5381                         correction = '100%';
5382                 }
5383         
5384                 // Apply to the container elements
5385                 divBodyStyle.width = _fnStringToCss( correction );
5386                 divHeaderStyle.width = _fnStringToCss( correction );
5387         
5388                 if ( footer ) {
5389                         settings.nScrollFoot.style.width = _fnStringToCss( correction );
5390                 }
5391         
5392         
5393                 /*
5394                  * 4. Clean up
5395                  */
5396                 if ( ! scrollY ) {
5397                         /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
5398                          * the scrollbar height from the visible display, rather than adding it on. We need to
5399                          * set the height in order to sort this. Don't want to do it in any other browsers.
5400                          */
5401                         if ( ie67 ) {
5402                                 divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
5403                         }
5404                 }
5405         
5406                 /* Finally set the width's of the header and footer tables */
5407                 var iOuterWidth = table.outerWidth();
5408                 divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
5409                 divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
5410         
5411                 // Figure out if there are scrollbar present - if so then we need a the header and footer to
5412                 // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
5413                 var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
5414                 var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
5415                 divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
5416         
5417                 if ( footer ) {
5418                         divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
5419                         divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
5420                         divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
5421                 }
5422         
5423                 // Correct DOM ordering for colgroup - comes before the thead
5424                 table.children('colgroup').insertBefore( table.children('thead') );
5425         
5426                 /* Adjust the position of the header in case we loose the y-scrollbar */
5427                 divBody.scroll();
5428         
5429                 // If sorting or filtering has occurred, jump the scrolling back to the top
5430                 // only if we aren't holding the position
5431                 if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
5432                         divBodyEl.scrollTop = 0;
5433                 }
5434         }
5435         
5436         
5437         
5438         /**
5439          * Apply a given function to the display child nodes of an element array (typically
5440          * TD children of TR rows
5441          *  @param {function} fn Method to apply to the objects
5442          *  @param array {nodes} an1 List of elements to look through for display children
5443          *  @param array {nodes} an2 Another list (identical structure to the first) - optional
5444          *  @memberof DataTable#oApi
5445          */
5446         function _fnApplyToChildren( fn, an1, an2 )
5447         {
5448                 var index=0, i=0, iLen=an1.length;
5449                 var nNode1, nNode2;
5450         
5451                 while ( i < iLen ) {
5452                         nNode1 = an1[i].firstChild;
5453                         nNode2 = an2 ? an2[i].firstChild : null;
5454         
5455                         while ( nNode1 ) {
5456                                 if ( nNode1.nodeType === 1 ) {
5457                                         if ( an2 ) {
5458                                                 fn( nNode1, nNode2, index );
5459                                         }
5460                                         else {
5461                                                 fn( nNode1, index );
5462                                         }
5463         
5464                                         index++;
5465                                 }
5466         
5467                                 nNode1 = nNode1.nextSibling;
5468                                 nNode2 = an2 ? nNode2.nextSibling : null;
5469                         }
5470         
5471                         i++;
5472                 }
5473         }
5474         
5475         
5476         
5477         var __re_html_remove = /<.*?>/g;
5478         
5479         
5480         /**
5481          * Calculate the width of columns for the table
5482          *  @param {object} oSettings dataTables settings object
5483          *  @memberof DataTable#oApi
5484          */
5485         function _fnCalculateColumnWidths ( oSettings )
5486         {
5487                 var
5488                         table = oSettings.nTable,
5489                         columns = oSettings.aoColumns,
5490                         scroll = oSettings.oScroll,
5491                         scrollY = scroll.sY,
5492                         scrollX = scroll.sX,
5493                         scrollXInner = scroll.sXInner,
5494                         columnCount = columns.length,
5495                         visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
5496                         headerCells = $('th', oSettings.nTHead),
5497                         tableWidthAttr = table.getAttribute('width'), // from DOM element
5498                         tableContainer = table.parentNode,
5499                         userInputs = false,
5500                         i, column, columnIdx, width, outerWidth,
5501                         browser = oSettings.oBrowser,
5502                         ie67 = browser.bScrollOversize;
5503         
5504                 var styleWidth = table.style.width;
5505                 if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
5506                         tableWidthAttr = styleWidth;
5507                 }
5508         
5509                 /* Convert any user input sizes into pixel sizes */
5510                 for ( i=0 ; i<visibleColumns.length ; i++ ) {
5511                         column = columns[ visibleColumns[i] ];
5512         
5513                         if ( column.sWidth !== null ) {
5514                                 column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
5515         
5516                                 userInputs = true;
5517                         }
5518                 }
5519         
5520                 /* If the number of columns in the DOM equals the number that we have to
5521                  * process in DataTables, then we can use the offsets that are created by
5522                  * the web- browser. No custom sizes can be set in order for this to happen,
5523                  * nor scrolling used
5524                  */
5525                 if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
5526                      columnCount == _fnVisbleColumns( oSettings ) &&
5527                      columnCount == headerCells.length
5528                 ) {
5529                         for ( i=0 ; i<columnCount ; i++ ) {
5530                                 var colIdx = _fnVisibleToColumnIndex( oSettings, i );
5531         
5532                                 if ( colIdx !== null ) {
5533                                         columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
5534                                 }
5535                         }
5536                 }
5537                 else
5538                 {
5539                         // Otherwise construct a single row, worst case, table with the widest
5540                         // node in the data, assign any user defined widths, then insert it into
5541                         // the DOM and allow the browser to do all the hard work of calculating
5542                         // table widths
5543                         var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
5544                                 .css( 'visibility', 'hidden' )
5545                                 .removeAttr( 'id' );
5546         
5547                         // Clean up the table body
5548                         tmpTable.find('tbody tr').remove();
5549                         var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5550         
5551                         // Clone the table header and footer - we can't use the header / footer
5552                         // from the cloned table, since if scrolling is active, the table's
5553                         // real header and footer are contained in different table tags
5554                         tmpTable.find('thead, tfoot').remove();
5555                         tmpTable
5556                                 .append( $(oSettings.nTHead).clone() )
5557                                 .append( $(oSettings.nTFoot).clone() );
5558         
5559                         // Remove any assigned widths from the footer (from scrolling)
5560                         tmpTable.find('tfoot th, tfoot td').css('width', '');
5561         
5562                         // Apply custom sizing to the cloned header
5563                         headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
5564         
5565                         for ( i=0 ; i<visibleColumns.length ; i++ ) {
5566                                 column = columns[ visibleColumns[i] ];
5567         
5568                                 headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
5569                                         _fnStringToCss( column.sWidthOrig ) :
5570                                         '';
5571         
5572                                 // For scrollX we need to force the column width otherwise the
5573                                 // browser will collapse it. If this width is smaller than the
5574                                 // width the column requires, then it will have no effect
5575                                 if ( column.sWidthOrig && scrollX ) {
5576                                         $( headerCells[i] ).append( $('<div/>').css( {
5577                                                 width: column.sWidthOrig,
5578                                                 margin: 0,
5579                                                 padding: 0,
5580                                                 border: 0,
5581                                                 height: 1
5582                                         } ) );
5583                                 }
5584                         }
5585         
5586                         // Find the widest cell for each column and put it into the table
5587                         if ( oSettings.aoData.length ) {
5588                                 for ( i=0 ; i<visibleColumns.length ; i++ ) {
5589                                         columnIdx = visibleColumns[i];
5590                                         column = columns[ columnIdx ];
5591         
5592                                         $( _fnGetWidestNode( oSettings, columnIdx ) )
5593                                                 .clone( false )
5594                                                 .append( column.sContentPadding )
5595                                                 .appendTo( tr );
5596                                 }
5597                         }
5598         
5599                         // Tidy the temporary table - remove name attributes so there aren't
5600                         // duplicated in the dom (radio elements for example)
5601                         $('[name]', tmpTable).removeAttr('name');
5602         
5603                         // Table has been built, attach to the document so we can work with it.
5604                         // A holding element is used, positioned at the top of the container
5605                         // with minimal height, so it has no effect on if the container scrolls
5606                         // or not. Otherwise it might trigger scrolling when it actually isn't
5607                         // needed
5608                         var holder = $('<div/>').css( scrollX || scrollY ?
5609                                         {
5610                                                 position: 'absolute',
5611                                                 top: 0,
5612                                                 left: 0,
5613                                                 height: 1,
5614                                                 right: 0,
5615                                                 overflow: 'hidden'
5616                                         } :
5617                                         {}
5618                                 )
5619                                 .append( tmpTable )
5620                                 .appendTo( tableContainer );
5621         
5622                         // When scrolling (X or Y) we want to set the width of the table as 
5623                         // appropriate. However, when not scrolling leave the table width as it
5624                         // is. This results in slightly different, but I think correct behaviour
5625                         if ( scrollX && scrollXInner ) {
5626                                 tmpTable.width( scrollXInner );
5627                         }
5628                         else if ( scrollX ) {
5629                                 tmpTable.css( 'width', 'auto' );
5630                                 tmpTable.removeAttr('width');
5631         
5632                                 // If there is no width attribute or style, then allow the table to
5633                                 // collapse
5634                                 if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5635                                         tmpTable.width( tableContainer.clientWidth );
5636                                 }
5637                         }
5638                         else if ( scrollY ) {
5639                                 tmpTable.width( tableContainer.clientWidth );
5640                         }
5641                         else if ( tableWidthAttr ) {
5642                                 tmpTable.width( tableWidthAttr );
5643                         }
5644         
5645                         // Get the width of each column in the constructed table - we need to
5646                         // know the inner width (so it can be assigned to the other table's
5647                         // cells) and the outer width so we can calculate the full width of the
5648                         // table. This is safe since DataTables requires a unique cell for each
5649                         // column, but if ever a header can span multiple columns, this will
5650                         // need to be modified.
5651                         var total = 0;
5652                         for ( i=0 ; i<visibleColumns.length ; i++ ) {
5653                                 var cell = $(headerCells[i]);
5654                                 var border = cell.outerWidth() - cell.width();
5655         
5656                                 // Use getBounding... where possible (not IE8-) because it can give
5657                                 // sub-pixel accuracy, which we then want to round up!
5658                                 var bounding = browser.bBounding ?
5659                                         Math.ceil( headerCells[i].getBoundingClientRect().width ) :
5660                                         cell.outerWidth();
5661         
5662                                 // Total is tracked to remove any sub-pixel errors as the outerWidth
5663                                 // of the table might not equal the total given here (IE!).
5664                                 total += bounding;
5665         
5666                                 // Width for each column to use
5667                                 columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
5668                         }
5669         
5670                         table.style.width = _fnStringToCss( total );
5671         
5672                         // Finished with the table - ditch it
5673                         holder.remove();
5674                 }
5675         
5676                 // If there is a width attr, we want to attach an event listener which
5677                 // allows the table sizing to automatically adjust when the window is
5678                 // resized. Use the width attr rather than CSS, since we can't know if the
5679                 // CSS is a relative value or absolute - DOM read is always px.
5680                 if ( tableWidthAttr ) {
5681                         table.style.width = _fnStringToCss( tableWidthAttr );
5682                 }
5683         
5684                 if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5685                         var bindResize = function () {
5686                                 $(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5687                                         _fnAdjustColumnSizing( oSettings );
5688                                 } ) );
5689                         };
5690         
5691                         // IE6/7 will crash if we bind a resize event handler on page load.
5692                         // To be removed in 1.11 which drops IE6/7 support
5693                         if ( ie67 ) {
5694                                 setTimeout( bindResize, 1000 );
5695                         }
5696                         else {
5697                                 bindResize();
5698                         }
5699         
5700                         oSettings._reszEvt = true;
5701                 }
5702         }
5703         
5704         
5705         /**
5706          * Throttle the calls to a function. Arguments and context are maintained for
5707          * the throttled function
5708          *  @param {function} fn Function to be called
5709          *  @param {int} [freq=200] call frequency in mS
5710          *  @returns {function} wrapped function
5711          *  @memberof DataTable#oApi
5712          */
5713         var _fnThrottle = DataTable.util.throttle;
5714         
5715         
5716         /**
5717          * Convert a CSS unit width to pixels (e.g. 2em)
5718          *  @param {string} width width to be converted
5719          *  @param {node} parent parent to get the with for (required for relative widths) - optional
5720          *  @returns {int} width in pixels
5721          *  @memberof DataTable#oApi
5722          */
5723         function _fnConvertToWidth ( width, parent )
5724         {
5725                 if ( ! width ) {
5726                         return 0;
5727                 }
5728         
5729                 var n = $('<div/>')
5730                         .css( 'width', _fnStringToCss( width ) )
5731                         .appendTo( parent || document.body );
5732         
5733                 var val = n[0].offsetWidth;
5734                 n.remove();
5735         
5736                 return val;
5737         }
5738         
5739         
5740         /**
5741          * Get the widest node
5742          *  @param {object} settings dataTables settings object
5743          *  @param {int} colIdx column of interest
5744          *  @returns {node} widest table node
5745          *  @memberof DataTable#oApi
5746          */
5747         function _fnGetWidestNode( settings, colIdx )
5748         {
5749                 var idx = _fnGetMaxLenString( settings, colIdx );
5750                 if ( idx < 0 ) {
5751                         return null;
5752                 }
5753         
5754                 var data = settings.aoData[ idx ];
5755                 return ! data.nTr ? // Might not have been created when deferred rendering
5756                         $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
5757                         data.anCells[ colIdx ];
5758         }
5759         
5760         
5761         /**
5762          * Get the maximum strlen for each data column
5763          *  @param {object} settings dataTables settings object
5764          *  @param {int} colIdx column of interest
5765          *  @returns {string} max string length for each column
5766          *  @memberof DataTable#oApi
5767          */
5768         function _fnGetMaxLenString( settings, colIdx )
5769         {
5770                 var s, max=-1, maxIdx = -1;
5771         
5772                 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
5773                         s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
5774                         s = s.replace( __re_html_remove, '' );
5775                         s = s.replace( /&nbsp;/g, ' ' );
5776         
5777                         if ( s.length > max ) {
5778                                 max = s.length;
5779                                 maxIdx = i;
5780                         }
5781                 }
5782         
5783                 return maxIdx;
5784         }
5785         
5786         
5787         /**
5788          * Append a CSS unit (only if required) to a string
5789          *  @param {string} value to css-ify
5790          *  @returns {string} value with css unit
5791          *  @memberof DataTable#oApi
5792          */
5793         function _fnStringToCss( s )
5794         {
5795                 if ( s === null ) {
5796                         return '0px';
5797                 }
5798         
5799                 if ( typeof s == 'number' ) {
5800                         return s < 0 ?
5801                                 '0px' :
5802                                 s+'px';
5803                 }
5804         
5805                 // Check it has a unit character already
5806                 return s.match(/\d$/) ?
5807                         s+'px' :
5808                         s;
5809         }
5810         
5811         
5812         
5813         function _fnSortFlatten ( settings )
5814         {
5815                 var
5816                         i, iLen, k, kLen,
5817                         aSort = [],
5818                         aiOrig = [],
5819                         aoColumns = settings.aoColumns,
5820                         aDataSort, iCol, sType, srcCol,
5821                         fixed = settings.aaSortingFixed,
5822                         fixedObj = $.isPlainObject( fixed ),
5823                         nestedSort = [],
5824                         add = function ( a ) {
5825                                 if ( a.length && ! $.isArray( a[0] ) ) {
5826                                         // 1D array
5827                                         nestedSort.push( a );
5828                                 }
5829                                 else {
5830                                         // 2D array
5831                                         $.merge( nestedSort, a );
5832                                 }
5833                         };
5834         
5835                 // Build the sort array, with pre-fix and post-fix options if they have been
5836                 // specified
5837                 if ( $.isArray( fixed ) ) {
5838                         add( fixed );
5839                 }
5840         
5841                 if ( fixedObj && fixed.pre ) {
5842                         add( fixed.pre );
5843                 }
5844         
5845                 add( settings.aaSorting );
5846         
5847                 if (fixedObj && fixed.post ) {
5848                         add( fixed.post );
5849                 }
5850         
5851                 for ( i=0 ; i<nestedSort.length ; i++ )
5852                 {
5853                         srcCol = nestedSort[i][0];
5854                         aDataSort = aoColumns[ srcCol ].aDataSort;
5855         
5856                         for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
5857                         {
5858                                 iCol = aDataSort[k];
5859                                 sType = aoColumns[ iCol ].sType || 'string';
5860         
5861                                 if ( nestedSort[i]._idx === undefined ) {
5862                                         nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
5863                                 }
5864         
5865                                 aSort.push( {
5866                                         src:       srcCol,
5867                                         col:       iCol,
5868                                         dir:       nestedSort[i][1],
5869                                         index:     nestedSort[i]._idx,
5870                                         type:      sType,
5871                                         formatter: DataTable.ext.type.order[ sType+"-pre" ]
5872                                 } );
5873                         }
5874                 }
5875         
5876                 return aSort;
5877         }
5878         
5879         /**
5880          * Change the order of the table
5881          *  @param {object} oSettings dataTables settings object
5882          *  @memberof DataTable#oApi
5883          *  @todo This really needs split up!
5884          */
5885         function _fnSort ( oSettings )
5886         {
5887                 var
5888                         i, ien, iLen, j, jLen, k, kLen,
5889                         sDataType, nTh,
5890                         aiOrig = [],
5891                         oExtSort = DataTable.ext.type.order,
5892                         aoData = oSettings.aoData,
5893                         aoColumns = oSettings.aoColumns,
5894                         aDataSort, data, iCol, sType, oSort,
5895                         formatters = 0,
5896                         sortCol,
5897                         displayMaster = oSettings.aiDisplayMaster,
5898                         aSort;
5899         
5900                 // Resolve any column types that are unknown due to addition or invalidation
5901                 // @todo Can this be moved into a 'data-ready' handler which is called when
5902                 //   data is going to be used in the table?
5903                 _fnColumnTypes( oSettings );
5904         
5905                 aSort = _fnSortFlatten( oSettings );
5906         
5907                 for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
5908                         sortCol = aSort[i];
5909         
5910                         // Track if we can use the fast sort algorithm
5911                         if ( sortCol.formatter ) {
5912                                 formatters++;
5913                         }
5914         
5915                         // Load the data needed for the sort, for each cell
5916                         _fnSortData( oSettings, sortCol.col );
5917                 }
5918         
5919                 /* No sorting required if server-side or no sorting array */
5920                 if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
5921                 {
5922                         // Create a value - key array of the current row positions such that we can use their
5923                         // current position during the sort, if values match, in order to perform stable sorting
5924                         for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
5925                                 aiOrig[ displayMaster[i] ] = i;
5926                         }
5927         
5928                         /* Do the sort - here we want multi-column sorting based on a given data source (column)
5929                          * and sorting function (from oSort) in a certain direction. It's reasonably complex to
5930                          * follow on it's own, but this is what we want (example two column sorting):
5931                          *  fnLocalSorting = function(a,b){
5932                          *    var iTest;
5933                          *    iTest = oSort['string-asc']('data11', 'data12');
5934                          *      if (iTest !== 0)
5935                          *        return iTest;
5936                          *    iTest = oSort['numeric-desc']('data21', 'data22');
5937                          *    if (iTest !== 0)
5938                          *      return iTest;
5939                          *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
5940                          *  }
5941                          * Basically we have a test for each sorting column, if the data in that column is equal,
5942                          * test the next column. If all columns match, then we use a numeric sort on the row
5943                          * positions in the original data array to provide a stable sort.
5944                          *
5945                          * Note - I know it seems excessive to have two sorting methods, but the first is around
5946                          * 15% faster, so the second is only maintained for backwards compatibility with sorting
5947                          * methods which do not have a pre-sort formatting function.
5948                          */
5949                         if ( formatters === aSort.length ) {
5950                                 // All sort types have formatting functions
5951                                 displayMaster.sort( function ( a, b ) {
5952                                         var
5953                                                 x, y, k, test, sort,
5954                                                 len=aSort.length,
5955                                                 dataA = aoData[a]._aSortData,
5956                                                 dataB = aoData[b]._aSortData;
5957         
5958                                         for ( k=0 ; k<len ; k++ ) {
5959                                                 sort = aSort[k];
5960         
5961                                                 x = dataA[ sort.col ];
5962                                                 y = dataB[ sort.col ];
5963         
5964                                                 test = x<y ? -1 : x>y ? 1 : 0;
5965                                                 if ( test !== 0 ) {
5966                                                         return sort.dir === 'asc' ? test : -test;
5967                                                 }
5968                                         }
5969         
5970                                         x = aiOrig[a];
5971                                         y = aiOrig[b];
5972                                         return x<y ? -1 : x>y ? 1 : 0;
5973                                 } );
5974                         }
5975                         else {
5976                                 // Depreciated - remove in 1.11 (providing a plug-in option)
5977                                 // Not all sort types have formatting methods, so we have to call their sorting
5978                                 // methods.
5979                                 displayMaster.sort( function ( a, b ) {
5980                                         var
5981                                                 x, y, k, l, test, sort, fn,
5982                                                 len=aSort.length,
5983                                                 dataA = aoData[a]._aSortData,
5984                                                 dataB = aoData[b]._aSortData;
5985         
5986                                         for ( k=0 ; k<len ; k++ ) {
5987                                                 sort = aSort[k];
5988         
5989                                                 x = dataA[ sort.col ];
5990                                                 y = dataB[ sort.col ];
5991         
5992                                                 fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
5993                                                 test = fn( x, y );
5994                                                 if ( test !== 0 ) {
5995                                                         return test;
5996                                                 }
5997                                         }
5998         
5999                                         x = aiOrig[a];
6000                                         y = aiOrig[b];
6001                                         return x<y ? -1 : x>y ? 1 : 0;
6002                                 } );
6003                         }
6004                 }
6005         
6006                 /* Tell the draw function that we have sorted the data */
6007                 oSettings.bSorted = true;
6008         }
6009         
6010         
6011         function _fnSortAria ( settings )
6012         {
6013                 var label;
6014                 var nextSort;
6015                 var columns = settings.aoColumns;
6016                 var aSort = _fnSortFlatten( settings );
6017                 var oAria = settings.oLanguage.oAria;
6018         
6019                 // ARIA attributes - need to loop all columns, to update all (removing old
6020                 // attributes as needed)
6021                 for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
6022                 {
6023                         var col = columns[i];
6024                         var asSorting = col.asSorting;
6025                         var sTitle = col.sTitle.replace( /<.*?>/g, "" );
6026                         var th = col.nTh;
6027         
6028                         // IE7 is throwing an error when setting these properties with jQuery's
6029                         // attr() and removeAttr() methods...
6030                         th.removeAttribute('aria-sort');
6031         
6032                         /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
6033                         if ( col.bSortable ) {
6034                                 if ( aSort.length > 0 && aSort[0].col == i ) {
6035                                         th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
6036                                         nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
6037                                 }
6038                                 else {
6039                                         nextSort = asSorting[0];
6040                                 }
6041         
6042                                 label = sTitle + ( nextSort === "asc" ?
6043                                         oAria.sSortAscending :
6044                                         oAria.sSortDescending
6045                                 );
6046                         }
6047                         else {
6048                                 label = sTitle;
6049                         }
6050         
6051                         th.setAttribute('aria-label', label);
6052                 }
6053         }
6054         
6055         
6056         /**
6057          * Function to run on user sort request
6058          *  @param {object} settings dataTables settings object
6059          *  @param {node} attachTo node to attach the handler to
6060          *  @param {int} colIdx column sorting index
6061          *  @param {boolean} [append=false] Append the requested sort to the existing
6062          *    sort if true (i.e. multi-column sort)
6063          *  @param {function} [callback] callback function
6064          *  @memberof DataTable#oApi
6065          */
6066         function _fnSortListener ( settings, colIdx, append, callback )
6067         {
6068                 var col = settings.aoColumns[ colIdx ];
6069                 var sorting = settings.aaSorting;
6070                 var asSorting = col.asSorting;
6071                 var nextSortIdx;
6072                 var next = function ( a, overflow ) {
6073                         var idx = a._idx;
6074                         if ( idx === undefined ) {
6075                                 idx = $.inArray( a[1], asSorting );
6076                         }
6077         
6078                         return idx+1 < asSorting.length ?
6079                                 idx+1 :
6080                                 overflow ?
6081                                         null :
6082                                         0;
6083                 };
6084         
6085                 // Convert to 2D array if needed
6086                 if ( typeof sorting[0] === 'number' ) {
6087                         sorting = settings.aaSorting = [ sorting ];
6088                 }
6089         
6090                 // If appending the sort then we are multi-column sorting
6091                 if ( append && settings.oFeatures.bSortMulti ) {
6092                         // Are we already doing some kind of sort on this column?
6093                         var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
6094         
6095                         if ( sortIdx !== -1 ) {
6096                                 // Yes, modify the sort
6097                                 nextSortIdx = next( sorting[sortIdx], true );
6098         
6099                                 if ( nextSortIdx === null && sorting.length === 1 ) {
6100                                         nextSortIdx = 0; // can't remove sorting completely
6101                                 }
6102         
6103                                 if ( nextSortIdx === null ) {
6104                                         sorting.splice( sortIdx, 1 );
6105                                 }
6106                                 else {
6107                                         sorting[sortIdx][1] = asSorting[ nextSortIdx ];
6108                                         sorting[sortIdx]._idx = nextSortIdx;
6109                                 }
6110                         }
6111                         else {
6112                                 // No sort on this column yet
6113                                 sorting.push( [ colIdx, asSorting[0], 0 ] );
6114                                 sorting[sorting.length-1]._idx = 0;
6115                         }
6116                 }
6117                 else if ( sorting.length && sorting[0][0] == colIdx ) {
6118                         // Single column - already sorting on this column, modify the sort
6119                         nextSortIdx = next( sorting[0] );
6120         
6121                         sorting.length = 1;
6122                         sorting[0][1] = asSorting[ nextSortIdx ];
6123                         sorting[0]._idx = nextSortIdx;
6124                 }
6125                 else {
6126                         // Single column - sort only on this column
6127                         sorting.length = 0;
6128                         sorting.push( [ colIdx, asSorting[0] ] );
6129                         sorting[0]._idx = 0;
6130                 }
6131         
6132                 // Run the sort by calling a full redraw
6133                 _fnReDraw( settings );
6134         
6135                 // callback used for async user interaction
6136                 if ( typeof callback == 'function' ) {
6137                         callback( settings );
6138                 }
6139         }
6140         
6141         
6142         /**
6143          * Attach a sort handler (click) to a node
6144          *  @param {object} settings dataTables settings object
6145          *  @param {node} attachTo node to attach the handler to
6146          *  @param {int} colIdx column sorting index
6147          *  @param {function} [callback] callback function
6148          *  @memberof DataTable#oApi
6149          */
6150         function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
6151         {
6152                 var col = settings.aoColumns[ colIdx ];
6153         
6154                 _fnBindAction( attachTo, {}, function (e) {
6155                         /* If the column is not sortable - don't to anything */
6156                         if ( col.bSortable === false ) {
6157                                 return;
6158                         }
6159         
6160                         // If processing is enabled use a timeout to allow the processing
6161                         // display to be shown - otherwise to it synchronously
6162                         if ( settings.oFeatures.bProcessing ) {
6163                                 _fnProcessingDisplay( settings, true );
6164         
6165                                 setTimeout( function() {
6166                                         _fnSortListener( settings, colIdx, e.shiftKey, callback );
6167         
6168                                         // In server-side processing, the draw callback will remove the
6169                                         // processing display
6170                                         if ( _fnDataSource( settings ) !== 'ssp' ) {
6171                                                 _fnProcessingDisplay( settings, false );
6172                                         }
6173                                 }, 0 );
6174                         }
6175                         else {
6176                                 _fnSortListener( settings, colIdx, e.shiftKey, callback );
6177                         }
6178                 } );
6179         }
6180         
6181         
6182         /**
6183          * Set the sorting classes on table's body, Note: it is safe to call this function
6184          * when bSort and bSortClasses are false
6185          *  @param {object} oSettings dataTables settings object
6186          *  @memberof DataTable#oApi
6187          */
6188         function _fnSortingClasses( settings )
6189         {
6190                 var oldSort = settings.aLastSort;
6191                 var sortClass = settings.oClasses.sSortColumn;
6192                 var sort = _fnSortFlatten( settings );
6193                 var features = settings.oFeatures;
6194                 var i, ien, colIdx;
6195         
6196                 if ( features.bSort && features.bSortClasses ) {
6197                         // Remove old sorting classes
6198                         for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
6199                                 colIdx = oldSort[i].src;
6200         
6201                                 // Remove column sorting
6202                                 $( _pluck( settings.aoData, 'anCells', colIdx ) )
6203                                         .removeClass( sortClass + (i<2 ? i+1 : 3) );
6204                         }
6205         
6206                         // Add new column sorting
6207                         for ( i=0, ien=sort.length ; i<ien ; i++ ) {
6208                                 colIdx = sort[i].src;
6209         
6210                                 $( _pluck( settings.aoData, 'anCells', colIdx ) )
6211                                         .addClass( sortClass + (i<2 ? i+1 : 3) );
6212                         }
6213                 }
6214         
6215                 settings.aLastSort = sort;
6216         }
6217         
6218         
6219         // Get the data to sort a column, be it from cache, fresh (populating the
6220         // cache), or from a sort formatter
6221         function _fnSortData( settings, idx )
6222         {
6223                 // Custom sorting function - provided by the sort data type
6224                 var column = settings.aoColumns[ idx ];
6225                 var customSort = DataTable.ext.order[ column.sSortDataType ];
6226                 var customData;
6227         
6228                 if ( customSort ) {
6229                         customData = customSort.call( settings.oInstance, settings, idx,
6230                                 _fnColumnIndexToVisible( settings, idx )
6231                         );
6232                 }
6233         
6234                 // Use / populate cache
6235                 var row, cellData;
6236                 var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
6237         
6238                 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6239                         row = settings.aoData[i];
6240         
6241                         if ( ! row._aSortData ) {
6242                                 row._aSortData = [];
6243                         }
6244         
6245                         if ( ! row._aSortData[idx] || customSort ) {
6246                                 cellData = customSort ?
6247                                         customData[i] : // If there was a custom sort function, use data from there
6248                                         _fnGetCellData( settings, i, idx, 'sort' );
6249         
6250                                 row._aSortData[ idx ] = formatter ?
6251                                         formatter( cellData ) :
6252                                         cellData;
6253                         }
6254                 }
6255         }
6256         
6257         
6258         
6259         /**
6260          * Save the state of a table
6261          *  @param {object} oSettings dataTables settings object
6262          *  @memberof DataTable#oApi
6263          */
6264         function _fnSaveState ( settings )
6265         {
6266                 if ( !settings.oFeatures.bStateSave || settings.bDestroying )
6267                 {
6268                         return;
6269                 }
6270         
6271                 /* Store the interesting variables */
6272                 var state = {
6273                         time:    +new Date(),
6274                         start:   settings._iDisplayStart,
6275                         length:  settings._iDisplayLength,
6276                         order:   $.extend( true, [], settings.aaSorting ),
6277                         search:  _fnSearchToCamel( settings.oPreviousSearch ),
6278                         columns: $.map( settings.aoColumns, function ( col, i ) {
6279                                 return {
6280                                         visible: col.bVisible,
6281                                         search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
6282                                 };
6283                         } )
6284                 };
6285         
6286                 _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
6287         
6288                 settings.oSavedState = state;
6289                 settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
6290         }
6291         
6292         
6293         /**
6294          * Attempt to load a saved table state
6295          *  @param {object} oSettings dataTables settings object
6296          *  @param {object} oInit DataTables init object so we can override settings
6297          *  @memberof DataTable#oApi
6298          */
6299         function _fnLoadState ( settings, oInit )
6300         {
6301                 var i, ien;
6302                 var columns = settings.aoColumns;
6303         
6304                 if ( ! settings.oFeatures.bStateSave ) {
6305                         return;
6306                 }
6307         
6308                 var state = settings.fnStateLoadCallback.call( settings.oInstance, settings );
6309                 if ( ! state || ! state.time ) {
6310                         return;
6311                 }
6312         
6313                 /* Allow custom and plug-in manipulation functions to alter the saved data set and
6314                  * cancelling of loading by returning false
6315                  */
6316                 var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, state] );
6317                 if ( $.inArray( false, abStateLoad ) !== -1 ) {
6318                         return;
6319                 }
6320         
6321                 /* Reject old data */
6322                 var duration = settings.iStateDuration;
6323                 if ( duration > 0 && state.time < +new Date() - (duration*1000) ) {
6324                         return;
6325                 }
6326         
6327                 // Number of columns have changed - all bets are off, no restore of settings
6328                 if ( columns.length !== state.columns.length ) {
6329                         return;
6330                 }
6331         
6332                 // Store the saved state so it might be accessed at any time
6333                 settings.oLoadedState = $.extend( true, {}, state );
6334         
6335                 // Restore key features - todo - for 1.11 this needs to be done by
6336                 // subscribed events
6337                 if ( state.start !== undefined ) {
6338                         settings._iDisplayStart    = state.start;
6339                         settings.iInitDisplayStart = state.start;
6340                 }
6341                 if ( state.length !== undefined ) {
6342                         settings._iDisplayLength   = state.length;
6343                 }
6344         
6345                 // Order
6346                 if ( state.order !== undefined ) {
6347                         settings.aaSorting = [];
6348                         $.each( state.order, function ( i, col ) {
6349                                 settings.aaSorting.push( col[0] >= columns.length ?
6350                                         [ 0, col[1] ] :
6351                                         col
6352                                 );
6353                         } );
6354                 }
6355         
6356                 // Search
6357                 if ( state.search !== undefined ) {
6358                         $.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );
6359                 }
6360         
6361                 // Columns
6362                 for ( i=0, ien=state.columns.length ; i<ien ; i++ ) {
6363                         var col = state.columns[i];
6364         
6365                         // Visibility
6366                         if ( col.visible !== undefined ) {
6367                                 columns[i].bVisible = col.visible;
6368                         }
6369         
6370                         // Search
6371                         if ( col.search !== undefined ) {
6372                                 $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6373                         }
6374                 }
6375         
6376                 _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] );
6377         }
6378         
6379         
6380         /**
6381          * Return the settings object for a particular table
6382          *  @param {node} table table we are using as a dataTable
6383          *  @returns {object} Settings object - or null if not found
6384          *  @memberof DataTable#oApi
6385          */
6386         function _fnSettingsFromNode ( table )
6387         {
6388                 var settings = DataTable.settings;
6389                 var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
6390         
6391                 return idx !== -1 ?
6392                         settings[ idx ] :
6393                         null;
6394         }
6395         
6396         
6397         /**
6398          * Log an error message
6399          *  @param {object} settings dataTables settings object
6400          *  @param {int} level log error messages, or display them to the user
6401          *  @param {string} msg error message
6402          *  @param {int} tn Technical note id to get more information about the error.
6403          *  @memberof DataTable#oApi
6404          */
6405         function _fnLog( settings, level, msg, tn )
6406         {
6407                 msg = 'DataTables warning: '+
6408                         (settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
6409         
6410                 if ( tn ) {
6411                         msg += '. For more information about this error, please see '+
6412                         'http://datatables.net/tn/'+tn;
6413                 }
6414         
6415                 if ( ! level  ) {
6416                         // Backwards compatibility pre 1.10
6417                         var ext = DataTable.ext;
6418                         var type = ext.sErrMode || ext.errMode;
6419         
6420                         if ( settings ) {
6421                                 _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
6422                         }
6423         
6424                         if ( type == 'alert' ) {
6425                                 alert( msg );
6426                         }
6427                         else if ( type == 'throw' ) {
6428                                 throw new Error(msg);
6429                         }
6430                         else if ( typeof type == 'function' ) {
6431                                 type( settings, tn, msg );
6432                         }
6433                 }
6434                 else if ( window.console && console.log ) {
6435                         console.log( msg );
6436                 }
6437         }
6438         
6439         
6440         /**
6441          * See if a property is defined on one object, if so assign it to the other object
6442          *  @param {object} ret target object
6443          *  @param {object} src source object
6444          *  @param {string} name property
6445          *  @param {string} [mappedName] name to map too - optional, name used if not given
6446          *  @memberof DataTable#oApi
6447          */
6448         function _fnMap( ret, src, name, mappedName )
6449         {
6450                 if ( $.isArray( name ) ) {
6451                         $.each( name, function (i, val) {
6452                                 if ( $.isArray( val ) ) {
6453                                         _fnMap( ret, src, val[0], val[1] );
6454                                 }
6455                                 else {
6456                                         _fnMap( ret, src, val );
6457                                 }
6458                         } );
6459         
6460                         return;
6461                 }
6462         
6463                 if ( mappedName === undefined ) {
6464                         mappedName = name;
6465                 }
6466         
6467                 if ( src[name] !== undefined ) {
6468                         ret[mappedName] = src[name];
6469                 }
6470         }
6471         
6472         
6473         /**
6474          * Extend objects - very similar to jQuery.extend, but deep copy objects, and
6475          * shallow copy arrays. The reason we need to do this, is that we don't want to
6476          * deep copy array init values (such as aaSorting) since the dev wouldn't be
6477          * able to override them, but we do want to deep copy arrays.
6478          *  @param {object} out Object to extend
6479          *  @param {object} extender Object from which the properties will be applied to
6480          *      out
6481          *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
6482          *      independent copy with the exception of the `data` or `aaData` parameters
6483          *      if they are present. This is so you can pass in a collection to
6484          *      DataTables and have that used as your data source without breaking the
6485          *      references
6486          *  @returns {object} out Reference, just for convenience - out === the return.
6487          *  @memberof DataTable#oApi
6488          *  @todo This doesn't take account of arrays inside the deep copied objects.
6489          */
6490         function _fnExtend( out, extender, breakRefs )
6491         {
6492                 var val;
6493         
6494                 for ( var prop in extender ) {
6495                         if ( extender.hasOwnProperty(prop) ) {
6496                                 val = extender[prop];
6497         
6498                                 if ( $.isPlainObject( val ) ) {
6499                                         if ( ! $.isPlainObject( out[prop] ) ) {
6500                                                 out[prop] = {};
6501                                         }
6502                                         $.extend( true, out[prop], val );
6503                                 }
6504                                 else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
6505                                         out[prop] = val.slice();
6506                                 }
6507                                 else {
6508                                         out[prop] = val;
6509                                 }
6510                         }
6511                 }
6512         
6513                 return out;
6514         }
6515         
6516         
6517         /**
6518          * Bind an event handers to allow a click or return key to activate the callback.
6519          * This is good for accessibility since a return on the keyboard will have the
6520          * same effect as a click, if the element has focus.
6521          *  @param {element} n Element to bind the action to
6522          *  @param {object} oData Data object to pass to the triggered function
6523          *  @param {function} fn Callback function for when the event is triggered
6524          *  @memberof DataTable#oApi
6525          */
6526         function _fnBindAction( n, oData, fn )
6527         {
6528                 $(n)
6529                         .bind( 'click.DT', oData, function (e) {
6530                                         n.blur(); // Remove focus outline for mouse users
6531                                         fn(e);
6532                                 } )
6533                         .bind( 'keypress.DT', oData, function (e){
6534                                         if ( e.which === 13 ) {
6535                                                 e.preventDefault();
6536                                                 fn(e);
6537                                         }
6538                                 } )
6539                         .bind( 'selectstart.DT', function () {
6540                                         /* Take the brutal approach to cancelling text selection */
6541                                         return false;
6542                                 } );
6543         }
6544         
6545         
6546         /**
6547          * Register a callback function. Easily allows a callback function to be added to
6548          * an array store of callback functions that can then all be called together.
6549          *  @param {object} oSettings dataTables settings object
6550          *  @param {string} sStore Name of the array storage for the callbacks in oSettings
6551          *  @param {function} fn Function to be called back
6552          *  @param {string} sName Identifying name for the callback (i.e. a label)
6553          *  @memberof DataTable#oApi
6554          */
6555         function _fnCallbackReg( oSettings, sStore, fn, sName )
6556         {
6557                 if ( fn )
6558                 {
6559                         oSettings[sStore].push( {
6560                                 "fn": fn,
6561                                 "sName": sName
6562                         } );
6563                 }
6564         }
6565         
6566         
6567         /**
6568          * Fire callback functions and trigger events. Note that the loop over the
6569          * callback array store is done backwards! Further note that you do not want to
6570          * fire off triggers in time sensitive applications (for example cell creation)
6571          * as its slow.
6572          *  @param {object} settings dataTables settings object
6573          *  @param {string} callbackArr Name of the array storage for the callbacks in
6574          *      oSettings
6575          *  @param {string} eventName Name of the jQuery custom event to trigger. If
6576          *      null no trigger is fired
6577          *  @param {array} args Array of arguments to pass to the callback function /
6578          *      trigger
6579          *  @memberof DataTable#oApi
6580          */
6581         function _fnCallbackFire( settings, callbackArr, eventName, args )
6582         {
6583                 var ret = [];
6584         
6585                 if ( callbackArr ) {
6586                         ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
6587                                 return val.fn.apply( settings.oInstance, args );
6588                         } );
6589                 }
6590         
6591                 if ( eventName !== null ) {
6592                         var e = $.Event( eventName+'.dt' );
6593         
6594                         $(settings.nTable).trigger( e, args );
6595         
6596                         ret.push( e.result );
6597                 }
6598         
6599                 return ret;
6600         }
6601         
6602         
6603         function _fnLengthOverflow ( settings )
6604         {
6605                 var
6606                         start = settings._iDisplayStart,
6607                         end = settings.fnDisplayEnd(),
6608                         len = settings._iDisplayLength;
6609         
6610                 /* If we have space to show extra rows (backing up from the end point - then do so */
6611                 if ( start >= end )
6612                 {
6613                         start = end - len;
6614                 }
6615         
6616                 // Keep the start record on the current page
6617                 start -= (start % len);
6618         
6619                 if ( len === -1 || start < 0 )
6620                 {
6621                         start = 0;
6622                 }
6623         
6624                 settings._iDisplayStart = start;
6625         }
6626         
6627         
6628         function _fnRenderer( settings, type )
6629         {
6630                 var renderer = settings.renderer;
6631                 var host = DataTable.ext.renderer[type];
6632         
6633                 if ( $.isPlainObject( renderer ) && renderer[type] ) {
6634                         // Specific renderer for this type. If available use it, otherwise use
6635                         // the default.
6636                         return host[renderer[type]] || host._;
6637                 }
6638                 else if ( typeof renderer === 'string' ) {
6639                         // Common renderer - if there is one available for this type use it,
6640                         // otherwise use the default
6641                         return host[renderer] || host._;
6642                 }
6643         
6644                 // Use the default
6645                 return host._;
6646         }
6647         
6648         
6649         /**
6650          * Detect the data source being used for the table. Used to simplify the code
6651          * a little (ajax) and to make it compress a little smaller.
6652          *
6653          *  @param {object} settings dataTables settings object
6654          *  @returns {string} Data source
6655          *  @memberof DataTable#oApi
6656          */
6657         function _fnDataSource ( settings )
6658         {
6659                 if ( settings.oFeatures.bServerSide ) {
6660                         return 'ssp';
6661                 }
6662                 else if ( settings.ajax || settings.sAjaxSource ) {
6663                         return 'ajax';
6664                 }
6665                 return 'dom';
6666         }
6667         
6669         
6670         
6671         /**
6672          * Computed structure of the DataTables API, defined by the options passed to
6673          * `DataTable.Api.register()` when building the API.
6674          *
6675          * The structure is built in order to speed creation and extension of the Api
6676          * objects since the extensions are effectively pre-parsed.
6677          *
6678          * The array is an array of objects with the following structure, where this
6679          * base array represents the Api prototype base:
6680          *
6681          *     [
6682          *       {
6683          *         name:      'data'                -- string   - Property name
6684          *         val:       function () {},       -- function - Api method (or undefined if just an object
6685          *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6686          *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6687          *       },
6688          *       {
6689          *         name:     'row'
6690          *         val:       {},
6691          *         methodExt: [ ... ],
6692          *         propExt:   [
6693          *           {
6694          *             name:      'data'
6695          *             val:       function () {},
6696          *             methodExt: [ ... ],
6697          *             propExt:   [ ... ]
6698          *           },
6699          *           ...
6700          *         ]
6701          *       }
6702          *     ]
6703          *
6704          * @type {Array}
6705          * @ignore
6706          */
6707         var __apiStruct = [];
6708         
6709         
6710         /**
6711          * `Array.prototype` reference.
6712          *
6713          * @type object
6714          * @ignore
6715          */
6716         var __arrayProto = Array.prototype;
6717         
6718         
6719         /**
6720          * Abstraction for `context` parameter of the `Api` constructor to allow it to
6721          * take several different forms for ease of use.
6722          *
6723          * Each of the input parameter types will be converted to a DataTables settings
6724          * object where possible.
6725          *
6726          * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6727          *   of:
6728          *
6729          *   * `string` - jQuery selector. Any DataTables' matching the given selector
6730          *     with be found and used.
6731          *   * `node` - `TABLE` node which has already been formed into a DataTable.
6732          *   * `jQuery` - A jQuery object of `TABLE` nodes.
6733          *   * `object` - DataTables settings object
6734          *   * `DataTables.Api` - API instance
6735          * @return {array|null} Matching DataTables settings objects. `null` or
6736          *   `undefined` is returned if no matching DataTable is found.
6737          * @ignore
6738          */
6739         var _toSettings = function ( mixed )
6740         {
6741                 var idx, jq;
6742                 var settings = DataTable.settings;
6743                 var tables = $.map( settings, function (el, i) {
6744                         return el.nTable;
6745                 } );
6746         
6747                 if ( ! mixed ) {
6748                         return [];
6749                 }
6750                 else if ( mixed.nTable && mixed.oApi ) {
6751                         // DataTables settings object
6752                         return [ mixed ];
6753                 }
6754                 else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6755                         // Table node
6756                         idx = $.inArray( mixed, tables );
6757                         return idx !== -1 ? [ settings[idx] ] : null;
6758                 }
6759                 else if ( mixed && typeof mixed.settings === 'function' ) {
6760                         return mixed.settings().toArray();
6761                 }
6762                 else if ( typeof mixed === 'string' ) {
6763                         // jQuery selector
6764                         jq = $(mixed);
6765                 }
6766                 else if ( mixed instanceof $ ) {
6767                         // jQuery object (also DataTables instance)
6768                         jq = mixed;
6769                 }
6770         
6771                 if ( jq ) {
6772                         return jq.map( function(i) {
6773                                 idx = $.inArray( this, tables );
6774                                 return idx !== -1 ? settings[idx] : null;
6775                         } ).toArray();
6776                 }
6777         };
6778         
6779         
6780         /**
6781          * DataTables API class - used to control and interface with  one or more
6782          * DataTables enhanced tables.
6783          *
6784          * The API class is heavily based on jQuery, presenting a chainable interface
6785          * that you can use to interact with tables. Each instance of the API class has
6786          * a "context" - i.e. the tables that it will operate on. This could be a single
6787          * table, all tables on a page or a sub-set thereof.
6788          *
6789          * Additionally the API is designed to allow you to easily work with the data in
6790          * the tables, retrieving and manipulating it as required. This is done by
6791          * presenting the API class as an array like interface. The contents of the
6792          * array depend upon the actions requested by each method (for example
6793          * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6794          * return an array of objects or arrays depending upon your table's
6795          * configuration). The API object has a number of array like methods (`push`,
6796          * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6797          * `unique` etc) to assist your working with the data held in a table.
6798          *
6799          * Most methods (those which return an Api instance) are chainable, which means
6800          * the return from a method call also has all of the methods available that the
6801          * top level object had. For example, these two calls are equivalent:
6802          *
6803          *     // Not chained
6804          *     api.row.add( {...} );
6805          *     api.draw();
6806          *
6807          *     // Chained
6808          *     api.row.add( {...} ).draw();
6809          *
6810          * @class DataTable.Api
6811          * @param {array|object|string|jQuery} context DataTable identifier. This is
6812          *   used to define which DataTables enhanced tables this API will operate on.
6813          *   Can be one of:
6814          *
6815          *   * `string` - jQuery selector. Any DataTables' matching the given selector
6816          *     with be found and used.
6817          *   * `node` - `TABLE` node which has already been formed into a DataTable.
6818          *   * `jQuery` - A jQuery object of `TABLE` nodes.
6819          *   * `object` - DataTables settings object
6820          * @param {array} [data] Data to initialise the Api instance with.
6821          *
6822          * @example
6823          *   // Direct initialisation during DataTables construction
6824          *   var api = $('#example').DataTable();
6825          *
6826          * @example
6827          *   // Initialisation using a DataTables jQuery object
6828          *   var api = $('#example').dataTable().api();
6829          *
6830          * @example
6831          *   // Initialisation as a constructor
6832          *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6833          */
6834         _Api = function ( context, data )
6835         {
6836                 if ( ! (this instanceof _Api) ) {
6837                         return new _Api( context, data );
6838                 }
6839         
6840                 var settings = [];
6841                 var ctxSettings = function ( o ) {
6842                         var a = _toSettings( o );
6843                         if ( a ) {
6844                                 settings = settings.concat( a );
6845                         }
6846                 };
6847         
6848                 if ( $.isArray( context ) ) {
6849                         for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6850                                 ctxSettings( context[i] );
6851                         }
6852                 }
6853                 else {
6854                         ctxSettings( context );
6855                 }
6856         
6857                 // Remove duplicates
6858                 this.context = _unique( settings );
6859         
6860                 // Initial data
6861                 if ( data ) {
6862                         $.merge( this, data );
6863                 }
6864         
6865                 // selector
6866                 this.selector = {
6867                         rows: null,
6868                         cols: null,
6869                         opts: null
6870                 };
6871         
6872                 _Api.extend( this, this, __apiStruct );
6873         };
6874         
6875         DataTable.Api = _Api;
6876         
6877         // Don't destroy the existing prototype, just extend it. Required for jQuery 2's
6878         // isPlainObject.
6879         $.extend( _Api.prototype, {
6880                 any: function ()
6881                 {
6882                         return this.count() !== 0;
6883                 },
6884         
6885         
6886                 concat:  __arrayProto.concat,
6887         
6888         
6889                 context: [], // array of table settings objects
6890         
6891         
6892                 count: function ()
6893                 {
6894                         return this.flatten().length;
6895                 },
6896         
6897         
6898                 each: function ( fn )
6899                 {
6900                         for ( var i=0, ien=this.length ; i<ien; i++ ) {
6901                                 fn.call( this, this[i], i, this );
6902                         }
6903         
6904                         return this;
6905                 },
6906         
6907         
6908                 eq: function ( idx )
6909                 {
6910                         var ctx = this.context;
6911         
6912                         return ctx.length > idx ?
6913                                 new _Api( ctx[idx], this[idx] ) :
6914                                 null;
6915                 },
6916         
6917         
6918                 filter: function ( fn )
6919                 {
6920                         var a = [];
6921         
6922                         if ( __arrayProto.filter ) {
6923                                 a = __arrayProto.filter.call( this, fn, this );
6924                         }
6925                         else {
6926                                 // Compatibility for browsers without EMCA-252-5 (JS 1.6)
6927                                 for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6928                                         if ( fn.call( this, this[i], i, this ) ) {
6929                                                 a.push( this[i] );
6930                                         }
6931                                 }
6932                         }
6933         
6934                         return new _Api( this.context, a );
6935                 },
6936         
6937         
6938                 flatten: function ()
6939                 {
6940                         var a = [];
6941                         return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
6942                 },
6943         
6944         
6945                 join:    __arrayProto.join,
6946         
6947         
6948                 indexOf: __arrayProto.indexOf || function (obj, start)
6949                 {
6950                         for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
6951                                 if ( this[i] === obj ) {
6952                                         return i;
6953                                 }
6954                         }
6955                         return -1;
6956                 },
6957         
6958                 iterator: function ( flatten, type, fn, alwaysNew ) {
6959                         var
6960                                 a = [], ret,
6961                                 i, ien, j, jen,
6962                                 context = this.context,
6963                                 rows, items, item,
6964                                 selector = this.selector;
6965         
6966                         // Argument shifting
6967                         if ( typeof flatten === 'string' ) {
6968                                 alwaysNew = fn;
6969                                 fn = type;
6970                                 type = flatten;
6971                                 flatten = false;
6972                         }
6973         
6974                         for ( i=0, ien=context.length ; i<ien ; i++ ) {
6975                                 var apiInst = new _Api( context[i] );
6976         
6977                                 if ( type === 'table' ) {
6978                                         ret = fn.call( apiInst, context[i], i );
6979         
6980                                         if ( ret !== undefined ) {
6981                                                 a.push( ret );
6982                                         }
6983                                 }
6984                                 else if ( type === 'columns' || type === 'rows' ) {
6985                                         // this has same length as context - one entry for each table
6986                                         ret = fn.call( apiInst, context[i], this[i], i );
6987         
6988                                         if ( ret !== undefined ) {
6989                                                 a.push( ret );
6990                                         }
6991                                 }
6992                                 else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
6993                                         // columns and rows share the same structure.
6994                                         // 'this' is an array of column indexes for each context
6995                                         items = this[i];
6996         
6997                                         if ( type === 'column-rows' ) {
6998                                                 rows = _selector_row_indexes( context[i], selector.opts );
6999                                         }
7000         
7001                                         for ( j=0, jen=items.length ; j<jen ; j++ ) {
7002                                                 item = items[j];
7003         
7004                                                 if ( type === 'cell' ) {
7005                                                         ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
7006                                                 }
7007                                                 else {
7008                                                         ret = fn.call( apiInst, context[i], item, i, j, rows );
7009                                                 }
7010         
7011                                                 if ( ret !== undefined ) {
7012                                                         a.push( ret );
7013                                                 }
7014                                         }
7015                                 }
7016                         }
7017         
7018                         if ( a.length || alwaysNew ) {
7019                                 var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
7020                                 var apiSelector = api.selector;
7021                                 apiSelector.rows = selector.rows;
7022                                 apiSelector.cols = selector.cols;
7023                                 apiSelector.opts = selector.opts;
7024                                 return api;
7025                         }
7026                         return this;
7027                 },
7028         
7029         
7030                 lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
7031                 {
7032                         // Bit cheeky...
7033                         return this.indexOf.apply( this.toArray.reverse(), arguments );
7034                 },
7035         
7036         
7037                 length:  0,
7038         
7039         
7040                 map: function ( fn )
7041                 {
7042                         var a = [];
7043         
7044                         if ( __arrayProto.map ) {
7045                                 a = __arrayProto.map.call( this, fn, this );
7046                         }
7047                         else {
7048                                 // Compatibility for browsers without EMCA-252-5 (JS 1.6)
7049                                 for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7050                                         a.push( fn.call( this, this[i], i ) );
7051                                 }
7052                         }
7053         
7054                         return new _Api( this.context, a );
7055                 },
7056         
7057         
7058                 pluck: function ( prop )
7059                 {
7060                         return this.map( function ( el ) {
7061                                 return el[ prop ];
7062                         } );
7063                 },
7064         
7065                 pop:     __arrayProto.pop,
7066         
7067         
7068                 push:    __arrayProto.push,
7069         
7070         
7071                 // Does not return an API instance
7072                 reduce: __arrayProto.reduce || function ( fn, init )
7073                 {
7074                         return _fnReduce( this, fn, init, 0, this.length, 1 );
7075                 },
7076         
7077         
7078                 reduceRight: __arrayProto.reduceRight || function ( fn, init )
7079                 {
7080                         return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7081                 },
7082         
7083         
7084                 reverse: __arrayProto.reverse,
7085         
7086         
7087                 // Object with rows, columns and opts
7088                 selector: null,
7089         
7090         
7091                 shift:   __arrayProto.shift,
7092         
7093         
7094                 sort:    __arrayProto.sort, // ? name - order?
7095         
7096         
7097                 splice:  __arrayProto.splice,
7098         
7099         
7100                 toArray: function ()
7101                 {
7102                         return __arrayProto.slice.call( this );
7103                 },
7104         
7105         
7106                 to$: function ()
7107                 {
7108                         return $( this );
7109                 },
7110         
7111         
7112                 toJQuery: function ()
7113                 {
7114                         return $( this );
7115                 },
7116         
7117         
7118                 unique: function ()
7119                 {
7120                         return new _Api( this.context, _unique(this) );
7121                 },
7122         
7123         
7124                 unshift: __arrayProto.unshift
7125         } );
7126         
7127         
7128         _Api.extend = function ( scope, obj, ext )
7129         {
7130                 // Only extend API instances and static properties of the API
7131                 if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7132                         return;
7133                 }
7134         
7135                 var
7136                         i, ien,
7137                         j, jen,
7138                         struct, inner,
7139                         methodScoping = function ( scope, fn, struc ) {
7140                                 return function () {
7141                                         var ret = fn.apply( scope, arguments );
7142         
7143                                         // Method extension
7144                                         _Api.extend( ret, ret, struc.methodExt );
7145                                         return ret;
7146                                 };
7147                         };
7148         
7149                 for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7150                         struct = ext[i];
7151         
7152                         // Value
7153                         obj[ struct.name ] = typeof struct.val === 'function' ?
7154                                 methodScoping( scope, struct.val, struct ) :
7155                                 $.isPlainObject( struct.val ) ?
7156                                         {} :
7157                                         struct.val;
7158         
7159                         obj[ struct.name ].__dt_wrapper = true;
7160         
7161                         // Property extension
7162                         _Api.extend( scope, obj[ struct.name ], struct.propExt );
7163                 }
7164         };
7165         
7166         
7167         // @todo - Is there need for an augment function?
7168         // _Api.augment = function ( inst, name )
7169         // {
7170         //      // Find src object in the structure from the name
7171         //      var parts = name.split('.');
7172         
7173         //      _Api.extend( inst, obj );
7174         // };
7175         
7176         
7177         //     [
7178         //       {
7179         //         name:      'data'                -- string   - Property name
7180         //         val:       function () {},       -- function - Api method (or undefined if just an object
7181         //         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7182         //         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7183         //       },
7184         //       {
7185         //         name:     'row'
7186         //         val:       {},
7187         //         methodExt: [ ... ],
7188         //         propExt:   [
7189         //           {
7190         //             name:      'data'
7191         //             val:       function () {},
7192         //             methodExt: [ ... ],
7193         //             propExt:   [ ... ]
7194         //           },
7195         //           ...
7196         //         ]
7197         //       }
7198         //     ]
7199         
7200         _Api.register = _api_register = function ( name, val )
7201         {
7202                 if ( $.isArray( name ) ) {
7203                         for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7204                                 _Api.register( name[j], val );
7205                         }
7206                         return;
7207                 }
7208         
7209                 var
7210                         i, ien,
7211                         heir = name.split('.'),
7212                         struct = __apiStruct,
7213                         key, method;
7214         
7215                 var find = function ( src, name ) {
7216                         for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7217                                 if ( src[i].name === name ) {
7218                                         return src[i];
7219                                 }
7220                         }
7221                         return null;
7222                 };
7223         
7224                 for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7225                         method = heir[i].indexOf('()') !== -1;
7226                         key = method ?
7227                                 heir[i].replace('()', '') :
7228                                 heir[i];
7229         
7230                         var src = find( struct, key );
7231                         if ( ! src ) {
7232                                 src = {
7233                                         name:      key,
7234                                         val:       {},
7235                                         methodExt: [],
7236                                         propExt:   []
7237                                 };
7238                                 struct.push( src );
7239                         }
7240         
7241                         if ( i === ien-1 ) {
7242                                 src.val = val;
7243                         }
7244                         else {
7245                                 struct = method ?
7246                                         src.methodExt :
7247                                         src.propExt;
7248                         }
7249                 }
7250         };
7251         
7252         
7253         _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7254                 _Api.register( pluralName, val );
7255         
7256                 _Api.register( singularName, function () {
7257                         var ret = val.apply( this, arguments );
7258         
7259                         if ( ret === this ) {
7260                                 // Returned item is the API instance that was passed in, return it
7261                                 return this;
7262                         }
7263                         else if ( ret instanceof _Api ) {
7264                                 // New API instance returned, want the value from the first item
7265                                 // in the returned array for the singular result.
7266                                 return ret.length ?
7267                                         $.isArray( ret[0] ) ?
7268                                                 new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7269                                                 ret[0] :
7270                                         undefined;
7271                         }
7272         
7273                         // Non-API return - just fire it back
7274                         return ret;
7275                 } );
7276         };
7277         
7278         
7279         /**
7280          * Selector for HTML tables. Apply the given selector to the give array of
7281          * DataTables settings objects.
7282          *
7283          * @param {string|integer} [selector] jQuery selector string or integer
7284          * @param  {array} Array of DataTables settings objects to be filtered
7285          * @return {array}
7286          * @ignore
7287          */
7288         var __table_selector = function ( selector, a )
7289         {
7290                 // Integer is used to pick out a table by index
7291                 if ( typeof selector === 'number' ) {
7292                         return [ a[ selector ] ];
7293                 }
7294         
7295                 // Perform a jQuery selector on the table nodes
7296                 var nodes = $.map( a, function (el, i) {
7297                         return el.nTable;
7298                 } );
7299         
7300                 return $(nodes)
7301                         .filter( selector )
7302                         .map( function (i) {
7303                                 // Need to translate back from the table node to the settings
7304                                 var idx = $.inArray( this, nodes );
7305                                 return a[ idx ];
7306                         } )
7307                         .toArray();
7308         };
7309         
7310         
7311         
7312         /**
7313          * Context selector for the API's context (i.e. the tables the API instance
7314          * refers to.
7315          *
7316          * @name    DataTable.Api#tables
7317          * @param {string|integer} [selector] Selector to pick which tables the iterator
7318          *   should operate on. If not given, all tables in the current context are
7319          *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7320          *   select multiple tables or as an integer to select a single table.
7321          * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7322          */
7323         _api_register( 'tables()', function ( selector ) {
7324                 // A new instance is created if there was a selector specified
7325                 return selector ?
7326                         new _Api( __table_selector( selector, this.context ) ) :
7327                         this;
7328         } );
7329         
7330         
7331         _api_register( 'table()', function ( selector ) {
7332                 var tables = this.tables( selector );
7333                 var ctx = tables.context;
7334         
7335                 // Truncate to the first matched table
7336                 return ctx.length ?
7337                         new _Api( ctx[0] ) :
7338                         tables;
7339         } );
7340         
7341         
7342         _api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7343                 return this.iterator( 'table', function ( ctx ) {
7344                         return ctx.nTable;
7345                 }, 1 );
7346         } );
7347         
7348         
7349         _api_registerPlural( 'tables().body()', 'table().body()' , function () {
7350                 return this.iterator( 'table', function ( ctx ) {
7351                         return ctx.nTBody;
7352                 }, 1 );
7353         } );
7354         
7355         
7356         _api_registerPlural( 'tables().header()', 'table().header()' , function () {
7357                 return this.iterator( 'table', function ( ctx ) {
7358                         return ctx.nTHead;
7359                 }, 1 );
7360         } );
7361         
7362         
7363         _api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7364                 return this.iterator( 'table', function ( ctx ) {
7365                         return ctx.nTFoot;
7366                 }, 1 );
7367         } );
7368         
7369         
7370         _api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7371                 return this.iterator( 'table', function ( ctx ) {
7372                         return ctx.nTableWrapper;
7373                 }, 1 );
7374         } );
7375         
7376         
7377         
7378         /**
7379          * Redraw the tables in the current context.
7380          */
7381         _api_register( 'draw()', function ( paging ) {
7382                 return this.iterator( 'table', function ( settings ) {
7383                         if ( paging === 'page' ) {
7384                                 _fnDraw( settings );
7385                         }
7386                         else {
7387                                 if ( typeof paging === 'string' ) {
7388                                         paging = paging === 'full-hold' ?
7389                                                 false :
7390                                                 true;
7391                                 }
7392         
7393                                 _fnReDraw( settings, paging===false );
7394                         }
7395                 } );
7396         } );
7397         
7398         
7399         
7400         /**
7401          * Get the current page index.
7402          *
7403          * @return {integer} Current page index (zero based)
7404          *//**
7405          * Set the current page.
7406          *
7407          * Note that if you attempt to show a page which does not exist, DataTables will
7408          * not throw an error, but rather reset the paging.
7409          *
7410          * @param {integer|string} action The paging action to take. This can be one of:
7411          *  * `integer` - The page index to jump to
7412          *  * `string` - An action to take:
7413          *    * `first` - Jump to first page.
7414          *    * `next` - Jump to the next page
7415          *    * `previous` - Jump to previous page
7416          *    * `last` - Jump to the last page.
7417          * @returns {DataTables.Api} this
7418          */
7419         _api_register( 'page()', function ( action ) {
7420                 if ( action === undefined ) {
7421                         return this.page.info().page; // not an expensive call
7422                 }
7423         
7424                 // else, have an action to take on all tables
7425                 return this.iterator( 'table', function ( settings ) {
7426                         _fnPageChange( settings, action );
7427                 } );
7428         } );
7429         
7430         
7431         /**
7432          * Paging information for the first table in the current context.
7433          *
7434          * If you require paging information for another table, use the `table()` method
7435          * with a suitable selector.
7436          *
7437          * @return {object} Object with the following properties set:
7438          *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7439          *  * `pages` - Total number of pages
7440          *  * `start` - Display index for the first record shown on the current page
7441          *  * `end` - Display index for the last record shown on the current page
7442          *  * `length` - Display length (number of records). Note that generally `start
7443          *    + length = end`, but this is not always true, for example if there are
7444          *    only 2 records to show on the final page, with a length of 10.
7445          *  * `recordsTotal` - Full data set length
7446          *  * `recordsDisplay` - Data set length once the current filtering criterion
7447          *    are applied.
7448          */
7449         _api_register( 'page.info()', function ( action ) {
7450                 if ( this.context.length === 0 ) {
7451                         return undefined;
7452                 }
7453         
7454                 var
7455                         settings   = this.context[0],
7456                         start      = settings._iDisplayStart,
7457                         len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7458                         visRecords = settings.fnRecordsDisplay(),
7459                         all        = len === -1;
7460         
7461                 return {
7462                         "page":           all ? 0 : Math.floor( start / len ),
7463                         "pages":          all ? 1 : Math.ceil( visRecords / len ),
7464                         "start":          start,
7465                         "end":            settings.fnDisplayEnd(),
7466                         "length":         len,
7467                         "recordsTotal":   settings.fnRecordsTotal(),
7468                         "recordsDisplay": visRecords,
7469                         "serverSide":     _fnDataSource( settings ) === 'ssp'
7470                 };
7471         } );
7472         
7473         
7474         /**
7475          * Get the current page length.
7476          *
7477          * @return {integer} Current page length. Note `-1` indicates that all records
7478          *   are to be shown.
7479          *//**
7480          * Set the current page length.
7481          *
7482          * @param {integer} Page length to set. Use `-1` to show all records.
7483          * @returns {DataTables.Api} this
7484          */
7485         _api_register( 'page.len()', function ( len ) {
7486                 // Note that we can't call this function 'length()' because `length`
7487                 // is a Javascript property of functions which defines how many arguments
7488                 // the function expects.
7489                 if ( len === undefined ) {
7490                         return this.context.length !== 0 ?
7491                                 this.context[0]._iDisplayLength :
7492                                 undefined;
7493                 }
7494         
7495                 // else, set the page length
7496                 return this.iterator( 'table', function ( settings ) {
7497                         _fnLengthChange( settings, len );
7498                 } );
7499         } );
7500         
7501         
7502         
7503         var __reload = function ( settings, holdPosition, callback ) {
7504                 // Use the draw event to trigger a callback
7505                 if ( callback ) {
7506                         var api = new _Api( settings );
7507         
7508                         api.one( 'draw', function () {
7509                                 callback( api.ajax.json() );
7510                         } );
7511                 }
7512         
7513                 if ( _fnDataSource( settings ) == 'ssp' ) {
7514                         _fnReDraw( settings, holdPosition );
7515                 }
7516                 else {
7517                         _fnProcessingDisplay( settings, true );
7518         
7519                         // Cancel an existing request
7520                         var xhr = settings.jqXHR;
7521                         if ( xhr && xhr.readyState !== 4 ) {
7522                                 xhr.abort();
7523                         }
7524         
7525                         // Trigger xhr
7526                         _fnBuildAjax( settings, [], function( json ) {
7527                                 _fnClearTable( settings );
7528         
7529                                 var data = _fnAjaxDataSrc( settings, json );
7530                                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7531                                         _fnAddData( settings, data[i] );
7532                                 }
7533         
7534                                 _fnReDraw( settings, holdPosition );
7535                                 _fnProcessingDisplay( settings, false );
7536                         } );
7537                 }
7538         };
7539         
7540         
7541         /**
7542          * Get the JSON response from the last Ajax request that DataTables made to the
7543          * server. Note that this returns the JSON from the first table in the current
7544          * context.
7545          *
7546          * @return {object} JSON received from the server.
7547          */
7548         _api_register( 'ajax.json()', function () {
7549                 var ctx = this.context;
7550         
7551                 if ( ctx.length > 0 ) {
7552                         return ctx[0].json;
7553                 }
7554         
7555                 // else return undefined;
7556         } );
7557         
7558         
7559         /**
7560          * Get the data submitted in the last Ajax request
7561          */
7562         _api_register( 'ajax.params()', function () {
7563                 var ctx = this.context;
7564         
7565                 if ( ctx.length > 0 ) {
7566                         return ctx[0].oAjaxData;
7567                 }
7568         
7569                 // else return undefined;
7570         } );
7571         
7572         
7573         /**
7574          * Reload tables from the Ajax data source. Note that this function will
7575          * automatically re-draw the table when the remote data has been loaded.
7576          *
7577          * @param {boolean} [reset=true] Reset (default) or hold the current paging
7578          *   position. A full re-sort and re-filter is performed when this method is
7579          *   called, which is why the pagination reset is the default action.
7580          * @returns {DataTables.Api} this
7581          */
7582         _api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7583                 return this.iterator( 'table', function (settings) {
7584                         __reload( settings, resetPaging===false, callback );
7585                 } );
7586         } );
7587         
7588         
7589         /**
7590          * Get the current Ajax URL. Note that this returns the URL from the first
7591          * table in the current context.
7592          *
7593          * @return {string} Current Ajax source URL
7594          *//**
7595          * Set the Ajax URL. Note that this will set the URL for all tables in the
7596          * current context.
7597          *
7598          * @param {string} url URL to set.
7599          * @returns {DataTables.Api} this
7600          */
7601         _api_register( 'ajax.url()', function ( url ) {
7602                 var ctx = this.context;
7603         
7604                 if ( url === undefined ) {
7605                         // get
7606                         if ( ctx.length === 0 ) {
7607                                 return undefined;
7608                         }
7609                         ctx = ctx[0];
7610         
7611                         return ctx.ajax ?
7612                                 $.isPlainObject( ctx.ajax ) ?
7613                                         ctx.ajax.url :
7614                                         ctx.ajax :
7615                                 ctx.sAjaxSource;
7616                 }
7617         
7618                 // set
7619                 return this.iterator( 'table', function ( settings ) {
7620                         if ( $.isPlainObject( settings.ajax ) ) {
7621                                 settings.ajax.url = url;
7622                         }
7623                         else {
7624                                 settings.ajax = url;
7625                         }
7626                         // No need to consider sAjaxSource here since DataTables gives priority
7627                         // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7628                         // value of `sAjaxSource` redundant.
7629                 } );
7630         } );
7631         
7632         
7633         /**
7634          * Load data from the newly set Ajax URL. Note that this method is only
7635          * available when `ajax.url()` is used to set a URL. Additionally, this method
7636          * has the same effect as calling `ajax.reload()` but is provided for
7637          * convenience when setting a new URL. Like `ajax.reload()` it will
7638          * automatically redraw the table once the remote data has been loaded.
7639          *
7640          * @returns {DataTables.Api} this
7641          */
7642         _api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7643                 // Same as a reload, but makes sense to present it for easy access after a
7644                 // url change
7645                 return this.iterator( 'table', function ( ctx ) {
7646                         __reload( ctx, resetPaging===false, callback );
7647                 } );
7648         } );
7649         
7650         
7651         
7652         
7653         var _selector_run = function ( type, selector, selectFn, settings, opts )
7654         {
7655                 var
7656                         out = [], res,
7657                         a, i, ien, j, jen,
7658                         selectorType = typeof selector;
7659         
7660                 // Can't just check for isArray here, as an API or jQuery instance might be
7661                 // given with their array like look
7662                 if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7663                         selector = [ selector ];
7664                 }
7665         
7666                 for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7667                         a = selector[i] && selector[i].split ?
7668                                 selector[i].split(',') :
7669                                 [ selector[i] ];
7670         
7671                         for ( j=0, jen=a.length ; j<jen ; j++ ) {
7672                                 res = selectFn( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
7673         
7674                                 if ( res && res.length ) {
7675                                         out = out.concat( res );
7676                                 }
7677                         }
7678                 }
7679         
7680                 // selector extensions
7681                 var ext = _ext.selector[ type ];
7682                 if ( ext.length ) {
7683                         for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7684                                 out = ext[i]( settings, opts, out );
7685                         }
7686                 }
7687         
7688                 return _unique( out );
7689         };
7690         
7691         
7692         var _selector_opts = function ( opts )
7693         {
7694                 if ( ! opts ) {
7695                         opts = {};
7696                 }
7697         
7698                 // Backwards compatibility for 1.9- which used the terminology filter rather
7699                 // than search
7700                 if ( opts.filter && opts.search === undefined ) {
7701                         opts.search = opts.filter;
7702                 }
7703         
7704                 return $.extend( {
7705                         search: 'none',
7706                         order: 'current',
7707                         page: 'all'
7708                 }, opts );
7709         };
7710         
7711         
7712         var _selector_first = function ( inst )
7713         {
7714                 // Reduce the API instance to the first item found
7715                 for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7716                         if ( inst[i].length > 0 ) {
7717                                 // Assign the first element to the first item in the instance
7718                                 // and truncate the instance and context
7719                                 inst[0] = inst[i];
7720                                 inst[0].length = 1;
7721                                 inst.length = 1;
7722                                 inst.context = [ inst.context[i] ];
7723         
7724                                 return inst;
7725                         }
7726                 }
7727         
7728                 // Not found - return an empty instance
7729                 inst.length = 0;
7730                 return inst;
7731         };
7732         
7733         
7734         var _selector_row_indexes = function ( settings, opts )
7735         {
7736                 var
7737                         i, ien, tmp, a=[],
7738                         displayFiltered = settings.aiDisplay,
7739                         displayMaster = settings.aiDisplayMaster;
7740         
7741                 var
7742                         search = opts.search,  // none, applied, removed
7743                         order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7744                         page   = opts.page;    // all, current
7745         
7746                 if ( _fnDataSource( settings ) == 'ssp' ) {
7747                         // In server-side processing mode, most options are irrelevant since
7748                         // rows not shown don't exist and the index order is the applied order
7749                         // Removed is a special case - for consistency just return an empty
7750                         // array
7751                         return search === 'removed' ?
7752                                 [] :
7753                                 _range( 0, displayMaster.length );
7754                 }
7755                 else if ( page == 'current' ) {
7756                         // Current page implies that order=current and fitler=applied, since it is
7757                         // fairly senseless otherwise, regardless of what order and search actually
7758                         // are
7759                         for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7760                                 a.push( displayFiltered[i] );
7761                         }
7762                 }
7763                 else if ( order == 'current' || order == 'applied' ) {
7764                         a = search == 'none' ?
7765                                 displayMaster.slice() :                      // no search
7766                                 search == 'applied' ?
7767                                         displayFiltered.slice() :                // applied search
7768                                         $.map( displayMaster, function (el, i) { // removed search
7769                                                 return $.inArray( el, displayFiltered ) === -1 ? el : null;
7770                                         } );
7771                 }
7772                 else if ( order == 'index' || order == 'original' ) {
7773                         for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7774                                 if ( search == 'none' ) {
7775                                         a.push( i );
7776                                 }
7777                                 else { // applied | removed
7778                                         tmp = $.inArray( i, displayFiltered );
7779         
7780                                         if ((tmp === -1 && search == 'removed') ||
7781                                                 (tmp >= 0   && search == 'applied') )
7782                                         {
7783                                                 a.push( i );
7784                                         }
7785                                 }
7786                         }
7787                 }
7788         
7789                 return a;
7790         };
7791         
7792         
7793         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7794          * Rows
7795          *
7796          * {}          - no selector - use all available rows
7797          * {integer}   - row aoData index
7798          * {node}      - TR node
7799          * {string}    - jQuery selector to apply to the TR elements
7800          * {array}     - jQuery array of nodes, or simply an array of TR nodes
7801          *
7802          */
7803         
7804         
7805         var __row_selector = function ( settings, selector, opts )
7806         {
7807                 var run = function ( sel ) {
7808                         var selInt = _intVal( sel );
7809                         var i, ien;
7810         
7811                         // Short cut - selector is a number and no options provided (default is
7812                         // all records, so no need to check if the index is in there, since it
7813                         // must be - dev error if the index doesn't exist).
7814                         if ( selInt !== null && ! opts ) {
7815                                 return [ selInt ];
7816                         }
7817         
7818                         var rows = _selector_row_indexes( settings, opts );
7819         
7820                         if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7821                                 // Selector - integer
7822                                 return [ selInt ];
7823                         }
7824                         else if ( ! sel ) {
7825                                 // Selector - none
7826                                 return rows;
7827                         }
7828         
7829                         // Selector - function
7830                         if ( typeof sel === 'function' ) {
7831                                 return $.map( rows, function (idx) {
7832                                         var row = settings.aoData[ idx ];
7833                                         return sel( idx, row._aData, row.nTr ) ? idx : null;
7834                                 } );
7835                         }
7836         
7837                         // Get nodes in the order from the `rows` array with null values removed
7838                         var nodes = _removeEmpty(
7839                                 _pluck_order( settings.aoData, rows, 'nTr' )
7840                         );
7841         
7842                         // Selector - node
7843                         if ( sel.nodeName ) {
7844                                 if ( sel._DT_RowIndex !== undefined ) {
7845                                         return [ sel._DT_RowIndex ]; // Property added by DT for fast lookup
7846                                 }
7847                                 else if ( sel._DT_CellIndex ) {
7848                                         return [ sel._DT_CellIndex.row ];
7849                                 }
7850                                 else {
7851                                         var host = $(sel).closest('*[data-dt-row]');
7852                                         return host.length ?
7853                                                 [ host.data('dt-row') ] :
7854                                                 [];
7855                                 }
7856                         }
7857         
7858                         // ID selector. Want to always be able to select rows by id, regardless
7859                         // of if the tr element has been created or not, so can't rely upon
7860                         // jQuery here - hence a custom implementation. This does not match
7861                         // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
7862                         // but to select it using a CSS selector engine (like Sizzle or
7863                         // querySelect) it would need to need to be escaped for some characters.
7864                         // DataTables simplifies this for row selectors since you can select
7865                         // only a row. A # indicates an id any anything that follows is the id -
7866                         // unescaped.
7867                         if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
7868                                 // get row index from id
7869                                 var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
7870                                 if ( rowObj !== undefined ) {
7871                                         return [ rowObj.idx ];
7872                                 }
7873         
7874                                 // need to fall through to jQuery in case there is DOM id that
7875                                 // matches
7876                         }
7877         
7878                         // Selector - jQuery selector string, array of nodes or jQuery object/
7879                         // As jQuery's .filter() allows jQuery objects to be passed in filter,
7880                         // it also allows arrays, so this will cope with all three options
7881                         return $(nodes)
7882                                 .filter( sel )
7883                                 .map( function () {
7884                                         return this._DT_RowIndex;
7885                                 } )
7886                                 .toArray();
7887                 };
7888         
7889                 return _selector_run( 'row', selector, run, settings, opts );
7890         };
7891         
7892         
7893         _api_register( 'rows()', function ( selector, opts ) {
7894                 // argument shifting
7895                 if ( selector === undefined ) {
7896                         selector = '';
7897                 }
7898                 else if ( $.isPlainObject( selector ) ) {
7899                         opts = selector;
7900                         selector = '';
7901                 }
7902         
7903                 opts = _selector_opts( opts );
7904         
7905                 var inst = this.iterator( 'table', function ( settings ) {
7906                         return __row_selector( settings, selector, opts );
7907                 }, 1 );
7908         
7909                 // Want argument shifting here and in __row_selector?
7910                 inst.selector.rows = selector;
7911                 inst.selector.opts = opts;
7912         
7913                 return inst;
7914         } );
7915         
7916         _api_register( 'rows().nodes()', function () {
7917                 return this.iterator( 'row', function ( settings, row ) {
7918                         return settings.aoData[ row ].nTr || undefined;
7919                 }, 1 );
7920         } );
7921         
7922         _api_register( 'rows().data()', function () {
7923                 return this.iterator( true, 'rows', function ( settings, rows ) {
7924                         return _pluck_order( settings.aoData, rows, '_aData' );
7925                 }, 1 );
7926         } );
7927         
7928         _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
7929                 return this.iterator( 'row', function ( settings, row ) {
7930                         var r = settings.aoData[ row ];
7931                         return type === 'search' ? r._aFilterData : r._aSortData;
7932                 }, 1 );
7933         } );
7934         
7935         _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
7936                 return this.iterator( 'row', function ( settings, row ) {
7937                         _fnInvalidate( settings, row, src );
7938                 } );
7939         } );
7940         
7941         _api_registerPlural( 'rows().indexes()', 'row().index()', function () {
7942                 return this.iterator( 'row', function ( settings, row ) {
7943                         return row;
7944                 }, 1 );
7945         } );
7946         
7947         _api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
7948                 var a = [];
7949                 var context = this.context;
7950         
7951                 // `iterator` will drop undefined values, but in this case we want them
7952                 for ( var i=0, ien=context.length ; i<ien ; i++ ) {
7953                         for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
7954                                 var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
7955                                 a.push( (hash === true ? '#' : '' )+ id );
7956                         }
7957                 }
7958         
7959                 return new _Api( context, a );
7960         } );
7961         
7962         _api_registerPlural( 'rows().remove()', 'row().remove()', function () {
7963                 var that = this;
7964         
7965                 this.iterator( 'row', function ( settings, row, thatIdx ) {
7966                         var data = settings.aoData;
7967                         var rowData = data[ row ];
7968                         var i, ien, j, jen;
7969                         var loopRow, loopCells;
7970         
7971                         data.splice( row, 1 );
7972         
7973                         // Update the cached indexes
7974                         for ( i=0, ien=data.length ; i<ien ; i++ ) {
7975                                 loopRow = data[i];
7976                                 loopCells = loopRow.anCells;
7977         
7978                                 // Rows
7979                                 if ( loopRow.nTr !== null ) {
7980                                         loopRow.nTr._DT_RowIndex = i;
7981                                 }
7982         
7983                                 // Cells
7984                                 if ( loopCells !== null ) {
7985                                         for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
7986                                                 loopCells[j]._DT_CellIndex.row = i;
7987                                         }
7988                                 }
7989                         }
7990         
7991                         // Delete from the display arrays
7992                         _fnDeleteIndex( settings.aiDisplayMaster, row );
7993                         _fnDeleteIndex( settings.aiDisplay, row );
7994                         _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
7995         
7996                         // Check for an 'overflow' they case for displaying the table
7997                         _fnLengthOverflow( settings );
7998         
7999                         // Remove the row's ID reference if there is one
8000                         var id = settings.rowIdFn( rowData._aData );
8001                         if ( id !== undefined ) {
8002                                 delete settings.aIds[ id ];
8003                         }
8004                 } );
8005         
8006                 this.iterator( 'table', function ( settings ) {
8007                         for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8008                                 settings.aoData[i].idx = i;
8009                         }
8010                 } );
8011         
8012                 return this;
8013         } );
8014         
8015         
8016         _api_register( 'rows.add()', function ( rows ) {
8017                 var newRows = this.iterator( 'table', function ( settings ) {
8018                                 var row, i, ien;
8019                                 var out = [];
8020         
8021                                 for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8022                                         row = rows[i];
8023         
8024                                         if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8025                                                 out.push( _fnAddTr( settings, row )[0] );
8026                                         }
8027                                         else {
8028                                                 out.push( _fnAddData( settings, row ) );
8029                                         }
8030                                 }
8031         
8032                                 return out;
8033                         }, 1 );
8034         
8035                 // Return an Api.rows() extended instance, so rows().nodes() etc can be used
8036                 var modRows = this.rows( -1 );
8037                 modRows.pop();
8038                 $.merge( modRows, newRows );
8039         
8040                 return modRows;
8041         } );
8042         
8043         
8044         
8045         
8046         
8047         /**
8048          *
8049          */
8050         _api_register( 'row()', function ( selector, opts ) {
8051                 return _selector_first( this.rows( selector, opts ) );
8052         } );
8053         
8054         
8055         _api_register( 'row().data()', function ( data ) {
8056                 var ctx = this.context;
8057         
8058                 if ( data === undefined ) {
8059                         // Get
8060                         return ctx.length && this.length ?
8061                                 ctx[0].aoData[ this[0] ]._aData :
8062                                 undefined;
8063                 }
8064         
8065                 // Set
8066                 ctx[0].aoData[ this[0] ]._aData = data;
8067         
8068                 // Automatically invalidate
8069                 _fnInvalidate( ctx[0], this[0], 'data' );
8070         
8071                 return this;
8072         } );
8073         
8074         
8075         _api_register( 'row().node()', function () {
8076                 var ctx = this.context;
8077         
8078                 return ctx.length && this.length ?
8079                         ctx[0].aoData[ this[0] ].nTr || null :
8080                         null;
8081         } );
8082         
8083         
8084         _api_register( 'row.add()', function ( row ) {
8085                 // Allow a jQuery object to be passed in - only a single row is added from
8086                 // it though - the first element in the set
8087                 if ( row instanceof $ && row.length ) {
8088                         row = row[0];
8089                 }
8090         
8091                 var rows = this.iterator( 'table', function ( settings ) {
8092                         if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8093                                 return _fnAddTr( settings, row )[0];
8094                         }
8095                         return _fnAddData( settings, row );
8096                 } );
8097         
8098                 // Return an Api.rows() extended instance, with the newly added row selected
8099                 return this.row( rows[0] );
8100         } );
8101         
8102         
8103         
8104         var __details_add = function ( ctx, row, data, klass )
8105         {
8106                 // Convert to array of TR elements
8107                 var rows = [];
8108                 var addRow = function ( r, k ) {
8109                         // Recursion to allow for arrays of jQuery objects
8110                         if ( $.isArray( r ) || r instanceof $ ) {
8111                                 for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8112                                         addRow( r[i], k );
8113                                 }
8114                                 return;
8115                         }
8116         
8117                         // If we get a TR element, then just add it directly - up to the dev
8118                         // to add the correct number of columns etc
8119                         if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8120                                 rows.push( r );
8121                         }
8122                         else {
8123                                 // Otherwise create a row with a wrapper
8124                                 var created = $('<tr><td/></tr>').addClass( k );
8125                                 $('td', created)
8126                                         .addClass( k )
8127                                         .html( r )
8128                                         [0].colSpan = _fnVisbleColumns( ctx );
8129         
8130                                 rows.push( created[0] );
8131                         }
8132                 };
8133         
8134                 addRow( data, klass );
8135         
8136                 if ( row._details ) {
8137                         row._details.remove();
8138                 }
8139         
8140                 row._details = $(rows);
8141         
8142                 // If the children were already shown, that state should be retained
8143                 if ( row._detailsShow ) {
8144                         row._details.insertAfter( row.nTr );
8145                 }
8146         };
8147         
8148         
8149         var __details_remove = function ( api, idx )
8150         {
8151                 var ctx = api.context;
8152         
8153                 if ( ctx.length ) {
8154                         var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8155         
8156                         if ( row && row._details ) {
8157                                 row._details.remove();
8158         
8159                                 row._detailsShow = undefined;
8160                                 row._details = undefined;
8161                         }
8162                 }
8163         };
8164         
8165         
8166         var __details_display = function ( api, show ) {
8167                 var ctx = api.context;
8168         
8169                 if ( ctx.length && api.length ) {
8170                         var row = ctx[0].aoData[ api[0] ];
8171         
8172                         if ( row._details ) {
8173                                 row._detailsShow = show;
8174         
8175                                 if ( show ) {
8176                                         row._details.insertAfter( row.nTr );
8177                                 }
8178                                 else {
8179                                         row._details.detach();
8180                                 }
8181         
8182                                 __details_events( ctx[0] );
8183                         }
8184                 }
8185         };
8186         
8187         
8188         var __details_events = function ( settings )
8189         {
8190                 var api = new _Api( settings );
8191                 var namespace = '.dt.DT_details';
8192                 var drawEvent = 'draw'+namespace;
8193                 var colvisEvent = 'column-visibility'+namespace;
8194                 var destroyEvent = 'destroy'+namespace;
8195                 var data = settings.aoData;
8196         
8197                 api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8198         
8199                 if ( _pluck( data, '_details' ).length > 0 ) {
8200                         // On each draw, insert the required elements into the document
8201                         api.on( drawEvent, function ( e, ctx ) {
8202                                 if ( settings !== ctx ) {
8203                                         return;
8204                                 }
8205         
8206                                 api.rows( {page:'current'} ).eq(0).each( function (idx) {
8207                                         // Internal data grab
8208                                         var row = data[ idx ];
8209         
8210                                         if ( row._detailsShow ) {
8211                                                 row._details.insertAfter( row.nTr );
8212                                         }
8213                                 } );
8214                         } );
8215         
8216                         // Column visibility change - update the colspan
8217                         api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8218                                 if ( settings !== ctx ) {
8219                                         return;
8220                                 }
8221         
8222                                 // Update the colspan for the details rows (note, only if it already has
8223                                 // a colspan)
8224                                 var row, visible = _fnVisbleColumns( ctx );
8225         
8226                                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8227                                         row = data[i];
8228         
8229                                         if ( row._details ) {
8230                                                 row._details.children('td[colspan]').attr('colspan', visible );
8231                                         }
8232                                 }
8233                         } );
8234         
8235                         // Table destroyed - nuke any child rows
8236                         api.on( destroyEvent, function ( e, ctx ) {
8237                                 if ( settings !== ctx ) {
8238                                         return;
8239                                 }
8240         
8241                                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8242                                         if ( data[i]._details ) {
8243                                                 __details_remove( api, i );
8244                                         }
8245                                 }
8246                         } );
8247                 }
8248         };
8249         
8250         // Strings for the method names to help minification
8251         var _emp = '';
8252         var _child_obj = _emp+'row().child';
8253         var _child_mth = _child_obj+'()';
8254         
8255         // data can be:
8256         //  tr
8257         //  string
8258         //  jQuery or array of any of the above
8259         _api_register( _child_mth, function ( data, klass ) {
8260                 var ctx = this.context;
8261         
8262                 if ( data === undefined ) {
8263                         // get
8264                         return ctx.length && this.length ?
8265                                 ctx[0].aoData[ this[0] ]._details :
8266                                 undefined;
8267                 }
8268                 else if ( data === true ) {
8269                         // show
8270                         this.child.show();
8271                 }
8272                 else if ( data === false ) {
8273                         // remove
8274                         __details_remove( this );
8275                 }
8276                 else if ( ctx.length && this.length ) {
8277                         // set
8278                         __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8279                 }
8280         
8281                 return this;
8282         } );
8283         
8284         
8285         _api_register( [
8286                 _child_obj+'.show()',
8287                 _child_mth+'.show()' // only when `child()` was called with parameters (without
8288         ], function ( show ) {   // it returns an object and this method is not executed)
8289                 __details_display( this, true );
8290                 return this;
8291         } );
8292         
8293         
8294         _api_register( [
8295                 _child_obj+'.hide()',
8296                 _child_mth+'.hide()' // only when `child()` was called with parameters (without
8297         ], function () {         // it returns an object and this method is not executed)
8298                 __details_display( this, false );
8299                 return this;
8300         } );
8301         
8302         
8303         _api_register( [
8304                 _child_obj+'.remove()',
8305                 _child_mth+'.remove()' // only when `child()` was called with parameters (without
8306         ], function () {           // it returns an object and this method is not executed)
8307                 __details_remove( this );
8308                 return this;
8309         } );
8310         
8311         
8312         _api_register( _child_obj+'.isShown()', function () {
8313                 var ctx = this.context;
8314         
8315                 if ( ctx.length && this.length ) {
8316                         // _detailsShown as false or undefined will fall through to return false
8317                         return ctx[0].aoData[ this[0] ]._detailsShow || false;
8318                 }
8319                 return false;
8320         } );
8321         
8322         
8323         
8324         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8325          * Columns
8326          *
8327          * {integer}           - column index (>=0 count from left, <0 count from right)
8328          * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8329          * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8330          * "{string}:name"     - column name
8331          * "{string}"          - jQuery selector on column header nodes
8332          *
8333          */
8334         
8335         // can be an array of these items, comma separated list, or an array of comma
8336         // separated lists
8337         
8338         var __re_column_selector = /^(.+):(name|visIdx|visible)$/;
8339         
8340         
8341         // r1 and r2 are redundant - but it means that the parameters match for the
8342         // iterator callback in columns().data()
8343         var __columnData = function ( settings, column, r1, r2, rows ) {
8344                 var a = [];
8345                 for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8346                         a.push( _fnGetCellData( settings, rows[row], column ) );
8347                 }
8348                 return a;
8349         };
8350         
8351         
8352         var __column_selector = function ( settings, selector, opts )
8353         {
8354                 var
8355                         columns = settings.aoColumns,
8356                         names = _pluck( columns, 'sName' ),
8357                         nodes = _pluck( columns, 'nTh' );
8358         
8359                 var run = function ( s ) {
8360                         var selInt = _intVal( s );
8361         
8362                         // Selector - all
8363                         if ( s === '' ) {
8364                                 return _range( columns.length );
8365                         }
8366         
8367                         // Selector - index
8368                         if ( selInt !== null ) {
8369                                 return [ selInt >= 0 ?
8370                                         selInt : // Count from left
8371                                         columns.length + selInt // Count from right (+ because its a negative value)
8372                                 ];
8373                         }
8374         
8375                         // Selector = function
8376                         if ( typeof s === 'function' ) {
8377                                 var rows = _selector_row_indexes( settings, opts );
8378         
8379                                 return $.map( columns, function (col, idx) {
8380                                         return s(
8381                                                         idx,
8382                                                         __columnData( settings, idx, 0, 0, rows ),
8383                                                         nodes[ idx ]
8384                                                 ) ? idx : null;
8385                                 } );
8386                         }
8387         
8388                         // jQuery or string selector
8389                         var match = typeof s === 'string' ?
8390                                 s.match( __re_column_selector ) :
8391                                 '';
8392         
8393                         if ( match ) {
8394                                 switch( match[2] ) {
8395                                         case 'visIdx':
8396                                         case 'visible':
8397                                                 var idx = parseInt( match[1], 10 );
8398                                                 // Visible index given, convert to column index
8399                                                 if ( idx < 0 ) {
8400                                                         // Counting from the right
8401                                                         var visColumns = $.map( columns, function (col,i) {
8402                                                                 return col.bVisible ? i : null;
8403                                                         } );
8404                                                         return [ visColumns[ visColumns.length + idx ] ];
8405                                                 }
8406                                                 // Counting from the left
8407                                                 return [ _fnVisibleToColumnIndex( settings, idx ) ];
8408         
8409                                         case 'name':
8410                                                 // match by name. `names` is column index complete and in order
8411                                                 return $.map( names, function (name, i) {
8412                                                         return name === match[1] ? i : null;
8413                                                 } );
8414         
8415                                         default:
8416                                                 return [];
8417                                 }
8418                         }
8419         
8420                         // Cell in the table body
8421                         if ( s.nodeName && s._DT_CellIndex ) {
8422                                 return [ s._DT_CellIndex.column ];
8423                         }
8424         
8425                         // jQuery selector on the TH elements for the columns
8426                         var jqResult = $( nodes )
8427                                 .filter( s )
8428                                 .map( function () {
8429                                         return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8430                                 } )
8431                                 .toArray();
8432         
8433                         if ( jqResult.length || ! s.nodeName ) {
8434                                 return jqResult;
8435                         }
8436         
8437                         // Otherwise a node which might have a `dt-column` data attribute, or be
8438                         // a child or such an element
8439                         var host = $(s).closest('*[data-dt-column]');
8440                         return host.length ?
8441                                 [ host.data('dt-column') ] :
8442                                 [];
8443                 };
8444         
8445                 return _selector_run( 'column', selector, run, settings, opts );
8446         };
8447         
8448         
8449         var __setColumnVis = function ( settings, column, vis ) {
8450                 var
8451                         cols = settings.aoColumns,
8452                         col  = cols[ column ],
8453                         data = settings.aoData,
8454                         row, cells, i, ien, tr;
8455         
8456                 // Get
8457                 if ( vis === undefined ) {
8458                         return col.bVisible;
8459                 }
8460         
8461                 // Set
8462                 // No change
8463                 if ( col.bVisible === vis ) {
8464                         return;
8465                 }
8466         
8467                 if ( vis ) {
8468                         // Insert column
8469                         // Need to decide if we should use appendChild or insertBefore
8470                         var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8471         
8472                         for ( i=0, ien=data.length ; i<ien ; i++ ) {
8473                                 tr = data[i].nTr;
8474                                 cells = data[i].anCells;
8475         
8476                                 if ( tr ) {
8477                                         // insertBefore can act like appendChild if 2nd arg is null
8478                                         tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8479                                 }
8480                         }
8481                 }
8482                 else {
8483                         // Remove column
8484                         $( _pluck( settings.aoData, 'anCells', column ) ).detach();
8485                 }
8486         
8487                 // Common actions
8488                 col.bVisible = vis;
8489                 _fnDrawHead( settings, settings.aoHeader );
8490                 _fnDrawHead( settings, settings.aoFooter );
8491         
8492                 _fnSaveState( settings );
8493         };
8494         
8495         
8496         _api_register( 'columns()', function ( selector, opts ) {
8497                 // argument shifting
8498                 if ( selector === undefined ) {
8499                         selector = '';
8500                 }
8501                 else if ( $.isPlainObject( selector ) ) {
8502                         opts = selector;
8503                         selector = '';
8504                 }
8505         
8506                 opts = _selector_opts( opts );
8507         
8508                 var inst = this.iterator( 'table', function ( settings ) {
8509                         return __column_selector( settings, selector, opts );
8510                 }, 1 );
8511         
8512                 // Want argument shifting here and in _row_selector?
8513                 inst.selector.cols = selector;
8514                 inst.selector.opts = opts;
8515         
8516                 return inst;
8517         } );
8518         
8519         _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8520                 return this.iterator( 'column', function ( settings, column ) {
8521                         return settings.aoColumns[column].nTh;
8522                 }, 1 );
8523         } );
8524         
8525         _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8526                 return this.iterator( 'column', function ( settings, column ) {
8527                         return settings.aoColumns[column].nTf;
8528                 }, 1 );
8529         } );
8530         
8531         _api_registerPlural( 'columns().data()', 'column().data()', function () {
8532                 return this.iterator( 'column-rows', __columnData, 1 );
8533         } );
8534         
8535         _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8536                 return this.iterator( 'column', function ( settings, column ) {
8537                         return settings.aoColumns[column].mData;
8538                 }, 1 );
8539         } );
8540         
8541         _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8542                 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8543                         return _pluck_order( settings.aoData, rows,
8544                                 type === 'search' ? '_aFilterData' : '_aSortData', column
8545                         );
8546                 }, 1 );
8547         } );
8548         
8549         _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8550                 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8551                         return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8552                 }, 1 );
8553         } );
8554         
8555         _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8556                 var ret = this.iterator( 'column', function ( settings, column ) {
8557                         if ( vis === undefined ) {
8558                                 return settings.aoColumns[ column ].bVisible;
8559                         } // else
8560                         __setColumnVis( settings, column, vis );
8561                 } );
8562         
8563                 // Group the column visibility changes
8564                 if ( vis !== undefined ) {
8565                         // Second loop once the first is done for events
8566                         this.iterator( 'column', function ( settings, column ) {
8567                                 _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
8568                         } );
8569         
8570                         if ( calc === undefined || calc ) {
8571                                 this.columns.adjust();
8572                         }
8573                 }
8574         
8575                 return ret;
8576         } );
8577         
8578         _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8579                 return this.iterator( 'column', function ( settings, column ) {
8580                         return type === 'visible' ?
8581                                 _fnColumnIndexToVisible( settings, column ) :
8582                                 column;
8583                 }, 1 );
8584         } );
8585         
8586         _api_register( 'columns.adjust()', function () {
8587                 return this.iterator( 'table', function ( settings ) {
8588                         _fnAdjustColumnSizing( settings );
8589                 }, 1 );
8590         } );
8591         
8592         _api_register( 'column.index()', function ( type, idx ) {
8593                 if ( this.context.length !== 0 ) {
8594                         var ctx = this.context[0];
8595         
8596                         if ( type === 'fromVisible' || type === 'toData' ) {
8597                                 return _fnVisibleToColumnIndex( ctx, idx );
8598                         }
8599                         else if ( type === 'fromData' || type === 'toVisible' ) {
8600                                 return _fnColumnIndexToVisible( ctx, idx );
8601                         }
8602                 }
8603         } );
8604         
8605         _api_register( 'column()', function ( selector, opts ) {
8606                 return _selector_first( this.columns( selector, opts ) );
8607         } );
8608         
8609         
8610         
8611         var __cell_selector = function ( settings, selector, opts )
8612         {
8613                 var data = settings.aoData;
8614                 var rows = _selector_row_indexes( settings, opts );
8615                 var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8616                 var allCells = $( [].concat.apply([], cells) );
8617                 var row;
8618                 var columns = settings.aoColumns.length;
8619                 var a, i, ien, j, o, host;
8620         
8621                 var run = function ( s ) {
8622                         var fnSelector = typeof s === 'function';
8623         
8624                         if ( s === null || s === undefined || fnSelector ) {
8625                                 // All cells and function selectors
8626                                 a = [];
8627         
8628                                 for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8629                                         row = rows[i];
8630         
8631                                         for ( j=0 ; j<columns ; j++ ) {
8632                                                 o = {
8633                                                         row: row,
8634                                                         column: j
8635                                                 };
8636         
8637                                                 if ( fnSelector ) {
8638                                                         // Selector - function
8639                                                         host = data[ row ];
8640         
8641                                                         if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8642                                                                 a.push( o );
8643                                                         }
8644                                                 }
8645                                                 else {
8646                                                         // Selector - all
8647                                                         a.push( o );
8648                                                 }
8649                                         }
8650                                 }
8651         
8652                                 return a;
8653                         }
8654                         
8655                         // Selector - index
8656                         if ( $.isPlainObject( s ) ) {
8657                                 return [s];
8658                         }
8659         
8660                         // Selector - jQuery filtered cells
8661                         var jqResult = allCells
8662                                 .filter( s )
8663                                 .map( function (i, el) {
8664                                         return { // use a new object, in case someone changes the values
8665                                                 row:    el._DT_CellIndex.row,
8666                                                 column: el._DT_CellIndex.column
8667                                         };
8668                                 } )
8669                                 .toArray();
8670         
8671                         if ( jqResult.length || ! s.nodeName ) {
8672                                 return jqResult;
8673                         }
8674         
8675                         // Otherwise the selector is a node, and there is one last option - the
8676                         // element might be a child of an element which has dt-row and dt-column
8677                         // data attributes
8678                         host = $(s).closest('*[data-dt-row]');
8679                         return host.length ?
8680                                 [ {
8681                                         row: host.data('dt-row'),
8682                                         column: host.data('dt-column')
8683                                 } ] :
8684                                 [];
8685                 };
8686         
8687                 return _selector_run( 'cell', selector, run, settings, opts );
8688         };
8689         
8690         
8691         
8692         
8693         _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8694                 // Argument shifting
8695                 if ( $.isPlainObject( rowSelector ) ) {
8696                         // Indexes
8697                         if ( rowSelector.row === undefined ) {
8698                                 // Selector options in first parameter
8699                                 opts = rowSelector;
8700                                 rowSelector = null;
8701                         }
8702                         else {
8703                                 // Cell index objects in first parameter
8704                                 opts = columnSelector;
8705                                 columnSelector = null;
8706                         }
8707                 }
8708                 if ( $.isPlainObject( columnSelector ) ) {
8709                         opts = columnSelector;
8710                         columnSelector = null;
8711                 }
8712         
8713                 // Cell selector
8714                 if ( columnSelector === null || columnSelector === undefined ) {
8715                         return this.iterator( 'table', function ( settings ) {
8716                                 return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8717                         } );
8718                 }
8719         
8720                 // Row + column selector
8721                 var columns = this.columns( columnSelector, opts );
8722                 var rows = this.rows( rowSelector, opts );
8723                 var a, i, ien, j, jen;
8724         
8725                 var cells = this.iterator( 'table', function ( settings, idx ) {
8726                         a = [];
8727         
8728                         for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
8729                                 for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
8730                                         a.push( {
8731                                                 row:    rows[idx][i],
8732                                                 column: columns[idx][j]
8733                                         } );
8734                                 }
8735                         }
8736         
8737                         return a;
8738                 }, 1 );
8739         
8740                 $.extend( cells.selector, {
8741                         cols: columnSelector,
8742                         rows: rowSelector,
8743                         opts: opts
8744                 } );
8745         
8746                 return cells;
8747         } );
8748         
8749         
8750         _api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8751                 return this.iterator( 'cell', function ( settings, row, column ) {
8752                         var data = settings.aoData[ row ];
8753         
8754                         return data && data.anCells ?
8755                                 data.anCells[ column ] :
8756                                 undefined;
8757                 }, 1 );
8758         } );
8759         
8760         
8761         _api_register( 'cells().data()', function () {
8762                 return this.iterator( 'cell', function ( settings, row, column ) {
8763                         return _fnGetCellData( settings, row, column );
8764                 }, 1 );
8765         } );
8766         
8767         
8768         _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8769                 type = type === 'search' ? '_aFilterData' : '_aSortData';
8770         
8771                 return this.iterator( 'cell', function ( settings, row, column ) {
8772                         return settings.aoData[ row ][ type ][ column ];
8773                 }, 1 );
8774         } );
8775         
8776         
8777         _api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
8778                 return this.iterator( 'cell', function ( settings, row, column ) {
8779                         return _fnGetCellData( settings, row, column, type );
8780                 }, 1 );
8781         } );
8782         
8783         
8784         _api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8785                 return this.iterator( 'cell', function ( settings, row, column ) {
8786                         return {
8787                                 row: row,
8788                                 column: column,
8789                                 columnVisible: _fnColumnIndexToVisible( settings, column )
8790                         };
8791                 }, 1 );
8792         } );
8793         
8794         
8795         _api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
8796                 return this.iterator( 'cell', function ( settings, row, column ) {
8797                         _fnInvalidate( settings, row, src, column );
8798                 } );
8799         } );
8800         
8801         
8802         
8803         _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8804                 return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8805         } );
8806         
8807         
8808         _api_register( 'cell().data()', function ( data ) {
8809                 var ctx = this.context;
8810                 var cell = this[0];
8811         
8812                 if ( data === undefined ) {
8813                         // Get
8814                         return ctx.length && cell.length ?
8815                                 _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8816                                 undefined;
8817                 }
8818         
8819                 // Set
8820                 _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8821                 _fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
8822         
8823                 return this;
8824         } );
8825         
8826         
8827         
8828         /**
8829          * Get current ordering (sorting) that has been applied to the table.
8830          *
8831          * @returns {array} 2D array containing the sorting information for the first
8832          *   table in the current context. Each element in the parent array represents
8833          *   a column being sorted upon (i.e. multi-sorting with two columns would have
8834          *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8835          *   the column index that the sorting condition applies to, the second is the
8836          *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8837          *   index of the sorting order from the `column.sorting` initialisation array.
8838          *//**
8839          * Set the ordering for the table.
8840          *
8841          * @param {integer} order Column index to sort upon.
8842          * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8843          * @returns {DataTables.Api} this
8844          *//**
8845          * Set the ordering for the table.
8846          *
8847          * @param {array} order 1D array of sorting information to be applied.
8848          * @param {array} [...] Optional additional sorting conditions
8849          * @returns {DataTables.Api} this
8850          *//**
8851          * Set the ordering for the table.
8852          *
8853          * @param {array} order 2D array of sorting information to be applied.
8854          * @returns {DataTables.Api} this
8855          */
8856         _api_register( 'order()', function ( order, dir ) {
8857                 var ctx = this.context;
8858         
8859                 if ( order === undefined ) {
8860                         // get
8861                         return ctx.length !== 0 ?
8862                                 ctx[0].aaSorting :
8863                                 undefined;
8864                 }
8865         
8866                 // set
8867                 if ( typeof order === 'number' ) {
8868                         // Simple column / direction passed in
8869                         order = [ [ order, dir ] ];
8870                 }
8871                 else if ( order.length && ! $.isArray( order[0] ) ) {
8872                         // Arguments passed in (list of 1D arrays)
8873                         order = Array.prototype.slice.call( arguments );
8874                 }
8875                 // otherwise a 2D array was passed in
8876         
8877                 return this.iterator( 'table', function ( settings ) {
8878                         settings.aaSorting = order.slice();
8879                 } );
8880         } );
8881         
8882         
8883         /**
8884          * Attach a sort listener to an element for a given column
8885          *
8886          * @param {node|jQuery|string} node Identifier for the element(s) to attach the
8887          *   listener to. This can take the form of a single DOM node, a jQuery
8888          *   collection of nodes or a jQuery selector which will identify the node(s).
8889          * @param {integer} column the column that a click on this node will sort on
8890          * @param {function} [callback] callback function when sort is run
8891          * @returns {DataTables.Api} this
8892          */
8893         _api_register( 'order.listener()', function ( node, column, callback ) {
8894                 return this.iterator( 'table', function ( settings ) {
8895                         _fnSortAttachListener( settings, node, column, callback );
8896                 } );
8897         } );
8898         
8899         
8900         _api_register( 'order.fixed()', function ( set ) {
8901                 if ( ! set ) {
8902                         var ctx = this.context;
8903                         var fixed = ctx.length ?
8904                                 ctx[0].aaSortingFixed :
8905                                 undefined;
8906         
8907                         return $.isArray( fixed ) ?
8908                                 { pre: fixed } :
8909                                 fixed;
8910                 }
8911         
8912                 return this.iterator( 'table', function ( settings ) {
8913                         settings.aaSortingFixed = $.extend( true, {}, set );
8914                 } );
8915         } );
8916         
8917         
8918         // Order by the selected column(s)
8919         _api_register( [
8920                 'columns().order()',
8921                 'column().order()'
8922         ], function ( dir ) {
8923                 var that = this;
8924         
8925                 return this.iterator( 'table', function ( settings, i ) {
8926                         var sort = [];
8927         
8928                         $.each( that[i], function (j, col) {
8929                                 sort.push( [ col, dir ] );
8930                         } );
8931         
8932                         settings.aaSorting = sort;
8933                 } );
8934         } );
8935         
8936         
8937         
8938         _api_register( 'search()', function ( input, regex, smart, caseInsen ) {
8939                 var ctx = this.context;
8940         
8941                 if ( input === undefined ) {
8942                         // get
8943                         return ctx.length !== 0 ?
8944                                 ctx[0].oPreviousSearch.sSearch :
8945                                 undefined;
8946                 }
8947         
8948                 // set
8949                 return this.iterator( 'table', function ( settings ) {
8950                         if ( ! settings.oFeatures.bFilter ) {
8951                                 return;
8952                         }
8953         
8954                         _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
8955                                 "sSearch": input+"",
8956                                 "bRegex":  regex === null ? false : regex,
8957                                 "bSmart":  smart === null ? true  : smart,
8958                                 "bCaseInsensitive": caseInsen === null ? true : caseInsen
8959                         } ), 1 );
8960                 } );
8961         } );
8962         
8963         
8964         _api_registerPlural(
8965                 'columns().search()',
8966                 'column().search()',
8967                 function ( input, regex, smart, caseInsen ) {
8968                         return this.iterator( 'column', function ( settings, column ) {
8969                                 var preSearch = settings.aoPreSearchCols;
8970         
8971                                 if ( input === undefined ) {
8972                                         // get
8973                                         return preSearch[ column ].sSearch;
8974                                 }
8975         
8976                                 // set
8977                                 if ( ! settings.oFeatures.bFilter ) {
8978                                         return;
8979                                 }
8980         
8981                                 $.extend( preSearch[ column ], {
8982                                         "sSearch": input+"",
8983                                         "bRegex":  regex === null ? false : regex,
8984                                         "bSmart":  smart === null ? true  : smart,
8985                                         "bCaseInsensitive": caseInsen === null ? true : caseInsen
8986                                 } );
8987         
8988                                 _fnFilterComplete( settings, settings.oPreviousSearch, 1 );
8989                         } );
8990                 }
8991         );
8992         
8993         /*
8994          * State API methods
8995          */
8996         
8997         _api_register( 'state()', function () {
8998                 return this.context.length ?
8999                         this.context[0].oSavedState :
9000                         null;
9001         } );
9002         
9003         
9004         _api_register( 'state.clear()', function () {
9005                 return this.iterator( 'table', function ( settings ) {
9006                         // Save an empty object
9007                         settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
9008                 } );
9009         } );
9010         
9011         
9012         _api_register( 'state.loaded()', function () {
9013                 return this.context.length ?
9014                         this.context[0].oLoadedState :
9015                         null;
9016         } );
9017         
9018         
9019         _api_register( 'state.save()', function () {
9020                 return this.iterator( 'table', function ( settings ) {
9021                         _fnSaveState( settings );
9022                 } );
9023         } );
9024         
9025         
9026         
9027         /**
9028          * Provide a common method for plug-ins to check the version of DataTables being
9029          * used, in order to ensure compatibility.
9030          *
9031          *  @param {string} version Version string to check for, in the format "X.Y.Z".
9032          *    Note that the formats "X" and "X.Y" are also acceptable.
9033          *  @returns {boolean} true if this version of DataTables is greater or equal to
9034          *    the required version, or false if this version of DataTales is not
9035          *    suitable
9036          *  @static
9037          *  @dtopt API-Static
9038          *
9039          *  @example
9040          *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9041          */
9042         DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
9043         {
9044                 var aThis = DataTable.version.split('.');
9045                 var aThat = version.split('.');
9046                 var iThis, iThat;
9047         
9048                 for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
9049                         iThis = parseInt( aThis[i], 10 ) || 0;
9050                         iThat = parseInt( aThat[i], 10 ) || 0;
9051         
9052                         // Parts are the same, keep comparing
9053                         if (iThis === iThat) {
9054                                 continue;
9055                         }
9056         
9057                         // Parts are different, return immediately
9058                         return iThis > iThat;
9059                 }
9060         
9061                 return true;
9062         };
9063         
9064         
9065         /**
9066          * Check if a `<table>` node is a DataTable table already or not.
9067          *
9068          *  @param {node|jquery|string} table Table node, jQuery object or jQuery
9069          *      selector for the table to test. Note that if more than more than one
9070          *      table is passed on, only the first will be checked
9071          *  @returns {boolean} true the table given is a DataTable, or false otherwise
9072          *  @static
9073          *  @dtopt API-Static
9074          *
9075          *  @example
9076          *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9077          *      $('#example').dataTable();
9078          *    }
9079          */
9080         DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
9081         {
9082                 var t = $(table).get(0);
9083                 var is = false;
9084         
9085                 $.each( DataTable.settings, function (i, o) {
9086                         var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9087                         var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
9088         
9089                         if ( o.nTable === t || head === t || foot === t ) {
9090                                 is = true;
9091                         }
9092                 } );
9093         
9094                 return is;
9095         };
9096         
9097         
9098         /**
9099          * Get all DataTable tables that have been initialised - optionally you can
9100          * select to get only currently visible tables.
9101          *
9102          *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
9103          *    or visible tables only.
9104          *  @returns {array} Array of `table` nodes (not DataTable instances) which are
9105          *    DataTables
9106          *  @static
9107          *  @dtopt API-Static
9108          *
9109          *  @example
9110          *    $.each( $.fn.dataTable.tables(true), function () {
9111          *      $(table).DataTable().columns.adjust();
9112          *    } );
9113          */
9114         DataTable.tables = DataTable.fnTables = function ( visible )
9115         {
9116                 var api = false;
9117         
9118                 if ( $.isPlainObject( visible ) ) {
9119                         api = visible.api;
9120                         visible = visible.visible;
9121                 }
9122         
9123                 var a = $.map( DataTable.settings, function (o) {
9124                         if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
9125                                 return o.nTable;
9126                         }
9127                 } );
9128         
9129                 return api ?
9130                         new _Api( a ) :
9131                         a;
9132         };
9133         
9134         
9135         /**
9136          * Convert from camel case parameters to Hungarian notation. This is made public
9137          * for the extensions to provide the same ability as DataTables core to accept
9138          * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9139          * parameters.
9140          *
9141          *  @param {object} src The model object which holds all parameters that can be
9142          *    mapped.
9143          *  @param {object} user The object to convert from camel case to Hungarian.
9144          *  @param {boolean} force When set to `true`, properties which already have a
9145          *    Hungarian value in the `user` object will be overwritten. Otherwise they
9146          *    won't be.
9147          */
9148         DataTable.camelToHungarian = _fnCamelToHungarian;
9149         
9150         
9151         
9152         /**
9153          *
9154          */
9155         _api_register( '$()', function ( selector, opts ) {
9156                 var
9157                         rows   = this.rows( opts ).nodes(), // Get all rows
9158                         jqRows = $(rows);
9159         
9160                 return $( [].concat(
9161                         jqRows.filter( selector ).toArray(),
9162                         jqRows.find( selector ).toArray()
9163                 ) );
9164         } );
9165         
9166         
9167         // jQuery functions to operate on the tables
9168         $.each( [ 'on', 'one', 'off' ], function (i, key) {
9169                 _api_register( key+'()', function ( /* event, handler */ ) {
9170                         var args = Array.prototype.slice.call(arguments);
9171         
9172                         // Add the `dt` namespace automatically if it isn't already present
9173                         if ( ! args[0].match(/\.dt\b/) ) {
9174                                 args[0] += '.dt';
9175                         }
9176         
9177                         var inst = $( this.tables().nodes() );
9178                         inst[key].apply( inst, args );
9179                         return this;
9180                 } );
9181         } );
9182         
9183         
9184         _api_register( 'clear()', function () {
9185                 return this.iterator( 'table', function ( settings ) {
9186                         _fnClearTable( settings );
9187                 } );
9188         } );
9189         
9190         
9191         _api_register( 'settings()', function () {
9192                 return new _Api( this.context, this.context );
9193         } );
9194         
9195         
9196         _api_register( 'init()', function () {
9197                 var ctx = this.context;
9198                 return ctx.length ? ctx[0].oInit : null;
9199         } );
9200         
9201         
9202         _api_register( 'data()', function () {
9203                 return this.iterator( 'table', function ( settings ) {
9204                         return _pluck( settings.aoData, '_aData' );
9205                 } ).flatten();
9206         } );
9207         
9208         
9209         _api_register( 'destroy()', function ( remove ) {
9210                 remove = remove || false;
9211         
9212                 return this.iterator( 'table', function ( settings ) {
9213                         var orig      = settings.nTableWrapper.parentNode;
9214                         var classes   = settings.oClasses;
9215                         var table     = settings.nTable;
9216                         var tbody     = settings.nTBody;
9217                         var thead     = settings.nTHead;
9218                         var tfoot     = settings.nTFoot;
9219                         var jqTable   = $(table);
9220                         var jqTbody   = $(tbody);
9221                         var jqWrapper = $(settings.nTableWrapper);
9222                         var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9223                         var i, ien;
9224         
9225                         // Flag to note that the table is currently being destroyed - no action
9226                         // should be taken
9227                         settings.bDestroying = true;
9228         
9229                         // Fire off the destroy callbacks for plug-ins etc
9230                         _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9231         
9232                         // If not being removed from the document, make all columns visible
9233                         if ( ! remove ) {
9234                                 new _Api( settings ).columns().visible( true );
9235                         }
9236         
9237                         // Blitz all `DT` namespaced events (these are internal events, the
9238                         // lowercase, `dt` events are user subscribed and they are responsible
9239                         // for removing them
9240                         jqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT');
9241                         $(window).unbind('.DT-'+settings.sInstance);
9242         
9243                         // When scrolling we had to break the table up - restore it
9244                         if ( table != thead.parentNode ) {
9245                                 jqTable.children('thead').detach();
9246                                 jqTable.append( thead );
9247                         }
9248         
9249                         if ( tfoot && table != tfoot.parentNode ) {
9250                                 jqTable.children('tfoot').detach();
9251                                 jqTable.append( tfoot );
9252                         }
9253         
9254                         settings.aaSorting = [];
9255                         settings.aaSortingFixed = [];
9256                         _fnSortingClasses( settings );
9257         
9258                         $( rows ).removeClass( settings.asStripeClasses.join(' ') );
9259         
9260                         $('th, td', thead).removeClass( classes.sSortable+' '+
9261                                 classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9262                         );
9263         
9264                         if ( settings.bJUI ) {
9265                                 $('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach();
9266                                 $('th, td', thead).each( function () {
9267                                         var wrapper = $('div.'+classes.sSortJUIWrapper, this);
9268                                         $(this).append( wrapper.contents() );
9269                                         wrapper.detach();
9270                                 } );
9271                         }
9272         
9273                         // Add the TR elements back into the table in their original order
9274                         jqTbody.children().detach();
9275                         jqTbody.append( rows );
9276         
9277                         // Remove the DataTables generated nodes, events and classes
9278                         var removedMethod = remove ? 'remove' : 'detach';
9279                         jqTable[ removedMethod ]();
9280                         jqWrapper[ removedMethod ]();
9281         
9282                         // If we need to reattach the table to the document
9283                         if ( ! remove && orig ) {
9284                                 // insertBefore acts like appendChild if !arg[1]
9285                                 orig.insertBefore( table, settings.nTableReinsertBefore );
9286         
9287                                 // Restore the width of the original table - was read from the style property,
9288                                 // so we can restore directly to that
9289                                 jqTable
9290                                         .css( 'width', settings.sDestroyWidth )
9291                                         .removeClass( classes.sTable );
9292         
9293                                 // If the were originally stripe classes - then we add them back here.
9294                                 // Note this is not fool proof (for example if not all rows had stripe
9295                                 // classes - but it's a good effort without getting carried away
9296                                 ien = settings.asDestroyStripes.length;
9297         
9298                                 if ( ien ) {
9299                                         jqTbody.children().each( function (i) {
9300                                                 $(this).addClass( settings.asDestroyStripes[i % ien] );
9301                                         } );
9302                                 }
9303                         }
9304         
9305                         /* Remove the settings object from the settings array */
9306                         var idx = $.inArray( settings, DataTable.settings );
9307                         if ( idx !== -1 ) {
9308                                 DataTable.settings.splice( idx, 1 );
9309                         }
9310                 } );
9311         } );
9312         
9313         
9314         // Add the `every()` method for rows, columns and cells in a compact form
9315         $.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9316                 _api_register( type+'s().every()', function ( fn ) {
9317                         var opts = this.selector.opts;
9318                         var api = this;
9319         
9320                         return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9321                                 // Rows and columns:
9322                                 //  arg1 - index
9323                                 //  arg2 - table counter
9324                                 //  arg3 - loop counter
9325                                 //  arg4 - undefined
9326                                 // Cells:
9327                                 //  arg1 - row index
9328                                 //  arg2 - column index
9329                                 //  arg3 - table counter
9330                                 //  arg4 - loop counter
9331                                 fn.call(
9332                                         api[ type ](
9333                                                 arg1,
9334                                                 type==='cell' ? arg2 : opts,
9335                                                 type==='cell' ? opts : undefined
9336                                         ),
9337                                         arg1, arg2, arg3, arg4
9338                                 );
9339                         } );
9340                 } );
9341         } );
9342         
9343         
9344         // i18n method for extensions to be able to use the language object from the
9345         // DataTable
9346         _api_register( 'i18n()', function ( token, def, plural ) {
9347                 var ctx = this.context[0];
9348                 var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9349         
9350                 if ( resolved === undefined ) {
9351                         resolved = def;
9352                 }
9353         
9354                 if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9355                         resolved = resolved[ plural ] !== undefined ?
9356                                 resolved[ plural ] :
9357                                 resolved._;
9358                 }
9359         
9360                 return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9361         } );
9363         /**
9364          * Version string for plug-ins to check compatibility. Allowed format is
9365          * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9366          * only for non-release builds. See http://semver.org/ for more information.
9367          *  @member
9368          *  @type string
9369          *  @default Version number
9370          */
9371         DataTable.version = "1.10.12";
9373         /**
9374          * Private data store, containing all of the settings objects that are
9375          * created for the tables on a given page.
9376          *
9377          * Note that the `DataTable.settings` object is aliased to
9378          * `jQuery.fn.dataTableExt` through which it may be accessed and
9379          * manipulated, or `jQuery.fn.dataTable.settings`.
9380          *  @member
9381          *  @type array
9382          *  @default []
9383          *  @private
9384          */
9385         DataTable.settings = [];
9387         /**
9388          * Object models container, for the various models that DataTables has
9389          * available to it. These models define the objects that are used to hold
9390          * the active state and configuration of the table.
9391          *  @namespace
9392          */
9393         DataTable.models = {};
9394         
9395         
9396         
9397         /**
9398          * Template object for the way in which DataTables holds information about
9399          * search information for the global filter and individual column filters.
9400          *  @namespace
9401          */
9402         DataTable.models.oSearch = {
9403                 /**
9404                  * Flag to indicate if the filtering should be case insensitive or not
9405                  *  @type boolean
9406                  *  @default true
9407                  */
9408                 "bCaseInsensitive": true,
9409         
9410                 /**
9411                  * Applied search term
9412                  *  @type string
9413                  *  @default <i>Empty string</i>
9414                  */
9415                 "sSearch": "",
9416         
9417                 /**
9418                  * Flag to indicate if the search term should be interpreted as a
9419                  * regular expression (true) or not (false) and therefore and special
9420                  * regex characters escaped.
9421                  *  @type boolean
9422                  *  @default false
9423                  */
9424                 "bRegex": false,
9425         
9426                 /**
9427                  * Flag to indicate if DataTables is to use its smart filtering or not.
9428                  *  @type boolean
9429                  *  @default true
9430                  */
9431                 "bSmart": true
9432         };
9433         
9434         
9435         
9436         
9437         /**
9438          * Template object for the way in which DataTables holds information about
9439          * each individual row. This is the object format used for the settings
9440          * aoData array.
9441          *  @namespace
9442          */
9443         DataTable.models.oRow = {
9444                 /**
9445                  * TR element for the row
9446                  *  @type node
9447                  *  @default null
9448                  */
9449                 "nTr": null,
9450         
9451                 /**
9452                  * Array of TD elements for each row. This is null until the row has been
9453                  * created.
9454                  *  @type array nodes
9455                  *  @default []
9456                  */
9457                 "anCells": null,
9458         
9459                 /**
9460                  * Data object from the original data source for the row. This is either
9461                  * an array if using the traditional form of DataTables, or an object if
9462                  * using mData options. The exact type will depend on the passed in
9463                  * data from the data source, or will be an array if using DOM a data
9464                  * source.
9465                  *  @type array|object
9466                  *  @default []
9467                  */
9468                 "_aData": [],
9469         
9470                 /**
9471                  * Sorting data cache - this array is ostensibly the same length as the
9472                  * number of columns (although each index is generated only as it is
9473                  * needed), and holds the data that is used for sorting each column in the
9474                  * row. We do this cache generation at the start of the sort in order that
9475                  * the formatting of the sort data need be done only once for each cell
9476                  * per sort. This array should not be read from or written to by anything
9477                  * other than the master sorting methods.
9478                  *  @type array
9479                  *  @default null
9480                  *  @private
9481                  */
9482                 "_aSortData": null,
9483         
9484                 /**
9485                  * Per cell filtering data cache. As per the sort data cache, used to
9486                  * increase the performance of the filtering in DataTables
9487                  *  @type array
9488                  *  @default null
9489                  *  @private
9490                  */
9491                 "_aFilterData": null,
9492         
9493                 /**
9494                  * Filtering data cache. This is the same as the cell filtering cache, but
9495                  * in this case a string rather than an array. This is easily computed with
9496                  * a join on `_aFilterData`, but is provided as a cache so the join isn't
9497                  * needed on every search (memory traded for performance)
9498                  *  @type array
9499                  *  @default null
9500                  *  @private
9501                  */
9502                 "_sFilterRow": null,
9503         
9504                 /**
9505                  * Cache of the class name that DataTables has applied to the row, so we
9506                  * can quickly look at this variable rather than needing to do a DOM check
9507                  * on className for the nTr property.
9508                  *  @type string
9509                  *  @default <i>Empty string</i>
9510                  *  @private
9511                  */
9512                 "_sRowStripe": "",
9513         
9514                 /**
9515                  * Denote if the original data source was from the DOM, or the data source
9516                  * object. This is used for invalidating data, so DataTables can
9517                  * automatically read data from the original source, unless uninstructed
9518                  * otherwise.
9519                  *  @type string
9520                  *  @default null
9521                  *  @private
9522                  */
9523                 "src": null,
9524         
9525                 /**
9526                  * Index in the aoData array. This saves an indexOf lookup when we have the
9527                  * object, but want to know the index
9528                  *  @type integer
9529                  *  @default -1
9530                  *  @private
9531                  */
9532                 "idx": -1
9533         };
9534         
9535         
9536         /**
9537          * Template object for the column information object in DataTables. This object
9538          * is held in the settings aoColumns array and contains all the information that
9539          * DataTables needs about each individual column.
9540          *
9541          * Note that this object is related to {@link DataTable.defaults.column}
9542          * but this one is the internal data store for DataTables's cache of columns.
9543          * It should NOT be manipulated outside of DataTables. Any configuration should
9544          * be done through the initialisation options.
9545          *  @namespace
9546          */
9547         DataTable.models.oColumn = {
9548                 /**
9549                  * Column index. This could be worked out on-the-fly with $.inArray, but it
9550                  * is faster to just hold it as a variable
9551                  *  @type integer
9552                  *  @default null
9553                  */
9554                 "idx": null,
9555         
9556                 /**
9557                  * A list of the columns that sorting should occur on when this column
9558                  * is sorted. That this property is an array allows multi-column sorting
9559                  * to be defined for a column (for example first name / last name columns
9560                  * would benefit from this). The values are integers pointing to the
9561                  * columns to be sorted on (typically it will be a single integer pointing
9562                  * at itself, but that doesn't need to be the case).
9563                  *  @type array
9564                  */
9565                 "aDataSort": null,
9566         
9567                 /**
9568                  * Define the sorting directions that are applied to the column, in sequence
9569                  * as the column is repeatedly sorted upon - i.e. the first value is used
9570                  * as the sorting direction when the column if first sorted (clicked on).
9571                  * Sort it again (click again) and it will move on to the next index.
9572                  * Repeat until loop.
9573                  *  @type array
9574                  */
9575                 "asSorting": null,
9576         
9577                 /**
9578                  * Flag to indicate if the column is searchable, and thus should be included
9579                  * in the filtering or not.
9580                  *  @type boolean
9581                  */
9582                 "bSearchable": null,
9583         
9584                 /**
9585                  * Flag to indicate if the column is sortable or not.
9586                  *  @type boolean
9587                  */
9588                 "bSortable": null,
9589         
9590                 /**
9591                  * Flag to indicate if the column is currently visible in the table or not
9592                  *  @type boolean
9593                  */
9594                 "bVisible": null,
9595         
9596                 /**
9597                  * Store for manual type assignment using the `column.type` option. This
9598                  * is held in store so we can manipulate the column's `sType` property.
9599                  *  @type string
9600                  *  @default null
9601                  *  @private
9602                  */
9603                 "_sManualType": null,
9604         
9605                 /**
9606                  * Flag to indicate if HTML5 data attributes should be used as the data
9607                  * source for filtering or sorting. True is either are.
9608                  *  @type boolean
9609                  *  @default false
9610                  *  @private
9611                  */
9612                 "_bAttrSrc": false,
9613         
9614                 /**
9615                  * Developer definable function that is called whenever a cell is created (Ajax source,
9616                  * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9617                  * allowing you to modify the DOM element (add background colour for example) when the
9618                  * element is available.
9619                  *  @type function
9620                  *  @param {element} nTd The TD node that has been created
9621                  *  @param {*} sData The Data for the cell
9622                  *  @param {array|object} oData The data for the whole row
9623                  *  @param {int} iRow The row index for the aoData data store
9624                  *  @default null
9625                  */
9626                 "fnCreatedCell": null,
9627         
9628                 /**
9629                  * Function to get data from a cell in a column. You should <b>never</b>
9630                  * access data directly through _aData internally in DataTables - always use
9631                  * the method attached to this property. It allows mData to function as
9632                  * required. This function is automatically assigned by the column
9633                  * initialisation method
9634                  *  @type function
9635                  *  @param {array|object} oData The data array/object for the array
9636                  *    (i.e. aoData[]._aData)
9637                  *  @param {string} sSpecific The specific data type you want to get -
9638                  *    'display', 'type' 'filter' 'sort'
9639                  *  @returns {*} The data for the cell from the given row's data
9640                  *  @default null
9641                  */
9642                 "fnGetData": null,
9643         
9644                 /**
9645                  * Function to set data for a cell in the column. You should <b>never</b>
9646                  * set the data directly to _aData internally in DataTables - always use
9647                  * this method. It allows mData to function as required. This function
9648                  * is automatically assigned by the column initialisation method
9649                  *  @type function
9650                  *  @param {array|object} oData The data array/object for the array
9651                  *    (i.e. aoData[]._aData)
9652                  *  @param {*} sValue Value to set
9653                  *  @default null
9654                  */
9655                 "fnSetData": null,
9656         
9657                 /**
9658                  * Property to read the value for the cells in the column from the data
9659                  * source array / object. If null, then the default content is used, if a
9660                  * function is given then the return from the function is used.
9661                  *  @type function|int|string|null
9662                  *  @default null
9663                  */
9664                 "mData": null,
9665         
9666                 /**
9667                  * Partner property to mData which is used (only when defined) to get
9668                  * the data - i.e. it is basically the same as mData, but without the
9669                  * 'set' option, and also the data fed to it is the result from mData.
9670                  * This is the rendering method to match the data method of mData.
9671                  *  @type function|int|string|null
9672                  *  @default null
9673                  */
9674                 "mRender": null,
9675         
9676                 /**
9677                  * Unique header TH/TD element for this column - this is what the sorting
9678                  * listener is attached to (if sorting is enabled.)
9679                  *  @type node
9680                  *  @default null
9681                  */
9682                 "nTh": null,
9683         
9684                 /**
9685                  * Unique footer TH/TD element for this column (if there is one). Not used
9686                  * in DataTables as such, but can be used for plug-ins to reference the
9687                  * footer for each column.
9688                  *  @type node
9689                  *  @default null
9690                  */
9691                 "nTf": null,
9692         
9693                 /**
9694                  * The class to apply to all TD elements in the table's TBODY for the column
9695                  *  @type string
9696                  *  @default null
9697                  */
9698                 "sClass": null,
9699         
9700                 /**
9701                  * When DataTables calculates the column widths to assign to each column,
9702                  * it finds the longest string in each column and then constructs a
9703                  * temporary table and reads the widths from that. The problem with this
9704                  * is that "mmm" is much wider then "iiii", but the latter is a longer
9705                  * string - thus the calculation can go wrong (doing it properly and putting
9706                  * it into an DOM object and measuring that is horribly(!) slow). Thus as
9707                  * a "work around" we provide this option. It will append its value to the
9708                  * text that is found to be the longest string for the column - i.e. padding.
9709                  *  @type string
9710                  */
9711                 "sContentPadding": null,
9712         
9713                 /**
9714                  * Allows a default value to be given for a column's data, and will be used
9715                  * whenever a null data source is encountered (this can be because mData
9716                  * is set to null, or because the data source itself is null).
9717                  *  @type string
9718                  *  @default null
9719                  */
9720                 "sDefaultContent": null,
9721         
9722                 /**
9723                  * Name for the column, allowing reference to the column by name as well as
9724                  * by index (needs a lookup to work by name).
9725                  *  @type string
9726                  */
9727                 "sName": null,
9728         
9729                 /**
9730                  * Custom sorting data type - defines which of the available plug-ins in
9731                  * afnSortData the custom sorting will use - if any is defined.
9732                  *  @type string
9733                  *  @default std
9734                  */
9735                 "sSortDataType": 'std',
9736         
9737                 /**
9738                  * Class to be applied to the header element when sorting on this column
9739                  *  @type string
9740                  *  @default null
9741                  */
9742                 "sSortingClass": null,
9743         
9744                 /**
9745                  * Class to be applied to the header element when sorting on this column -
9746                  * when jQuery UI theming is used.
9747                  *  @type string
9748                  *  @default null
9749                  */
9750                 "sSortingClassJUI": null,
9751         
9752                 /**
9753                  * Title of the column - what is seen in the TH element (nTh).
9754                  *  @type string
9755                  */
9756                 "sTitle": null,
9757         
9758                 /**
9759                  * Column sorting and filtering type
9760                  *  @type string
9761                  *  @default null
9762                  */
9763                 "sType": null,
9764         
9765                 /**
9766                  * Width of the column
9767                  *  @type string
9768                  *  @default null
9769                  */
9770                 "sWidth": null,
9771         
9772                 /**
9773                  * Width of the column when it was first "encountered"
9774                  *  @type string
9775                  *  @default null
9776                  */
9777                 "sWidthOrig": null
9778         };
9779         
9780         
9781         /*
9782          * Developer note: The properties of the object below are given in Hungarian
9783          * notation, that was used as the interface for DataTables prior to v1.10, however
9784          * from v1.10 onwards the primary interface is camel case. In order to avoid
9785          * breaking backwards compatibility utterly with this change, the Hungarian
9786          * version is still, internally the primary interface, but is is not documented
9787          * - hence the @name tags in each doc comment. This allows a Javascript function
9788          * to create a map from Hungarian notation to camel case (going the other direction
9789          * would require each property to be listed, which would at around 3K to the size
9790          * of DataTables, while this method is about a 0.5K hit.
9791          *
9792          * Ultimately this does pave the way for Hungarian notation to be dropped
9793          * completely, but that is a massive amount of work and will break current
9794          * installs (therefore is on-hold until v2).
9795          */
9796         
9797         /**
9798          * Initialisation options that can be given to DataTables at initialisation
9799          * time.
9800          *  @namespace
9801          */
9802         DataTable.defaults = {
9803                 /**
9804                  * An array of data to use for the table, passed in at initialisation which
9805                  * will be used in preference to any data which is already in the DOM. This is
9806                  * particularly useful for constructing tables purely in Javascript, for
9807                  * example with a custom Ajax call.
9808                  *  @type array
9809                  *  @default null
9810                  *
9811                  *  @dtopt Option
9812                  *  @name DataTable.defaults.data
9813                  *
9814                  *  @example
9815                  *    // Using a 2D array data source
9816                  *    $(document).ready( function () {
9817                  *      $('#example').dataTable( {
9818                  *        "data": [
9819                  *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9820                  *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9821                  *        ],
9822                  *        "columns": [
9823                  *          { "title": "Engine" },
9824                  *          { "title": "Browser" },
9825                  *          { "title": "Platform" },
9826                  *          { "title": "Version" },
9827                  *          { "title": "Grade" }
9828                  *        ]
9829                  *      } );
9830                  *    } );
9831                  *
9832                  *  @example
9833                  *    // Using an array of objects as a data source (`data`)
9834                  *    $(document).ready( function () {
9835                  *      $('#example').dataTable( {
9836                  *        "data": [
9837                  *          {
9838                  *            "engine":   "Trident",
9839                  *            "browser":  "Internet Explorer 4.0",
9840                  *            "platform": "Win 95+",
9841                  *            "version":  4,
9842                  *            "grade":    "X"
9843                  *          },
9844                  *          {
9845                  *            "engine":   "Trident",
9846                  *            "browser":  "Internet Explorer 5.0",
9847                  *            "platform": "Win 95+",
9848                  *            "version":  5,
9849                  *            "grade":    "C"
9850                  *          }
9851                  *        ],
9852                  *        "columns": [
9853                  *          { "title": "Engine",   "data": "engine" },
9854                  *          { "title": "Browser",  "data": "browser" },
9855                  *          { "title": "Platform", "data": "platform" },
9856                  *          { "title": "Version",  "data": "version" },
9857                  *          { "title": "Grade",    "data": "grade" }
9858                  *        ]
9859                  *      } );
9860                  *    } );
9861                  */
9862                 "aaData": null,
9863         
9864         
9865                 /**
9866                  * If ordering is enabled, then DataTables will perform a first pass sort on
9867                  * initialisation. You can define which column(s) the sort is performed
9868                  * upon, and the sorting direction, with this variable. The `sorting` array
9869                  * should contain an array for each column to be sorted initially containing
9870                  * the column's index and a direction string ('asc' or 'desc').
9871                  *  @type array
9872                  *  @default [[0,'asc']]
9873                  *
9874                  *  @dtopt Option
9875                  *  @name DataTable.defaults.order
9876                  *
9877                  *  @example
9878                  *    // Sort by 3rd column first, and then 4th column
9879                  *    $(document).ready( function() {
9880                  *      $('#example').dataTable( {
9881                  *        "order": [[2,'asc'], [3,'desc']]
9882                  *      } );
9883                  *    } );
9884                  *
9885                  *    // No initial sorting
9886                  *    $(document).ready( function() {
9887                  *      $('#example').dataTable( {
9888                  *        "order": []
9889                  *      } );
9890                  *    } );
9891                  */
9892                 "aaSorting": [[0,'asc']],
9893         
9894         
9895                 /**
9896                  * This parameter is basically identical to the `sorting` parameter, but
9897                  * cannot be overridden by user interaction with the table. What this means
9898                  * is that you could have a column (visible or hidden) which the sorting
9899                  * will always be forced on first - any sorting after that (from the user)
9900                  * will then be performed as required. This can be useful for grouping rows
9901                  * together.
9902                  *  @type array
9903                  *  @default null
9904                  *
9905                  *  @dtopt Option
9906                  *  @name DataTable.defaults.orderFixed
9907                  *
9908                  *  @example
9909                  *    $(document).ready( function() {
9910                  *      $('#example').dataTable( {
9911                  *        "orderFixed": [[0,'asc']]
9912                  *      } );
9913                  *    } )
9914                  */
9915                 "aaSortingFixed": [],
9916         
9917         
9918                 /**
9919                  * DataTables can be instructed to load data to display in the table from a
9920                  * Ajax source. This option defines how that Ajax call is made and where to.
9921                  *
9922                  * The `ajax` property has three different modes of operation, depending on
9923                  * how it is defined. These are:
9924                  *
9925                  * * `string` - Set the URL from where the data should be loaded from.
9926                  * * `object` - Define properties for `jQuery.ajax`.
9927                  * * `function` - Custom data get function
9928                  *
9929                  * `string`
9930                  * --------
9931                  *
9932                  * As a string, the `ajax` property simply defines the URL from which
9933                  * DataTables will load data.
9934                  *
9935                  * `object`
9936                  * --------
9937                  *
9938                  * As an object, the parameters in the object are passed to
9939                  * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
9940                  * of the Ajax request. DataTables has a number of default parameters which
9941                  * you can override using this option. Please refer to the jQuery
9942                  * documentation for a full description of the options available, although
9943                  * the following parameters provide additional options in DataTables or
9944                  * require special consideration:
9945                  *
9946                  * * `data` - As with jQuery, `data` can be provided as an object, but it
9947                  *   can also be used as a function to manipulate the data DataTables sends
9948                  *   to the server. The function takes a single parameter, an object of
9949                  *   parameters with the values that DataTables has readied for sending. An
9950                  *   object may be returned which will be merged into the DataTables
9951                  *   defaults, or you can add the items to the object that was passed in and
9952                  *   not return anything from the function. This supersedes `fnServerParams`
9953                  *   from DataTables 1.9-.
9954                  *
9955                  * * `dataSrc` - By default DataTables will look for the property `data` (or
9956                  *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
9957                  *   from an Ajax source or for server-side processing - this parameter
9958                  *   allows that property to be changed. You can use Javascript dotted
9959                  *   object notation to get a data source for multiple levels of nesting, or
9960                  *   it my be used as a function. As a function it takes a single parameter,
9961                  *   the JSON returned from the server, which can be manipulated as
9962                  *   required, with the returned value being that used by DataTables as the
9963                  *   data source for the table. This supersedes `sAjaxDataProp` from
9964                  *   DataTables 1.9-.
9965                  *
9966                  * * `success` - Should not be overridden it is used internally in
9967                  *   DataTables. To manipulate / transform the data returned by the server
9968                  *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
9969                  *
9970                  * `function`
9971                  * ----------
9972                  *
9973                  * As a function, making the Ajax call is left up to yourself allowing
9974                  * complete control of the Ajax request. Indeed, if desired, a method other
9975                  * than Ajax could be used to obtain the required data, such as Web storage
9976                  * or an AIR database.
9977                  *
9978                  * The function is given four parameters and no return is required. The
9979                  * parameters are:
9980                  *
9981                  * 1. _object_ - Data to send to the server
9982                  * 2. _function_ - Callback function that must be executed when the required
9983                  *    data has been obtained. That data should be passed into the callback
9984                  *    as the only parameter
9985                  * 3. _object_ - DataTables settings object for the table
9986                  *
9987                  * Note that this supersedes `fnServerData` from DataTables 1.9-.
9988                  *
9989                  *  @type string|object|function
9990                  *  @default null
9991                  *
9992                  *  @dtopt Option
9993                  *  @name DataTable.defaults.ajax
9994                  *  @since 1.10.0
9995                  *
9996                  * @example
9997                  *   // Get JSON data from a file via Ajax.
9998                  *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
9999                  *   $('#example').dataTable( {
10000                  *     "ajax": "data.json"
10001                  *   } );
10002                  *
10003                  * @example
10004                  *   // Get JSON data from a file via Ajax, using `dataSrc` to change
10005                  *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10006                  *   $('#example').dataTable( {
10007                  *     "ajax": {
10008                  *       "url": "data.json",
10009                  *       "dataSrc": "tableData"
10010                  *     }
10011                  *   } );
10012                  *
10013                  * @example
10014                  *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
10015                  *   // from a plain array rather than an array in an object
10016                  *   $('#example').dataTable( {
10017                  *     "ajax": {
10018                  *       "url": "data.json",
10019                  *       "dataSrc": ""
10020                  *     }
10021                  *   } );
10022                  *
10023                  * @example
10024                  *   // Manipulate the data returned from the server - add a link to data
10025                  *   // (note this can, should, be done using `render` for the column - this
10026                  *   // is just a simple example of how the data can be manipulated).
10027                  *   $('#example').dataTable( {
10028                  *     "ajax": {
10029                  *       "url": "data.json",
10030                  *       "dataSrc": function ( json ) {
10031                  *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10032                  *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10033                  *         }
10034                  *         return json;
10035                  *       }
10036                  *     }
10037                  *   } );
10038                  *
10039                  * @example
10040                  *   // Add data to the request
10041                  *   $('#example').dataTable( {
10042                  *     "ajax": {
10043                  *       "url": "data.json",
10044                  *       "data": function ( d ) {
10045                  *         return {
10046                  *           "extra_search": $('#extra').val()
10047                  *         };
10048                  *       }
10049                  *     }
10050                  *   } );
10051                  *
10052                  * @example
10053                  *   // Send request as POST
10054                  *   $('#example').dataTable( {
10055                  *     "ajax": {
10056                  *       "url": "data.json",
10057                  *       "type": "POST"
10058                  *     }
10059                  *   } );
10060                  *
10061                  * @example
10062                  *   // Get the data from localStorage (could interface with a form for
10063                  *   // adding, editing and removing rows).
10064                  *   $('#example').dataTable( {
10065                  *     "ajax": function (data, callback, settings) {
10066                  *       callback(
10067                  *         JSON.parse( localStorage.getItem('dataTablesData') )
10068                  *       );
10069                  *     }
10070                  *   } );
10071                  */
10072                 "ajax": null,
10073         
10074         
10075                 /**
10076                  * This parameter allows you to readily specify the entries in the length drop
10077                  * down menu that DataTables shows when pagination is enabled. It can be
10078                  * either a 1D array of options which will be used for both the displayed
10079                  * option and the value, or a 2D array which will use the array in the first
10080                  * position as the value, and the array in the second position as the
10081                  * displayed options (useful for language strings such as 'All').
10082                  *
10083                  * Note that the `pageLength` property will be automatically set to the
10084                  * first value given in this array, unless `pageLength` is also provided.
10085                  *  @type array
10086                  *  @default [ 10, 25, 50, 100 ]
10087                  *
10088                  *  @dtopt Option
10089                  *  @name DataTable.defaults.lengthMenu
10090                  *
10091                  *  @example
10092                  *    $(document).ready( function() {
10093                  *      $('#example').dataTable( {
10094                  *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10095                  *      } );
10096                  *    } );
10097                  */
10098                 "aLengthMenu": [ 10, 25, 50, 100 ],
10099         
10100         
10101                 /**
10102                  * The `columns` option in the initialisation parameter allows you to define
10103                  * details about the way individual columns behave. For a full list of
10104                  * column options that can be set, please see
10105                  * {@link DataTable.defaults.column}. Note that if you use `columns` to
10106                  * define your columns, you must have an entry in the array for every single
10107                  * column that you have in your table (these can be null if you don't which
10108                  * to specify any options).
10109                  *  @member
10110                  *
10111                  *  @name DataTable.defaults.column
10112                  */
10113                 "aoColumns": null,
10114         
10115                 /**
10116                  * Very similar to `columns`, `columnDefs` allows you to target a specific
10117                  * column, multiple columns, or all columns, using the `targets` property of
10118                  * each object in the array. This allows great flexibility when creating
10119                  * tables, as the `columnDefs` arrays can be of any length, targeting the
10120                  * columns you specifically want. `columnDefs` may use any of the column
10121                  * options available: {@link DataTable.defaults.column}, but it _must_
10122                  * have `targets` defined in each object in the array. Values in the `targets`
10123                  * array may be:
10124                  *   <ul>
10125                  *     <li>a string - class name will be matched on the TH for the column</li>
10126                  *     <li>0 or a positive integer - column index counting from the left</li>
10127                  *     <li>a negative integer - column index counting from the right</li>
10128                  *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10129                  *   </ul>
10130                  *  @member
10131                  *
10132                  *  @name DataTable.defaults.columnDefs
10133                  */
10134                 "aoColumnDefs": null,
10135         
10136         
10137                 /**
10138                  * Basically the same as `search`, this parameter defines the individual column
10139                  * filtering state at initialisation time. The array must be of the same size
10140                  * as the number of columns, and each element be an object with the parameters
10141                  * `search` and `escapeRegex` (the latter is optional). 'null' is also
10142                  * accepted and the default will be used.
10143                  *  @type array
10144                  *  @default []
10145                  *
10146                  *  @dtopt Option
10147                  *  @name DataTable.defaults.searchCols
10148                  *
10149                  *  @example
10150                  *    $(document).ready( function() {
10151                  *      $('#example').dataTable( {
10152                  *        "searchCols": [
10153                  *          null,
10154                  *          { "search": "My filter" },
10155                  *          null,
10156                  *          { "search": "^[0-9]", "escapeRegex": false }
10157                  *        ]
10158                  *      } );
10159                  *    } )
10160                  */
10161                 "aoSearchCols": [],
10162         
10163         
10164                 /**
10165                  * An array of CSS classes that should be applied to displayed rows. This
10166                  * array may be of any length, and DataTables will apply each class
10167                  * sequentially, looping when required.
10168                  *  @type array
10169                  *  @default null <i>Will take the values determined by the `oClasses.stripe*`
10170                  *    options</i>
10171                  *
10172                  *  @dtopt Option
10173                  *  @name DataTable.defaults.stripeClasses
10174                  *
10175                  *  @example
10176                  *    $(document).ready( function() {
10177                  *      $('#example').dataTable( {
10178                  *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10179                  *      } );
10180                  *    } )
10181                  */
10182                 "asStripeClasses": null,
10183         
10184         
10185                 /**
10186                  * Enable or disable automatic column width calculation. This can be disabled
10187                  * as an optimisation (it takes some time to calculate the widths) if the
10188                  * tables widths are passed in using `columns`.
10189                  *  @type boolean
10190                  *  @default true
10191                  *
10192                  *  @dtopt Features
10193                  *  @name DataTable.defaults.autoWidth
10194                  *
10195                  *  @example
10196                  *    $(document).ready( function () {
10197                  *      $('#example').dataTable( {
10198                  *        "autoWidth": false
10199                  *      } );
10200                  *    } );
10201                  */
10202                 "bAutoWidth": true,
10203         
10204         
10205                 /**
10206                  * Deferred rendering can provide DataTables with a huge speed boost when you
10207                  * are using an Ajax or JS data source for the table. This option, when set to
10208                  * true, will cause DataTables to defer the creation of the table elements for
10209                  * each row until they are needed for a draw - saving a significant amount of
10210                  * time.
10211                  *  @type boolean
10212                  *  @default false
10213                  *
10214                  *  @dtopt Features
10215                  *  @name DataTable.defaults.deferRender
10216                  *
10217                  *  @example
10218                  *    $(document).ready( function() {
10219                  *      $('#example').dataTable( {
10220                  *        "ajax": "sources/arrays.txt",
10221                  *        "deferRender": true
10222                  *      } );
10223                  *    } );
10224                  */
10225                 "bDeferRender": false,
10226         
10227         
10228                 /**
10229                  * Replace a DataTable which matches the given selector and replace it with
10230                  * one which has the properties of the new initialisation object passed. If no
10231                  * table matches the selector, then the new DataTable will be constructed as
10232                  * per normal.
10233                  *  @type boolean
10234                  *  @default false
10235                  *
10236                  *  @dtopt Options
10237                  *  @name DataTable.defaults.destroy
10238                  *
10239                  *  @example
10240                  *    $(document).ready( function() {
10241                  *      $('#example').dataTable( {
10242                  *        "srollY": "200px",
10243                  *        "paginate": false
10244                  *      } );
10245                  *
10246                  *      // Some time later....
10247                  *      $('#example').dataTable( {
10248                  *        "filter": false,
10249                  *        "destroy": true
10250                  *      } );
10251                  *    } );
10252                  */
10253                 "bDestroy": false,
10254         
10255         
10256                 /**
10257                  * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10258                  * that it allows the end user to input multiple words (space separated) and
10259                  * will match a row containing those words, even if not in the order that was
10260                  * specified (this allow matching across multiple columns). Note that if you
10261                  * wish to use filtering in DataTables this must remain 'true' - to remove the
10262                  * default filtering input box and retain filtering abilities, please use
10263                  * {@link DataTable.defaults.dom}.
10264                  *  @type boolean
10265                  *  @default true
10266                  *
10267                  *  @dtopt Features
10268                  *  @name DataTable.defaults.searching
10269                  *
10270                  *  @example
10271                  *    $(document).ready( function () {
10272                  *      $('#example').dataTable( {
10273                  *        "searching": false
10274                  *      } );
10275                  *    } );
10276                  */
10277                 "bFilter": true,
10278         
10279         
10280                 /**
10281                  * Enable or disable the table information display. This shows information
10282                  * about the data that is currently visible on the page, including information
10283                  * about filtered data if that action is being performed.
10284                  *  @type boolean
10285                  *  @default true
10286                  *
10287                  *  @dtopt Features
10288                  *  @name DataTable.defaults.info
10289                  *
10290                  *  @example
10291                  *    $(document).ready( function () {
10292                  *      $('#example').dataTable( {
10293                  *        "info": false
10294                  *      } );
10295                  *    } );
10296                  */
10297                 "bInfo": true,
10298         
10299         
10300                 /**
10301                  * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
10302                  * slightly different and additional mark-up from what DataTables has
10303                  * traditionally used).
10304                  *  @type boolean
10305                  *  @default false
10306                  *
10307                  *  @dtopt Features
10308                  *  @name DataTable.defaults.jQueryUI
10309                  *
10310                  *  @example
10311                  *    $(document).ready( function() {
10312                  *      $('#example').dataTable( {
10313                  *        "jQueryUI": true
10314                  *      } );
10315                  *    } );
10316                  */
10317                 "bJQueryUI": false,
10318         
10319         
10320                 /**
10321                  * Allows the end user to select the size of a formatted page from a select
10322                  * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10323                  *  @type boolean
10324                  *  @default true
10325                  *
10326                  *  @dtopt Features
10327                  *  @name DataTable.defaults.lengthChange
10328                  *
10329                  *  @example
10330                  *    $(document).ready( function () {
10331                  *      $('#example').dataTable( {
10332                  *        "lengthChange": false
10333                  *      } );
10334                  *    } );
10335                  */
10336                 "bLengthChange": true,
10337         
10338         
10339                 /**
10340                  * Enable or disable pagination.
10341                  *  @type boolean
10342                  *  @default true
10343                  *
10344                  *  @dtopt Features
10345                  *  @name DataTable.defaults.paging
10346                  *
10347                  *  @example
10348                  *    $(document).ready( function () {
10349                  *      $('#example').dataTable( {
10350                  *        "paging": false
10351                  *      } );
10352                  *    } );
10353                  */
10354                 "bPaginate": true,
10355         
10356         
10357                 /**
10358                  * Enable or disable the display of a 'processing' indicator when the table is
10359                  * being processed (e.g. a sort). This is particularly useful for tables with
10360                  * large amounts of data where it can take a noticeable amount of time to sort
10361                  * the entries.
10362                  *  @type boolean
10363                  *  @default false
10364                  *
10365                  *  @dtopt Features
10366                  *  @name DataTable.defaults.processing
10367                  *
10368                  *  @example
10369                  *    $(document).ready( function () {
10370                  *      $('#example').dataTable( {
10371                  *        "processing": true
10372                  *      } );
10373                  *    } );
10374                  */
10375                 "bProcessing": false,
10376         
10377         
10378                 /**
10379                  * Retrieve the DataTables object for the given selector. Note that if the
10380                  * table has already been initialised, this parameter will cause DataTables
10381                  * to simply return the object that has already been set up - it will not take
10382                  * account of any changes you might have made to the initialisation object
10383                  * passed to DataTables (setting this parameter to true is an acknowledgement
10384                  * that you understand this). `destroy` can be used to reinitialise a table if
10385                  * you need.
10386                  *  @type boolean
10387                  *  @default false
10388                  *
10389                  *  @dtopt Options
10390                  *  @name DataTable.defaults.retrieve
10391                  *
10392                  *  @example
10393                  *    $(document).ready( function() {
10394                  *      initTable();
10395                  *      tableActions();
10396                  *    } );
10397                  *
10398                  *    function initTable ()
10399                  *    {
10400                  *      return $('#example').dataTable( {
10401                  *        "scrollY": "200px",
10402                  *        "paginate": false,
10403                  *        "retrieve": true
10404                  *      } );
10405                  *    }
10406                  *
10407                  *    function tableActions ()
10408                  *    {
10409                  *      var table = initTable();
10410                  *      // perform API operations with oTable
10411                  *    }
10412                  */
10413                 "bRetrieve": false,
10414         
10415         
10416                 /**
10417                  * When vertical (y) scrolling is enabled, DataTables will force the height of
10418                  * the table's viewport to the given height at all times (useful for layout).
10419                  * However, this can look odd when filtering data down to a small data set,
10420                  * and the footer is left "floating" further down. This parameter (when
10421                  * enabled) will cause DataTables to collapse the table's viewport down when
10422                  * the result set will fit within the given Y height.
10423                  *  @type boolean
10424                  *  @default false
10425                  *
10426                  *  @dtopt Options
10427                  *  @name DataTable.defaults.scrollCollapse
10428                  *
10429                  *  @example
10430                  *    $(document).ready( function() {
10431                  *      $('#example').dataTable( {
10432                  *        "scrollY": "200",
10433                  *        "scrollCollapse": true
10434                  *      } );
10435                  *    } );
10436                  */
10437                 "bScrollCollapse": false,
10438         
10439         
10440                 /**
10441                  * Configure DataTables to use server-side processing. Note that the
10442                  * `ajax` parameter must also be given in order to give DataTables a
10443                  * source to obtain the required data for each draw.
10444                  *  @type boolean
10445                  *  @default false
10446                  *
10447                  *  @dtopt Features
10448                  *  @dtopt Server-side
10449                  *  @name DataTable.defaults.serverSide
10450                  *
10451                  *  @example
10452                  *    $(document).ready( function () {
10453                  *      $('#example').dataTable( {
10454                  *        "serverSide": true,
10455                  *        "ajax": "xhr.php"
10456                  *      } );
10457                  *    } );
10458                  */
10459                 "bServerSide": false,
10460         
10461         
10462                 /**
10463                  * Enable or disable sorting of columns. Sorting of individual columns can be
10464                  * disabled by the `sortable` option for each column.
10465                  *  @type boolean
10466                  *  @default true
10467                  *
10468                  *  @dtopt Features
10469                  *  @name DataTable.defaults.ordering
10470                  *
10471                  *  @example
10472                  *    $(document).ready( function () {
10473                  *      $('#example').dataTable( {
10474                  *        "ordering": false
10475                  *      } );
10476                  *    } );
10477                  */
10478                 "bSort": true,
10479         
10480         
10481                 /**
10482                  * Enable or display DataTables' ability to sort multiple columns at the
10483                  * same time (activated by shift-click by the user).
10484                  *  @type boolean
10485                  *  @default true
10486                  *
10487                  *  @dtopt Options
10488                  *  @name DataTable.defaults.orderMulti
10489                  *
10490                  *  @example
10491                  *    // Disable multiple column sorting ability
10492                  *    $(document).ready( function () {
10493                  *      $('#example').dataTable( {
10494                  *        "orderMulti": false
10495                  *      } );
10496                  *    } );
10497                  */
10498                 "bSortMulti": true,
10499         
10500         
10501                 /**
10502                  * Allows control over whether DataTables should use the top (true) unique
10503                  * cell that is found for a single column, or the bottom (false - default).
10504                  * This is useful when using complex headers.
10505                  *  @type boolean
10506                  *  @default false
10507                  *
10508                  *  @dtopt Options
10509                  *  @name DataTable.defaults.orderCellsTop
10510                  *
10511                  *  @example
10512                  *    $(document).ready( function() {
10513                  *      $('#example').dataTable( {
10514                  *        "orderCellsTop": true
10515                  *      } );
10516                  *    } );
10517                  */
10518                 "bSortCellsTop": false,
10519         
10520         
10521                 /**
10522                  * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10523                  * `sorting\_3` to the columns which are currently being sorted on. This is
10524                  * presented as a feature switch as it can increase processing time (while
10525                  * classes are removed and added) so for large data sets you might want to
10526                  * turn this off.
10527                  *  @type boolean
10528                  *  @default true
10529                  *
10530                  *  @dtopt Features
10531                  *  @name DataTable.defaults.orderClasses
10532                  *
10533                  *  @example
10534                  *    $(document).ready( function () {
10535                  *      $('#example').dataTable( {
10536                  *        "orderClasses": false
10537                  *      } );
10538                  *    } );
10539                  */
10540                 "bSortClasses": true,
10541         
10542         
10543                 /**
10544                  * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10545                  * used to save table display information such as pagination information,
10546                  * display length, filtering and sorting. As such when the end user reloads
10547                  * the page the display display will match what thy had previously set up.
10548                  *
10549                  * Due to the use of `localStorage` the default state saving is not supported
10550                  * in IE6 or 7. If state saving is required in those browsers, use
10551                  * `stateSaveCallback` to provide a storage solution such as cookies.
10552                  *  @type boolean
10553                  *  @default false
10554                  *
10555                  *  @dtopt Features
10556                  *  @name DataTable.defaults.stateSave
10557                  *
10558                  *  @example
10559                  *    $(document).ready( function () {
10560                  *      $('#example').dataTable( {
10561                  *        "stateSave": true
10562                  *      } );
10563                  *    } );
10564                  */
10565                 "bStateSave": false,
10566         
10567         
10568                 /**
10569                  * This function is called when a TR element is created (and all TD child
10570                  * elements have been inserted), or registered if using a DOM source, allowing
10571                  * manipulation of the TR element (adding classes etc).
10572                  *  @type function
10573                  *  @param {node} row "TR" element for the current row
10574                  *  @param {array} data Raw data array for this row
10575                  *  @param {int} dataIndex The index of this row in the internal aoData array
10576                  *
10577                  *  @dtopt Callbacks
10578                  *  @name DataTable.defaults.createdRow
10579                  *
10580                  *  @example
10581                  *    $(document).ready( function() {
10582                  *      $('#example').dataTable( {
10583                  *        "createdRow": function( row, data, dataIndex ) {
10584                  *          // Bold the grade for all 'A' grade browsers
10585                  *          if ( data[4] == "A" )
10586                  *          {
10587                  *            $('td:eq(4)', row).html( '<b>A</b>' );
10588                  *          }
10589                  *        }
10590                  *      } );
10591                  *    } );
10592                  */
10593                 "fnCreatedRow": null,
10594         
10595         
10596                 /**
10597                  * This function is called on every 'draw' event, and allows you to
10598                  * dynamically modify any aspect you want about the created DOM.
10599                  *  @type function
10600                  *  @param {object} settings DataTables settings object
10601                  *
10602                  *  @dtopt Callbacks
10603                  *  @name DataTable.defaults.drawCallback
10604                  *
10605                  *  @example
10606                  *    $(document).ready( function() {
10607                  *      $('#example').dataTable( {
10608                  *        "drawCallback": function( settings ) {
10609                  *          alert( 'DataTables has redrawn the table' );
10610                  *        }
10611                  *      } );
10612                  *    } );
10613                  */
10614                 "fnDrawCallback": null,
10615         
10616         
10617                 /**
10618                  * Identical to fnHeaderCallback() but for the table footer this function
10619                  * allows you to modify the table footer on every 'draw' event.
10620                  *  @type function
10621                  *  @param {node} foot "TR" element for the footer
10622                  *  @param {array} data Full table data (as derived from the original HTML)
10623                  *  @param {int} start Index for the current display starting point in the
10624                  *    display array
10625                  *  @param {int} end Index for the current display ending point in the
10626                  *    display array
10627                  *  @param {array int} display Index array to translate the visual position
10628                  *    to the full data array
10629                  *
10630                  *  @dtopt Callbacks
10631                  *  @name DataTable.defaults.footerCallback
10632                  *
10633                  *  @example
10634                  *    $(document).ready( function() {
10635                  *      $('#example').dataTable( {
10636                  *        "footerCallback": function( tfoot, data, start, end, display ) {
10637                  *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10638                  *        }
10639                  *      } );
10640                  *    } )
10641                  */
10642                 "fnFooterCallback": null,
10643         
10644         
10645                 /**
10646                  * When rendering large numbers in the information element for the table
10647                  * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10648                  * to have a comma separator for the 'thousands' units (e.g. 1 million is
10649                  * rendered as "1,000,000") to help readability for the end user. This
10650                  * function will override the default method DataTables uses.
10651                  *  @type function
10652                  *  @member
10653                  *  @param {int} toFormat number to be formatted
10654                  *  @returns {string} formatted string for DataTables to show the number
10655                  *
10656                  *  @dtopt Callbacks
10657                  *  @name DataTable.defaults.formatNumber
10658                  *
10659                  *  @example
10660                  *    // Format a number using a single quote for the separator (note that
10661                  *    // this can also be done with the language.thousands option)
10662                  *    $(document).ready( function() {
10663                  *      $('#example').dataTable( {
10664                  *        "formatNumber": function ( toFormat ) {
10665                  *          return toFormat.toString().replace(
10666                  *            /\B(?=(\d{3})+(?!\d))/g, "'"
10667                  *          );
10668                  *        };
10669                  *      } );
10670                  *    } );
10671                  */
10672                 "fnFormatNumber": function ( toFormat ) {
10673                         return toFormat.toString().replace(
10674                                 /\B(?=(\d{3})+(?!\d))/g,
10675                                 this.oLanguage.sThousands
10676                         );
10677                 },
10678         
10679         
10680                 /**
10681                  * This function is called on every 'draw' event, and allows you to
10682                  * dynamically modify the header row. This can be used to calculate and
10683                  * display useful information about the table.
10684                  *  @type function
10685                  *  @param {node} head "TR" element for the header
10686                  *  @param {array} data Full table data (as derived from the original HTML)
10687                  *  @param {int} start Index for the current display starting point in the
10688                  *    display array
10689                  *  @param {int} end Index for the current display ending point in the
10690                  *    display array
10691                  *  @param {array int} display Index array to translate the visual position
10692                  *    to the full data array
10693                  *
10694                  *  @dtopt Callbacks
10695                  *  @name DataTable.defaults.headerCallback
10696                  *
10697                  *  @example
10698                  *    $(document).ready( function() {
10699                  *      $('#example').dataTable( {
10700                  *        "fheaderCallback": function( head, data, start, end, display ) {
10701                  *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10702                  *        }
10703                  *      } );
10704                  *    } )
10705                  */
10706                 "fnHeaderCallback": null,
10707         
10708         
10709                 /**
10710                  * The information element can be used to convey information about the current
10711                  * state of the table. Although the internationalisation options presented by
10712                  * DataTables are quite capable of dealing with most customisations, there may
10713                  * be times where you wish to customise the string further. This callback
10714                  * allows you to do exactly that.
10715                  *  @type function
10716                  *  @param {object} oSettings DataTables settings object
10717                  *  @param {int} start Starting position in data for the draw
10718                  *  @param {int} end End position in data for the draw
10719                  *  @param {int} max Total number of rows in the table (regardless of
10720                  *    filtering)
10721                  *  @param {int} total Total number of rows in the data set, after filtering
10722                  *  @param {string} pre The string that DataTables has formatted using it's
10723                  *    own rules
10724                  *  @returns {string} The string to be displayed in the information element.
10725                  *
10726                  *  @dtopt Callbacks
10727                  *  @name DataTable.defaults.infoCallback
10728                  *
10729                  *  @example
10730                  *    $('#example').dataTable( {
10731                  *      "infoCallback": function( settings, start, end, max, total, pre ) {
10732                  *        return start +" to "+ end;
10733                  *      }
10734                  *    } );
10735                  */
10736                 "fnInfoCallback": null,
10737         
10738         
10739                 /**
10740                  * Called when the table has been initialised. Normally DataTables will
10741                  * initialise sequentially and there will be no need for this function,
10742                  * however, this does not hold true when using external language information
10743                  * since that is obtained using an async XHR call.
10744                  *  @type function
10745                  *  @param {object} settings DataTables settings object
10746                  *  @param {object} json The JSON object request from the server - only
10747                  *    present if client-side Ajax sourced data is used
10748                  *
10749                  *  @dtopt Callbacks
10750                  *  @name DataTable.defaults.initComplete
10751                  *
10752                  *  @example
10753                  *    $(document).ready( function() {
10754                  *      $('#example').dataTable( {
10755                  *        "initComplete": function(settings, json) {
10756                  *          alert( 'DataTables has finished its initialisation.' );
10757                  *        }
10758                  *      } );
10759                  *    } )
10760                  */
10761                 "fnInitComplete": null,
10762         
10763         
10764                 /**
10765                  * Called at the very start of each table draw and can be used to cancel the
10766                  * draw by returning false, any other return (including undefined) results in
10767                  * the full draw occurring).
10768                  *  @type function
10769                  *  @param {object} settings DataTables settings object
10770                  *  @returns {boolean} False will cancel the draw, anything else (including no
10771                  *    return) will allow it to complete.
10772                  *
10773                  *  @dtopt Callbacks
10774                  *  @name DataTable.defaults.preDrawCallback
10775                  *
10776                  *  @example
10777                  *    $(document).ready( function() {
10778                  *      $('#example').dataTable( {
10779                  *        "preDrawCallback": function( settings ) {
10780                  *          if ( $('#test').val() == 1 ) {
10781                  *            return false;
10782                  *          }
10783                  *        }
10784                  *      } );
10785                  *    } );
10786                  */
10787                 "fnPreDrawCallback": null,
10788         
10789         
10790                 /**
10791                  * This function allows you to 'post process' each row after it have been
10792                  * generated for each table draw, but before it is rendered on screen. This
10793                  * function might be used for setting the row class name etc.
10794                  *  @type function
10795                  *  @param {node} row "TR" element for the current row
10796                  *  @param {array} data Raw data array for this row
10797                  *  @param {int} displayIndex The display index for the current table draw
10798                  *  @param {int} displayIndexFull The index of the data in the full list of
10799                  *    rows (after filtering)
10800                  *
10801                  *  @dtopt Callbacks
10802                  *  @name DataTable.defaults.rowCallback
10803                  *
10804                  *  @example
10805                  *    $(document).ready( function() {
10806                  *      $('#example').dataTable( {
10807                  *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10808                  *          // Bold the grade for all 'A' grade browsers
10809                  *          if ( data[4] == "A" ) {
10810                  *            $('td:eq(4)', row).html( '<b>A</b>' );
10811                  *          }
10812                  *        }
10813                  *      } );
10814                  *    } );
10815                  */
10816                 "fnRowCallback": null,
10817         
10818         
10819                 /**
10820                  * __Deprecated__ The functionality provided by this parameter has now been
10821                  * superseded by that provided through `ajax`, which should be used instead.
10822                  *
10823                  * This parameter allows you to override the default function which obtains
10824                  * the data from the server so something more suitable for your application.
10825                  * For example you could use POST data, or pull information from a Gears or
10826                  * AIR database.
10827                  *  @type function
10828                  *  @member
10829                  *  @param {string} source HTTP source to obtain the data from (`ajax`)
10830                  *  @param {array} data A key/value pair object containing the data to send
10831                  *    to the server
10832                  *  @param {function} callback to be called on completion of the data get
10833                  *    process that will draw the data on the page.
10834                  *  @param {object} settings DataTables settings object
10835                  *
10836                  *  @dtopt Callbacks
10837                  *  @dtopt Server-side
10838                  *  @name DataTable.defaults.serverData
10839                  *
10840                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
10841                  */
10842                 "fnServerData": null,
10843         
10844         
10845                 /**
10846                  * __Deprecated__ The functionality provided by this parameter has now been
10847                  * superseded by that provided through `ajax`, which should be used instead.
10848                  *
10849                  *  It is often useful to send extra data to the server when making an Ajax
10850                  * request - for example custom filtering information, and this callback
10851                  * function makes it trivial to send extra information to the server. The
10852                  * passed in parameter is the data set that has been constructed by
10853                  * DataTables, and you can add to this or modify it as you require.
10854                  *  @type function
10855                  *  @param {array} data Data array (array of objects which are name/value
10856                  *    pairs) that has been constructed by DataTables and will be sent to the
10857                  *    server. In the case of Ajax sourced data with server-side processing
10858                  *    this will be an empty array, for server-side processing there will be a
10859                  *    significant number of parameters!
10860                  *  @returns {undefined} Ensure that you modify the data array passed in,
10861                  *    as this is passed by reference.
10862                  *
10863                  *  @dtopt Callbacks
10864                  *  @dtopt Server-side
10865                  *  @name DataTable.defaults.serverParams
10866                  *
10867                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
10868                  */
10869                 "fnServerParams": null,
10870         
10871         
10872                 /**
10873                  * Load the table state. With this function you can define from where, and how, the
10874                  * state of a table is loaded. By default DataTables will load from `localStorage`
10875                  * but you might wish to use a server-side database or cookies.
10876                  *  @type function
10877                  *  @member
10878                  *  @param {object} settings DataTables settings object
10879                  *  @return {object} The DataTables state object to be loaded
10880                  *
10881                  *  @dtopt Callbacks
10882                  *  @name DataTable.defaults.stateLoadCallback
10883                  *
10884                  *  @example
10885                  *    $(document).ready( function() {
10886                  *      $('#example').dataTable( {
10887                  *        "stateSave": true,
10888                  *        "stateLoadCallback": function (settings) {
10889                  *          var o;
10890                  *
10891                  *          // Send an Ajax request to the server to get the data. Note that
10892                  *          // this is a synchronous request.
10893                  *          $.ajax( {
10894                  *            "url": "/state_load",
10895                  *            "async": false,
10896                  *            "dataType": "json",
10897                  *            "success": function (json) {
10898                  *              o = json;
10899                  *            }
10900                  *          } );
10901                  *
10902                  *          return o;
10903                  *        }
10904                  *      } );
10905                  *    } );
10906                  */
10907                 "fnStateLoadCallback": function ( settings ) {
10908                         try {
10909                                 return JSON.parse(
10910                                         (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
10911                                                 'DataTables_'+settings.sInstance+'_'+location.pathname
10912                                         )
10913                                 );
10914                         } catch (e) {}
10915                 },
10916         
10917         
10918                 /**
10919                  * Callback which allows modification of the saved state prior to loading that state.
10920                  * This callback is called when the table is loading state from the stored data, but
10921                  * prior to the settings object being modified by the saved state. Note that for
10922                  * plug-in authors, you should use the `stateLoadParams` event to load parameters for
10923                  * a plug-in.
10924                  *  @type function
10925                  *  @param {object} settings DataTables settings object
10926                  *  @param {object} data The state object that is to be loaded
10927                  *
10928                  *  @dtopt Callbacks
10929                  *  @name DataTable.defaults.stateLoadParams
10930                  *
10931                  *  @example
10932                  *    // Remove a saved filter, so filtering is never loaded
10933                  *    $(document).ready( function() {
10934                  *      $('#example').dataTable( {
10935                  *        "stateSave": true,
10936                  *        "stateLoadParams": function (settings, data) {
10937                  *          data.oSearch.sSearch = "";
10938                  *        }
10939                  *      } );
10940                  *    } );
10941                  *
10942                  *  @example
10943                  *    // Disallow state loading by returning false
10944                  *    $(document).ready( function() {
10945                  *      $('#example').dataTable( {
10946                  *        "stateSave": true,
10947                  *        "stateLoadParams": function (settings, data) {
10948                  *          return false;
10949                  *        }
10950                  *      } );
10951                  *    } );
10952                  */
10953                 "fnStateLoadParams": null,
10954         
10955         
10956                 /**
10957                  * Callback that is called when the state has been loaded from the state saving method
10958                  * and the DataTables settings object has been modified as a result of the loaded state.
10959                  *  @type function
10960                  *  @param {object} settings DataTables settings object
10961                  *  @param {object} data The state object that was loaded
10962                  *
10963                  *  @dtopt Callbacks
10964                  *  @name DataTable.defaults.stateLoaded
10965                  *
10966                  *  @example
10967                  *    // Show an alert with the filtering value that was saved
10968                  *    $(document).ready( function() {
10969                  *      $('#example').dataTable( {
10970                  *        "stateSave": true,
10971                  *        "stateLoaded": function (settings, data) {
10972                  *          alert( 'Saved filter was: '+data.oSearch.sSearch );
10973                  *        }
10974                  *      } );
10975                  *    } );
10976                  */
10977                 "fnStateLoaded": null,
10978         
10979         
10980                 /**
10981                  * Save the table state. This function allows you to define where and how the state
10982                  * information for the table is stored By default DataTables will use `localStorage`
10983                  * but you might wish to use a server-side database or cookies.
10984                  *  @type function
10985                  *  @member
10986                  *  @param {object} settings DataTables settings object
10987                  *  @param {object} data The state object to be saved
10988                  *
10989                  *  @dtopt Callbacks
10990                  *  @name DataTable.defaults.stateSaveCallback
10991                  *
10992                  *  @example
10993                  *    $(document).ready( function() {
10994                  *      $('#example').dataTable( {
10995                  *        "stateSave": true,
10996                  *        "stateSaveCallback": function (settings, data) {
10997                  *          // Send an Ajax request to the server with the state object
10998                  *          $.ajax( {
10999                  *            "url": "/state_save",
11000                  *            "data": data,
11001                  *            "dataType": "json",
11002                  *            "method": "POST"
11003                  *            "success": function () {}
11004                  *          } );
11005                  *        }
11006                  *      } );
11007                  *    } );
11008                  */
11009                 "fnStateSaveCallback": function ( settings, data ) {
11010                         try {
11011                                 (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
11012                                         'DataTables_'+settings.sInstance+'_'+location.pathname,
11013                                         JSON.stringify( data )
11014                                 );
11015                         } catch (e) {}
11016                 },
11017         
11018         
11019                 /**
11020                  * Callback which allows modification of the state to be saved. Called when the table
11021                  * has changed state a new state save is required. This method allows modification of
11022                  * the state saving object prior to actually doing the save, including addition or
11023                  * other state properties or modification. Note that for plug-in authors, you should
11024                  * use the `stateSaveParams` event to save parameters for a plug-in.
11025                  *  @type function
11026                  *  @param {object} settings DataTables settings object
11027                  *  @param {object} data The state object to be saved
11028                  *
11029                  *  @dtopt Callbacks
11030                  *  @name DataTable.defaults.stateSaveParams
11031                  *
11032                  *  @example
11033                  *    // Remove a saved filter, so filtering is never saved
11034                  *    $(document).ready( function() {
11035                  *      $('#example').dataTable( {
11036                  *        "stateSave": true,
11037                  *        "stateSaveParams": function (settings, data) {
11038                  *          data.oSearch.sSearch = "";
11039                  *        }
11040                  *      } );
11041                  *    } );
11042                  */
11043                 "fnStateSaveParams": null,
11044         
11045         
11046                 /**
11047                  * Duration for which the saved state information is considered valid. After this period
11048                  * has elapsed the state will be returned to the default.
11049                  * Value is given in seconds.
11050                  *  @type int
11051                  *  @default 7200 <i>(2 hours)</i>
11052                  *
11053                  *  @dtopt Options
11054                  *  @name DataTable.defaults.stateDuration
11055                  *
11056                  *  @example
11057                  *    $(document).ready( function() {
11058                  *      $('#example').dataTable( {
11059                  *        "stateDuration": 60*60*24; // 1 day
11060                  *      } );
11061                  *    } )
11062                  */
11063                 "iStateDuration": 7200,
11064         
11065         
11066                 /**
11067                  * When enabled DataTables will not make a request to the server for the first
11068                  * page draw - rather it will use the data already on the page (no sorting etc
11069                  * will be applied to it), thus saving on an XHR at load time. `deferLoading`
11070                  * is used to indicate that deferred loading is required, but it is also used
11071                  * to tell DataTables how many records there are in the full table (allowing
11072                  * the information element and pagination to be displayed correctly). In the case
11073                  * where a filtering is applied to the table on initial load, this can be
11074                  * indicated by giving the parameter as an array, where the first element is
11075                  * the number of records available after filtering and the second element is the
11076                  * number of records without filtering (allowing the table information element
11077                  * to be shown correctly).
11078                  *  @type int | array
11079                  *  @default null
11080                  *
11081                  *  @dtopt Options
11082                  *  @name DataTable.defaults.deferLoading
11083                  *
11084                  *  @example
11085                  *    // 57 records available in the table, no filtering applied
11086                  *    $(document).ready( function() {
11087                  *      $('#example').dataTable( {
11088                  *        "serverSide": true,
11089                  *        "ajax": "scripts/server_processing.php",
11090                  *        "deferLoading": 57
11091                  *      } );
11092                  *    } );
11093                  *
11094                  *  @example
11095                  *    // 57 records after filtering, 100 without filtering (an initial filter applied)
11096                  *    $(document).ready( function() {
11097                  *      $('#example').dataTable( {
11098                  *        "serverSide": true,
11099                  *        "ajax": "scripts/server_processing.php",
11100                  *        "deferLoading": [ 57, 100 ],
11101                  *        "search": {
11102                  *          "search": "my_filter"
11103                  *        }
11104                  *      } );
11105                  *    } );
11106                  */
11107                 "iDeferLoading": null,
11108         
11109         
11110                 /**
11111                  * Number of rows to display on a single page when using pagination. If
11112                  * feature enabled (`lengthChange`) then the end user will be able to override
11113                  * this to a custom setting using a pop-up menu.
11114                  *  @type int
11115                  *  @default 10
11116                  *
11117                  *  @dtopt Options
11118                  *  @name DataTable.defaults.pageLength
11119                  *
11120                  *  @example
11121                  *    $(document).ready( function() {
11122                  *      $('#example').dataTable( {
11123                  *        "pageLength": 50
11124                  *      } );
11125                  *    } )
11126                  */
11127                 "iDisplayLength": 10,
11128         
11129         
11130                 /**
11131                  * Define the starting point for data display when using DataTables with
11132                  * pagination. Note that this parameter is the number of records, rather than
11133                  * the page number, so if you have 10 records per page and want to start on
11134                  * the third page, it should be "20".
11135                  *  @type int
11136                  *  @default 0
11137                  *
11138                  *  @dtopt Options
11139                  *  @name DataTable.defaults.displayStart
11140                  *
11141                  *  @example
11142                  *    $(document).ready( function() {
11143                  *      $('#example').dataTable( {
11144                  *        "displayStart": 20
11145                  *      } );
11146                  *    } )
11147                  */
11148                 "iDisplayStart": 0,
11149         
11150         
11151                 /**
11152                  * By default DataTables allows keyboard navigation of the table (sorting, paging,
11153                  * and filtering) by adding a `tabindex` attribute to the required elements. This
11154                  * allows you to tab through the controls and press the enter key to activate them.
11155                  * The tabindex is default 0, meaning that the tab follows the flow of the document.
11156                  * You can overrule this using this parameter if you wish. Use a value of -1 to
11157                  * disable built-in keyboard navigation.
11158                  *  @type int
11159                  *  @default 0
11160                  *
11161                  *  @dtopt Options
11162                  *  @name DataTable.defaults.tabIndex
11163                  *
11164                  *  @example
11165                  *    $(document).ready( function() {
11166                  *      $('#example').dataTable( {
11167                  *        "tabIndex": 1
11168                  *      } );
11169                  *    } );
11170                  */
11171                 "iTabIndex": 0,
11172         
11173         
11174                 /**
11175                  * Classes that DataTables assigns to the various components and features
11176                  * that it adds to the HTML table. This allows classes to be configured
11177                  * during initialisation in addition to through the static
11178                  * {@link DataTable.ext.oStdClasses} object).
11179                  *  @namespace
11180                  *  @name DataTable.defaults.classes
11181                  */
11182                 "oClasses": {},
11183         
11184         
11185                 /**
11186                  * All strings that DataTables uses in the user interface that it creates
11187                  * are defined in this object, allowing you to modified them individually or
11188                  * completely replace them all as required.
11189                  *  @namespace
11190                  *  @name DataTable.defaults.language
11191                  */
11192                 "oLanguage": {
11193                         /**
11194                          * Strings that are used for WAI-ARIA labels and controls only (these are not
11195                          * actually visible on the page, but will be read by screenreaders, and thus
11196                          * must be internationalised as well).
11197                          *  @namespace
11198                          *  @name DataTable.defaults.language.aria
11199                          */
11200                         "oAria": {
11201                                 /**
11202                                  * ARIA label that is added to the table headers when the column may be
11203                                  * sorted ascending by activing the column (click or return when focused).
11204                                  * Note that the column header is prefixed to this string.
11205                                  *  @type string
11206                                  *  @default : activate to sort column ascending
11207                                  *
11208                                  *  @dtopt Language
11209                                  *  @name DataTable.defaults.language.aria.sortAscending
11210                                  *
11211                                  *  @example
11212                                  *    $(document).ready( function() {
11213                                  *      $('#example').dataTable( {
11214                                  *        "language": {
11215                                  *          "aria": {
11216                                  *            "sortAscending": " - click/return to sort ascending"
11217                                  *          }
11218                                  *        }
11219                                  *      } );
11220                                  *    } );
11221                                  */
11222                                 "sSortAscending": ": activate to sort column ascending",
11223         
11224                                 /**
11225                                  * ARIA label that is added to the table headers when the column may be
11226                                  * sorted descending by activing the column (click or return when focused).
11227                                  * Note that the column header is prefixed to this string.
11228                                  *  @type string
11229                                  *  @default : activate to sort column ascending
11230                                  *
11231                                  *  @dtopt Language
11232                                  *  @name DataTable.defaults.language.aria.sortDescending
11233                                  *
11234                                  *  @example
11235                                  *    $(document).ready( function() {
11236                                  *      $('#example').dataTable( {
11237                                  *        "language": {
11238                                  *          "aria": {
11239                                  *            "sortDescending": " - click/return to sort descending"
11240                                  *          }
11241                                  *        }
11242                                  *      } );
11243                                  *    } );
11244                                  */
11245                                 "sSortDescending": ": activate to sort column descending"
11246                         },
11247         
11248                         /**
11249                          * Pagination string used by DataTables for the built-in pagination
11250                          * control types.
11251                          *  @namespace
11252                          *  @name DataTable.defaults.language.paginate
11253                          */
11254                         "oPaginate": {
11255                                 /**
11256                                  * Text to use when using the 'full_numbers' type of pagination for the
11257                                  * button to take the user to the first page.
11258                                  *  @type string
11259                                  *  @default First
11260                                  *
11261                                  *  @dtopt Language
11262                                  *  @name DataTable.defaults.language.paginate.first
11263                                  *
11264                                  *  @example
11265                                  *    $(document).ready( function() {
11266                                  *      $('#example').dataTable( {
11267                                  *        "language": {
11268                                  *          "paginate": {
11269                                  *            "first": "First page"
11270                                  *          }
11271                                  *        }
11272                                  *      } );
11273                                  *    } );
11274                                  */
11275                                 "sFirst": "First",
11276         
11277         
11278                                 /**
11279                                  * Text to use when using the 'full_numbers' type of pagination for the
11280                                  * button to take the user to the last page.
11281                                  *  @type string
11282                                  *  @default Last
11283                                  *
11284                                  *  @dtopt Language
11285                                  *  @name DataTable.defaults.language.paginate.last
11286                                  *
11287                                  *  @example
11288                                  *    $(document).ready( function() {
11289                                  *      $('#example').dataTable( {
11290                                  *        "language": {
11291                                  *          "paginate": {
11292                                  *            "last": "Last page"
11293                                  *          }
11294                                  *        }
11295                                  *      } );
11296                                  *    } );
11297                                  */
11298                                 "sLast": "Last",
11299         
11300         
11301                                 /**
11302                                  * Text to use for the 'next' pagination button (to take the user to the
11303                                  * next page).
11304                                  *  @type string
11305                                  *  @default Next
11306                                  *
11307                                  *  @dtopt Language
11308                                  *  @name DataTable.defaults.language.paginate.next
11309                                  *
11310                                  *  @example
11311                                  *    $(document).ready( function() {
11312                                  *      $('#example').dataTable( {
11313                                  *        "language": {
11314                                  *          "paginate": {
11315                                  *            "next": "Next page"
11316                                  *          }
11317                                  *        }
11318                                  *      } );
11319                                  *    } );
11320                                  */
11321                                 "sNext": "Next",
11322         
11323         
11324                                 /**
11325                                  * Text to use for the 'previous' pagination button (to take the user to
11326                                  * the previous page).
11327                                  *  @type string
11328                                  *  @default Previous
11329                                  *
11330                                  *  @dtopt Language
11331                                  *  @name DataTable.defaults.language.paginate.previous
11332                                  *
11333                                  *  @example
11334                                  *    $(document).ready( function() {
11335                                  *      $('#example').dataTable( {
11336                                  *        "language": {
11337                                  *          "paginate": {
11338                                  *            "previous": "Previous page"
11339                                  *          }
11340                                  *        }
11341                                  *      } );
11342                                  *    } );
11343                                  */
11344                                 "sPrevious": "Previous"
11345                         },
11346         
11347                         /**
11348                          * This string is shown in preference to `zeroRecords` when the table is
11349                          * empty of data (regardless of filtering). Note that this is an optional
11350                          * parameter - if it is not given, the value of `zeroRecords` will be used
11351                          * instead (either the default or given value).
11352                          *  @type string
11353                          *  @default No data available in table
11354                          *
11355                          *  @dtopt Language
11356                          *  @name DataTable.defaults.language.emptyTable
11357                          *
11358                          *  @example
11359                          *    $(document).ready( function() {
11360                          *      $('#example').dataTable( {
11361                          *        "language": {
11362                          *          "emptyTable": "No data available in table"
11363                          *        }
11364                          *      } );
11365                          *    } );
11366                          */
11367                         "sEmptyTable": "No data available in table",
11368         
11369         
11370                         /**
11371                          * This string gives information to the end user about the information
11372                          * that is current on display on the page. The following tokens can be
11373                          * used in the string and will be dynamically replaced as the table
11374                          * display updates. This tokens can be placed anywhere in the string, or
11375                          * removed as needed by the language requires:
11376                          *
11377                          * * `\_START\_` - Display index of the first record on the current page
11378                          * * `\_END\_` - Display index of the last record on the current page
11379                          * * `\_TOTAL\_` - Number of records in the table after filtering
11380                          * * `\_MAX\_` - Number of records in the table without filtering
11381                          * * `\_PAGE\_` - Current page number
11382                          * * `\_PAGES\_` - Total number of pages of data in the table
11383                          *
11384                          *  @type string
11385                          *  @default Showing _START_ to _END_ of _TOTAL_ entries
11386                          *
11387                          *  @dtopt Language
11388                          *  @name DataTable.defaults.language.info
11389                          *
11390                          *  @example
11391                          *    $(document).ready( function() {
11392                          *      $('#example').dataTable( {
11393                          *        "language": {
11394                          *          "info": "Showing page _PAGE_ of _PAGES_"
11395                          *        }
11396                          *      } );
11397                          *    } );
11398                          */
11399                         "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11400         
11401         
11402                         /**
11403                          * Display information string for when the table is empty. Typically the
11404                          * format of this string should match `info`.
11405                          *  @type string
11406                          *  @default Showing 0 to 0 of 0 entries
11407                          *
11408                          *  @dtopt Language
11409                          *  @name DataTable.defaults.language.infoEmpty
11410                          *
11411                          *  @example
11412                          *    $(document).ready( function() {
11413                          *      $('#example').dataTable( {
11414                          *        "language": {
11415                          *          "infoEmpty": "No entries to show"
11416                          *        }
11417                          *      } );
11418                          *    } );
11419                          */
11420                         "sInfoEmpty": "Showing 0 to 0 of 0 entries",
11421         
11422         
11423                         /**
11424                          * When a user filters the information in a table, this string is appended
11425                          * to the information (`info`) to give an idea of how strong the filtering
11426                          * is. The variable _MAX_ is dynamically updated.
11427                          *  @type string
11428                          *  @default (filtered from _MAX_ total entries)
11429                          *
11430                          *  @dtopt Language
11431                          *  @name DataTable.defaults.language.infoFiltered
11432                          *
11433                          *  @example
11434                          *    $(document).ready( function() {
11435                          *      $('#example').dataTable( {
11436                          *        "language": {
11437                          *          "infoFiltered": " - filtering from _MAX_ records"
11438                          *        }
11439                          *      } );
11440                          *    } );
11441                          */
11442                         "sInfoFiltered": "(filtered from _MAX_ total entries)",
11443         
11444         
11445                         /**
11446                          * If can be useful to append extra information to the info string at times,
11447                          * and this variable does exactly that. This information will be appended to
11448                          * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11449                          * being used) at all times.
11450                          *  @type string
11451                          *  @default <i>Empty string</i>
11452                          *
11453                          *  @dtopt Language
11454                          *  @name DataTable.defaults.language.infoPostFix
11455                          *
11456                          *  @example
11457                          *    $(document).ready( function() {
11458                          *      $('#example').dataTable( {
11459                          *        "language": {
11460                          *          "infoPostFix": "All records shown are derived from real information."
11461                          *        }
11462                          *      } );
11463                          *    } );
11464                          */
11465                         "sInfoPostFix": "",
11466         
11467         
11468                         /**
11469                          * This decimal place operator is a little different from the other
11470                          * language options since DataTables doesn't output floating point
11471                          * numbers, so it won't ever use this for display of a number. Rather,
11472                          * what this parameter does is modify the sort methods of the table so
11473                          * that numbers which are in a format which has a character other than
11474                          * a period (`.`) as a decimal place will be sorted numerically.
11475                          *
11476                          * Note that numbers with different decimal places cannot be shown in
11477                          * the same table and still be sortable, the table must be consistent.
11478                          * However, multiple different tables on the page can use different
11479                          * decimal place characters.
11480                          *  @type string
11481                          *  @default 
11482                          *
11483                          *  @dtopt Language
11484                          *  @name DataTable.defaults.language.decimal
11485                          *
11486                          *  @example
11487                          *    $(document).ready( function() {
11488                          *      $('#example').dataTable( {
11489                          *        "language": {
11490                          *          "decimal": ","
11491                          *          "thousands": "."
11492                          *        }
11493                          *      } );
11494                          *    } );
11495                          */
11496                         "sDecimal": "",
11497         
11498         
11499                         /**
11500                          * DataTables has a build in number formatter (`formatNumber`) which is
11501                          * used to format large numbers that are used in the table information.
11502                          * By default a comma is used, but this can be trivially changed to any
11503                          * character you wish with this parameter.
11504                          *  @type string
11505                          *  @default ,
11506                          *
11507                          *  @dtopt Language
11508                          *  @name DataTable.defaults.language.thousands
11509                          *
11510                          *  @example
11511                          *    $(document).ready( function() {
11512                          *      $('#example').dataTable( {
11513                          *        "language": {
11514                          *          "thousands": "'"
11515                          *        }
11516                          *      } );
11517                          *    } );
11518                          */
11519                         "sThousands": ",",
11520         
11521         
11522                         /**
11523                          * Detail the action that will be taken when the drop down menu for the
11524                          * pagination length option is changed. The '_MENU_' variable is replaced
11525                          * with a default select list of 10, 25, 50 and 100, and can be replaced
11526                          * with a custom select box if required.
11527                          *  @type string
11528                          *  @default Show _MENU_ entries
11529                          *
11530                          *  @dtopt Language
11531                          *  @name DataTable.defaults.language.lengthMenu
11532                          *
11533                          *  @example
11534                          *    // Language change only
11535                          *    $(document).ready( function() {
11536                          *      $('#example').dataTable( {
11537                          *        "language": {
11538                          *          "lengthMenu": "Display _MENU_ records"
11539                          *        }
11540                          *      } );
11541                          *    } );
11542                          *
11543                          *  @example
11544                          *    // Language and options change
11545                          *    $(document).ready( function() {
11546                          *      $('#example').dataTable( {
11547                          *        "language": {
11548                          *          "lengthMenu": 'Display <select>'+
11549                          *            '<option value="10">10</option>'+
11550                          *            '<option value="20">20</option>'+
11551                          *            '<option value="30">30</option>'+
11552                          *            '<option value="40">40</option>'+
11553                          *            '<option value="50">50</option>'+
11554                          *            '<option value="-1">All</option>'+
11555                          *            '</select> records'
11556                          *        }
11557                          *      } );
11558                          *    } );
11559                          */
11560                         "sLengthMenu": "Show _MENU_ entries",
11561         
11562         
11563                         /**
11564                          * When using Ajax sourced data and during the first draw when DataTables is
11565                          * gathering the data, this message is shown in an empty row in the table to
11566                          * indicate to the end user the the data is being loaded. Note that this
11567                          * parameter is not used when loading data by server-side processing, just
11568                          * Ajax sourced data with client-side processing.
11569                          *  @type string
11570                          *  @default Loading...
11571                          *
11572                          *  @dtopt Language
11573                          *  @name DataTable.defaults.language.loadingRecords
11574                          *
11575                          *  @example
11576                          *    $(document).ready( function() {
11577                          *      $('#example').dataTable( {
11578                          *        "language": {
11579                          *          "loadingRecords": "Please wait - loading..."
11580                          *        }
11581                          *      } );
11582                          *    } );
11583                          */
11584                         "sLoadingRecords": "Loading...",
11585         
11586         
11587                         /**
11588                          * Text which is displayed when the table is processing a user action
11589                          * (usually a sort command or similar).
11590                          *  @type string
11591                          *  @default Processing...
11592                          *
11593                          *  @dtopt Language
11594                          *  @name DataTable.defaults.language.processing
11595                          *
11596                          *  @example
11597                          *    $(document).ready( function() {
11598                          *      $('#example').dataTable( {
11599                          *        "language": {
11600                          *          "processing": "DataTables is currently busy"
11601                          *        }
11602                          *      } );
11603                          *    } );
11604                          */
11605                         "sProcessing": "Processing...",
11606         
11607         
11608                         /**
11609                          * Details the actions that will be taken when the user types into the
11610                          * filtering input text box. The variable "_INPUT_", if used in the string,
11611                          * is replaced with the HTML text box for the filtering input allowing
11612                          * control over where it appears in the string. If "_INPUT_" is not given
11613                          * then the input box is appended to the string automatically.
11614                          *  @type string
11615                          *  @default Search:
11616                          *
11617                          *  @dtopt Language
11618                          *  @name DataTable.defaults.language.search
11619                          *
11620                          *  @example
11621                          *    // Input text box will be appended at the end automatically
11622                          *    $(document).ready( function() {
11623                          *      $('#example').dataTable( {
11624                          *        "language": {
11625                          *          "search": "Filter records:"
11626                          *        }
11627                          *      } );
11628                          *    } );
11629                          *
11630                          *  @example
11631                          *    // Specify where the filter should appear
11632                          *    $(document).ready( function() {
11633                          *      $('#example').dataTable( {
11634                          *        "language": {
11635                          *          "search": "Apply filter _INPUT_ to table"
11636                          *        }
11637                          *      } );
11638                          *    } );
11639                          */
11640                         "sSearch": "Search:",
11641         
11642         
11643                         /**
11644                          * Assign a `placeholder` attribute to the search `input` element
11645                          *  @type string
11646                          *  @default 
11647                          *
11648                          *  @dtopt Language
11649                          *  @name DataTable.defaults.language.searchPlaceholder
11650                          */
11651                         "sSearchPlaceholder": "",
11652         
11653         
11654                         /**
11655                          * All of the language information can be stored in a file on the
11656                          * server-side, which DataTables will look up if this parameter is passed.
11657                          * It must store the URL of the language file, which is in a JSON format,
11658                          * and the object has the same properties as the oLanguage object in the
11659                          * initialiser object (i.e. the above parameters). Please refer to one of
11660                          * the example language files to see how this works in action.
11661                          *  @type string
11662                          *  @default <i>Empty string - i.e. disabled</i>
11663                          *
11664                          *  @dtopt Language
11665                          *  @name DataTable.defaults.language.url
11666                          *
11667                          *  @example
11668                          *    $(document).ready( function() {
11669                          *      $('#example').dataTable( {
11670                          *        "language": {
11671                          *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11672                          *        }
11673                          *      } );
11674                          *    } );
11675                          */
11676                         "sUrl": "",
11677         
11678         
11679                         /**
11680                          * Text shown inside the table records when the is no information to be
11681                          * displayed after filtering. `emptyTable` is shown when there is simply no
11682                          * information in the table at all (regardless of filtering).
11683                          *  @type string
11684                          *  @default No matching records found
11685                          *
11686                          *  @dtopt Language
11687                          *  @name DataTable.defaults.language.zeroRecords
11688                          *
11689                          *  @example
11690                          *    $(document).ready( function() {
11691                          *      $('#example').dataTable( {
11692                          *        "language": {
11693                          *          "zeroRecords": "No records to display"
11694                          *        }
11695                          *      } );
11696                          *    } );
11697                          */
11698                         "sZeroRecords": "No matching records found"
11699                 },
11700         
11701         
11702                 /**
11703                  * This parameter allows you to have define the global filtering state at
11704                  * initialisation time. As an object the `search` parameter must be
11705                  * defined, but all other parameters are optional. When `regex` is true,
11706                  * the search string will be treated as a regular expression, when false
11707                  * (default) it will be treated as a straight string. When `smart`
11708                  * DataTables will use it's smart filtering methods (to word match at
11709                  * any point in the data), when false this will not be done.
11710                  *  @namespace
11711                  *  @extends DataTable.models.oSearch
11712                  *
11713                  *  @dtopt Options
11714                  *  @name DataTable.defaults.search
11715                  *
11716                  *  @example
11717                  *    $(document).ready( function() {
11718                  *      $('#example').dataTable( {
11719                  *        "search": {"search": "Initial search"}
11720                  *      } );
11721                  *    } )
11722                  */
11723                 "oSearch": $.extend( {}, DataTable.models.oSearch ),
11724         
11725         
11726                 /**
11727                  * __Deprecated__ The functionality provided by this parameter has now been
11728                  * superseded by that provided through `ajax`, which should be used instead.
11729                  *
11730                  * By default DataTables will look for the property `data` (or `aaData` for
11731                  * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11732                  * source or for server-side processing - this parameter allows that
11733                  * property to be changed. You can use Javascript dotted object notation to
11734                  * get a data source for multiple levels of nesting.
11735                  *  @type string
11736                  *  @default data
11737                  *
11738                  *  @dtopt Options
11739                  *  @dtopt Server-side
11740                  *  @name DataTable.defaults.ajaxDataProp
11741                  *
11742                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
11743                  */
11744                 "sAjaxDataProp": "data",
11745         
11746         
11747                 /**
11748                  * __Deprecated__ The functionality provided by this parameter has now been
11749                  * superseded by that provided through `ajax`, which should be used instead.
11750                  *
11751                  * You can instruct DataTables to load data from an external
11752                  * source using this parameter (use aData if you want to pass data in you
11753                  * already have). Simply provide a url a JSON object can be obtained from.
11754                  *  @type string
11755                  *  @default null
11756                  *
11757                  *  @dtopt Options
11758                  *  @dtopt Server-side
11759                  *  @name DataTable.defaults.ajaxSource
11760                  *
11761                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
11762                  */
11763                 "sAjaxSource": null,
11764         
11765         
11766                 /**
11767                  * This initialisation variable allows you to specify exactly where in the
11768                  * DOM you want DataTables to inject the various controls it adds to the page
11769                  * (for example you might want the pagination controls at the top of the
11770                  * table). DIV elements (with or without a custom class) can also be added to
11771                  * aid styling. The follow syntax is used:
11772                  *   <ul>
11773                  *     <li>The following options are allowed:
11774                  *       <ul>
11775                  *         <li>'l' - Length changing</li>
11776                  *         <li>'f' - Filtering input</li>
11777                  *         <li>'t' - The table!</li>
11778                  *         <li>'i' - Information</li>
11779                  *         <li>'p' - Pagination</li>
11780                  *         <li>'r' - pRocessing</li>
11781                  *       </ul>
11782                  *     </li>
11783                  *     <li>The following constants are allowed:
11784                  *       <ul>
11785                  *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11786                  *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11787                  *       </ul>
11788                  *     </li>
11789                  *     <li>The following syntax is expected:
11790                  *       <ul>
11791                  *         <li>'&lt;' and '&gt;' - div elements</li>
11792                  *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11793                  *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11794                  *       </ul>
11795                  *     </li>
11796                  *     <li>Examples:
11797                  *       <ul>
11798                  *         <li>'&lt;"wrapper"flipt&gt;'</li>
11799                  *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11800                  *       </ul>
11801                  *     </li>
11802                  *   </ul>
11803                  *  @type string
11804                  *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11805                  *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11806                  *
11807                  *  @dtopt Options
11808                  *  @name DataTable.defaults.dom
11809                  *
11810                  *  @example
11811                  *    $(document).ready( function() {
11812                  *      $('#example').dataTable( {
11813                  *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11814                  *      } );
11815                  *    } );
11816                  */
11817                 "sDom": "lfrtip",
11818         
11819         
11820                 /**
11821                  * Search delay option. This will throttle full table searches that use the
11822                  * DataTables provided search input element (it does not effect calls to
11823                  * `dt-api search()`, providing a delay before the search is made.
11824                  *  @type integer
11825                  *  @default 0
11826                  *
11827                  *  @dtopt Options
11828                  *  @name DataTable.defaults.searchDelay
11829                  *
11830                  *  @example
11831                  *    $(document).ready( function() {
11832                  *      $('#example').dataTable( {
11833                  *        "searchDelay": 200
11834                  *      } );
11835                  *    } )
11836                  */
11837                 "searchDelay": null,
11838         
11839         
11840                 /**
11841                  * DataTables features four different built-in options for the buttons to
11842                  * display for pagination control:
11843                  *
11844                  * * `simple` - 'Previous' and 'Next' buttons only
11845                  * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11846                  * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11847                  * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus
11848                  *   page numbers
11849                  *  
11850                  * Further methods can be added using {@link DataTable.ext.oPagination}.
11851                  *  @type string
11852                  *  @default simple_numbers
11853                  *
11854                  *  @dtopt Options
11855                  *  @name DataTable.defaults.pagingType
11856                  *
11857                  *  @example
11858                  *    $(document).ready( function() {
11859                  *      $('#example').dataTable( {
11860                  *        "pagingType": "full_numbers"
11861                  *      } );
11862                  *    } )
11863                  */
11864                 "sPaginationType": "simple_numbers",
11865         
11866         
11867                 /**
11868                  * Enable horizontal scrolling. When a table is too wide to fit into a
11869                  * certain layout, or you have a large number of columns in the table, you
11870                  * can enable x-scrolling to show the table in a viewport, which can be
11871                  * scrolled. This property can be `true` which will allow the table to
11872                  * scroll horizontally when needed, or any CSS unit, or a number (in which
11873                  * case it will be treated as a pixel measurement). Setting as simply `true`
11874                  * is recommended.
11875                  *  @type boolean|string
11876                  *  @default <i>blank string - i.e. disabled</i>
11877                  *
11878                  *  @dtopt Features
11879                  *  @name DataTable.defaults.scrollX
11880                  *
11881                  *  @example
11882                  *    $(document).ready( function() {
11883                  *      $('#example').dataTable( {
11884                  *        "scrollX": true,
11885                  *        "scrollCollapse": true
11886                  *      } );
11887                  *    } );
11888                  */
11889                 "sScrollX": "",
11890         
11891         
11892                 /**
11893                  * This property can be used to force a DataTable to use more width than it
11894                  * might otherwise do when x-scrolling is enabled. For example if you have a
11895                  * table which requires to be well spaced, this parameter is useful for
11896                  * "over-sizing" the table, and thus forcing scrolling. This property can by
11897                  * any CSS unit, or a number (in which case it will be treated as a pixel
11898                  * measurement).
11899                  *  @type string
11900                  *  @default <i>blank string - i.e. disabled</i>
11901                  *
11902                  *  @dtopt Options
11903                  *  @name DataTable.defaults.scrollXInner
11904                  *
11905                  *  @example
11906                  *    $(document).ready( function() {
11907                  *      $('#example').dataTable( {
11908                  *        "scrollX": "100%",
11909                  *        "scrollXInner": "110%"
11910                  *      } );
11911                  *    } );
11912                  */
11913                 "sScrollXInner": "",
11914         
11915         
11916                 /**
11917                  * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
11918                  * to the given height, and enable scrolling for any data which overflows the
11919                  * current viewport. This can be used as an alternative to paging to display
11920                  * a lot of data in a small area (although paging and scrolling can both be
11921                  * enabled at the same time). This property can be any CSS unit, or a number
11922                  * (in which case it will be treated as a pixel measurement).
11923                  *  @type string
11924                  *  @default <i>blank string - i.e. disabled</i>
11925                  *
11926                  *  @dtopt Features
11927                  *  @name DataTable.defaults.scrollY
11928                  *
11929                  *  @example
11930                  *    $(document).ready( function() {
11931                  *      $('#example').dataTable( {
11932                  *        "scrollY": "200px",
11933                  *        "paginate": false
11934                  *      } );
11935                  *    } );
11936                  */
11937                 "sScrollY": "",
11938         
11939         
11940                 /**
11941                  * __Deprecated__ The functionality provided by this parameter has now been
11942                  * superseded by that provided through `ajax`, which should be used instead.
11943                  *
11944                  * Set the HTTP method that is used to make the Ajax call for server-side
11945                  * processing or Ajax sourced data.
11946                  *  @type string
11947                  *  @default GET
11948                  *
11949                  *  @dtopt Options
11950                  *  @dtopt Server-side
11951                  *  @name DataTable.defaults.serverMethod
11952                  *
11953                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
11954                  */
11955                 "sServerMethod": "GET",
11956         
11957         
11958                 /**
11959                  * DataTables makes use of renderers when displaying HTML elements for
11960                  * a table. These renderers can be added or modified by plug-ins to
11961                  * generate suitable mark-up for a site. For example the Bootstrap
11962                  * integration plug-in for DataTables uses a paging button renderer to
11963                  * display pagination buttons in the mark-up required by Bootstrap.
11964                  *
11965                  * For further information about the renderers available see
11966                  * DataTable.ext.renderer
11967                  *  @type string|object
11968                  *  @default null
11969                  *
11970                  *  @name DataTable.defaults.renderer
11971                  *
11972                  */
11973                 "renderer": null,
11974         
11975         
11976                 /**
11977                  * Set the data property name that DataTables should use to get a row's id
11978                  * to set as the `id` property in the node.
11979                  *  @type string
11980                  *  @default DT_RowId
11981                  *
11982                  *  @name DataTable.defaults.rowId
11983                  */
11984                 "rowId": "DT_RowId"
11985         };
11986         
11987         _fnHungarianMap( DataTable.defaults );
11988         
11989         
11990         
11991         /*
11992          * Developer note - See note in model.defaults.js about the use of Hungarian
11993          * notation and camel case.
11994          */
11995         
11996         /**
11997          * Column options that can be given to DataTables at initialisation time.
11998          *  @namespace
11999          */
12000         DataTable.defaults.column = {
12001                 /**
12002                  * Define which column(s) an order will occur on for this column. This
12003                  * allows a column's ordering to take multiple columns into account when
12004                  * doing a sort or use the data from a different column. For example first
12005                  * name / last name columns make sense to do a multi-column sort over the
12006                  * two columns.
12007                  *  @type array|int
12008                  *  @default null <i>Takes the value of the column index automatically</i>
12009                  *
12010                  *  @name DataTable.defaults.column.orderData
12011                  *  @dtopt Columns
12012                  *
12013                  *  @example
12014                  *    // Using `columnDefs`
12015                  *    $(document).ready( function() {
12016                  *      $('#example').dataTable( {
12017                  *        "columnDefs": [
12018                  *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12019                  *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12020                  *          { "orderData": 2, "targets": [ 2 ] }
12021                  *        ]
12022                  *      } );
12023                  *    } );
12024                  *
12025                  *  @example
12026                  *    // Using `columns`
12027                  *    $(document).ready( function() {
12028                  *      $('#example').dataTable( {
12029                  *        "columns": [
12030                  *          { "orderData": [ 0, 1 ] },
12031                  *          { "orderData": [ 1, 0 ] },
12032                  *          { "orderData": 2 },
12033                  *          null,
12034                  *          null
12035                  *        ]
12036                  *      } );
12037                  *    } );
12038                  */
12039                 "aDataSort": null,
12040                 "iDataSort": -1,
12041         
12042         
12043                 /**
12044                  * You can control the default ordering direction, and even alter the
12045                  * behaviour of the sort handler (i.e. only allow ascending ordering etc)
12046                  * using this parameter.
12047                  *  @type array
12048                  *  @default [ 'asc', 'desc' ]
12049                  *
12050                  *  @name DataTable.defaults.column.orderSequence
12051                  *  @dtopt Columns
12052                  *
12053                  *  @example
12054                  *    // Using `columnDefs`
12055                  *    $(document).ready( function() {
12056                  *      $('#example').dataTable( {
12057                  *        "columnDefs": [
12058                  *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12059                  *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12060                  *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12061                  *        ]
12062                  *      } );
12063                  *    } );
12064                  *
12065                  *  @example
12066                  *    // Using `columns`
12067                  *    $(document).ready( function() {
12068                  *      $('#example').dataTable( {
12069                  *        "columns": [
12070                  *          null,
12071                  *          { "orderSequence": [ "asc" ] },
12072                  *          { "orderSequence": [ "desc", "asc", "asc" ] },
12073                  *          { "orderSequence": [ "desc" ] },
12074                  *          null
12075                  *        ]
12076                  *      } );
12077                  *    } );
12078                  */
12079                 "asSorting": [ 'asc', 'desc' ],
12080         
12081         
12082                 /**
12083                  * Enable or disable filtering on the data in this column.
12084                  *  @type boolean
12085                  *  @default true
12086                  *
12087                  *  @name DataTable.defaults.column.searchable
12088                  *  @dtopt Columns
12089                  *
12090                  *  @example
12091                  *    // Using `columnDefs`
12092                  *    $(document).ready( function() {
12093                  *      $('#example').dataTable( {
12094                  *        "columnDefs": [
12095                  *          { "searchable": false, "targets": [ 0 ] }
12096                  *        ] } );
12097                  *    } );
12098                  *
12099                  *  @example
12100                  *    // Using `columns`
12101                  *    $(document).ready( function() {
12102                  *      $('#example').dataTable( {
12103                  *        "columns": [
12104                  *          { "searchable": false },
12105                  *          null,
12106                  *          null,
12107                  *          null,
12108                  *          null
12109                  *        ] } );
12110                  *    } );
12111                  */
12112                 "bSearchable": true,
12113         
12114         
12115                 /**
12116                  * Enable or disable ordering on this column.
12117                  *  @type boolean
12118                  *  @default true
12119                  *
12120                  *  @name DataTable.defaults.column.orderable
12121                  *  @dtopt Columns
12122                  *
12123                  *  @example
12124                  *    // Using `columnDefs`
12125                  *    $(document).ready( function() {
12126                  *      $('#example').dataTable( {
12127                  *        "columnDefs": [
12128                  *          { "orderable": false, "targets": [ 0 ] }
12129                  *        ] } );
12130                  *    } );
12131                  *
12132                  *  @example
12133                  *    // Using `columns`
12134                  *    $(document).ready( function() {
12135                  *      $('#example').dataTable( {
12136                  *        "columns": [
12137                  *          { "orderable": false },
12138                  *          null,
12139                  *          null,
12140                  *          null,
12141                  *          null
12142                  *        ] } );
12143                  *    } );
12144                  */
12145                 "bSortable": true,
12146         
12147         
12148                 /**
12149                  * Enable or disable the display of this column.
12150                  *  @type boolean
12151                  *  @default true
12152                  *
12153                  *  @name DataTable.defaults.column.visible
12154                  *  @dtopt Columns
12155                  *
12156                  *  @example
12157                  *    // Using `columnDefs`
12158                  *    $(document).ready( function() {
12159                  *      $('#example').dataTable( {
12160                  *        "columnDefs": [
12161                  *          { "visible": false, "targets": [ 0 ] }
12162                  *        ] } );
12163                  *    } );
12164                  *
12165                  *  @example
12166                  *    // Using `columns`
12167                  *    $(document).ready( function() {
12168                  *      $('#example').dataTable( {
12169                  *        "columns": [
12170                  *          { "visible": false },
12171                  *          null,
12172                  *          null,
12173                  *          null,
12174                  *          null
12175                  *        ] } );
12176                  *    } );
12177                  */
12178                 "bVisible": true,
12179         
12180         
12181                 /**
12182                  * Developer definable function that is called whenever a cell is created (Ajax source,
12183                  * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12184                  * allowing you to modify the DOM element (add background colour for example) when the
12185                  * element is available.
12186                  *  @type function
12187                  *  @param {element} td The TD node that has been created
12188                  *  @param {*} cellData The Data for the cell
12189                  *  @param {array|object} rowData The data for the whole row
12190                  *  @param {int} row The row index for the aoData data store
12191                  *  @param {int} col The column index for aoColumns
12192                  *
12193                  *  @name DataTable.defaults.column.createdCell
12194                  *  @dtopt Columns
12195                  *
12196                  *  @example
12197                  *    $(document).ready( function() {
12198                  *      $('#example').dataTable( {
12199                  *        "columnDefs": [ {
12200                  *          "targets": [3],
12201                  *          "createdCell": function (td, cellData, rowData, row, col) {
12202                  *            if ( cellData == "1.7" ) {
12203                  *              $(td).css('color', 'blue')
12204                  *            }
12205                  *          }
12206                  *        } ]
12207                  *      });
12208                  *    } );
12209                  */
12210                 "fnCreatedCell": null,
12211         
12212         
12213                 /**
12214                  * This parameter has been replaced by `data` in DataTables to ensure naming
12215                  * consistency. `dataProp` can still be used, as there is backwards
12216                  * compatibility in DataTables for this option, but it is strongly
12217                  * recommended that you use `data` in preference to `dataProp`.
12218                  *  @name DataTable.defaults.column.dataProp
12219                  */
12220         
12221         
12222                 /**
12223                  * This property can be used to read data from any data source property,
12224                  * including deeply nested objects / properties. `data` can be given in a
12225                  * number of different ways which effect its behaviour:
12226                  *
12227                  * * `integer` - treated as an array index for the data source. This is the
12228                  *   default that DataTables uses (incrementally increased for each column).
12229                  * * `string` - read an object property from the data source. There are
12230                  *   three 'special' options that can be used in the string to alter how
12231                  *   DataTables reads the data from the source object:
12232                  *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12233                  *      Javascript to read from nested objects, so to can the options
12234                  *      specified in `data`. For example: `browser.version` or
12235                  *      `browser.name`. If your object parameter name contains a period, use
12236                  *      `\\` to escape it - i.e. `first\\.name`.
12237                  *    * `[]` - Array notation. DataTables can automatically combine data
12238                  *      from and array source, joining the data with the characters provided
12239                  *      between the two brackets. For example: `name[, ]` would provide a
12240                  *      comma-space separated list from the source array. If no characters
12241                  *      are provided between the brackets, the original array source is
12242                  *      returned.
12243                  *    * `()` - Function notation. Adding `()` to the end of a parameter will
12244                  *      execute a function of the name given. For example: `browser()` for a
12245                  *      simple function on the data source, `browser.version()` for a
12246                  *      function in a nested property or even `browser().version` to get an
12247                  *      object property if the function called returns an object. Note that
12248                  *      function notation is recommended for use in `render` rather than
12249                  *      `data` as it is much simpler to use as a renderer.
12250                  * * `null` - use the original data source for the row rather than plucking
12251                  *   data directly from it. This action has effects on two other
12252                  *   initialisation options:
12253                  *    * `defaultContent` - When null is given as the `data` option and
12254                  *      `defaultContent` is specified for the column, the value defined by
12255                  *      `defaultContent` will be used for the cell.
12256                  *    * `render` - When null is used for the `data` option and the `render`
12257                  *      option is specified for the column, the whole data source for the
12258                  *      row is used for the renderer.
12259                  * * `function` - the function given will be executed whenever DataTables
12260                  *   needs to set or get the data for a cell in the column. The function
12261                  *   takes three parameters:
12262                  *    * Parameters:
12263                  *      * `{array|object}` The data source for the row
12264                  *      * `{string}` The type call data requested - this will be 'set' when
12265                  *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12266                  *        when gathering data. Note that when `undefined` is given for the
12267                  *        type DataTables expects to get the raw data for the object back<
12268                  *      * `{*}` Data to set when the second parameter is 'set'.
12269                  *    * Return:
12270                  *      * The return value from the function is not required when 'set' is
12271                  *        the type of call, but otherwise the return is what will be used
12272                  *        for the data requested.
12273                  *
12274                  * Note that `data` is a getter and setter option. If you just require
12275                  * formatting of data for output, you will likely want to use `render` which
12276                  * is simply a getter and thus simpler to use.
12277                  *
12278                  * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12279                  * name change reflects the flexibility of this property and is consistent
12280                  * with the naming of mRender. If 'mDataProp' is given, then it will still
12281                  * be used by DataTables, as it automatically maps the old name to the new
12282                  * if required.
12283                  *
12284                  *  @type string|int|function|null
12285                  *  @default null <i>Use automatically calculated column index</i>
12286                  *
12287                  *  @name DataTable.defaults.column.data
12288                  *  @dtopt Columns
12289                  *
12290                  *  @example
12291                  *    // Read table data from objects
12292                  *    // JSON structure for each row:
12293                  *    //   {
12294                  *    //      "engine": {value},
12295                  *    //      "browser": {value},
12296                  *    //      "platform": {value},
12297                  *    //      "version": {value},
12298                  *    //      "grade": {value}
12299                  *    //   }
12300                  *    $(document).ready( function() {
12301                  *      $('#example').dataTable( {
12302                  *        "ajaxSource": "sources/objects.txt",
12303                  *        "columns": [
12304                  *          { "data": "engine" },
12305                  *          { "data": "browser" },
12306                  *          { "data": "platform" },
12307                  *          { "data": "version" },
12308                  *          { "data": "grade" }
12309                  *        ]
12310                  *      } );
12311                  *    } );
12312                  *
12313                  *  @example
12314                  *    // Read information from deeply nested objects
12315                  *    // JSON structure for each row:
12316                  *    //   {
12317                  *    //      "engine": {value},
12318                  *    //      "browser": {value},
12319                  *    //      "platform": {
12320                  *    //         "inner": {value}
12321                  *    //      },
12322                  *    //      "details": [
12323                  *    //         {value}, {value}
12324                  *    //      ]
12325                  *    //   }
12326                  *    $(document).ready( function() {
12327                  *      $('#example').dataTable( {
12328                  *        "ajaxSource": "sources/deep.txt",
12329                  *        "columns": [
12330                  *          { "data": "engine" },
12331                  *          { "data": "browser" },
12332                  *          { "data": "platform.inner" },
12333                  *          { "data": "platform.details.0" },
12334                  *          { "data": "platform.details.1" }
12335                  *        ]
12336                  *      } );
12337                  *    } );
12338                  *
12339                  *  @example
12340                  *    // Using `data` as a function to provide different information for
12341                  *    // sorting, filtering and display. In this case, currency (price)
12342                  *    $(document).ready( function() {
12343                  *      $('#example').dataTable( {
12344                  *        "columnDefs": [ {
12345                  *          "targets": [ 0 ],
12346                  *          "data": function ( source, type, val ) {
12347                  *            if (type === 'set') {
12348                  *              source.price = val;
12349                  *              // Store the computed dislay and filter values for efficiency
12350                  *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12351                  *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12352                  *              return;
12353                  *            }
12354                  *            else if (type === 'display') {
12355                  *              return source.price_display;
12356                  *            }
12357                  *            else if (type === 'filter') {
12358                  *              return source.price_filter;
12359                  *            }
12360                  *            // 'sort', 'type' and undefined all just use the integer
12361                  *            return source.price;
12362                  *          }
12363                  *        } ]
12364                  *      } );
12365                  *    } );
12366                  *
12367                  *  @example
12368                  *    // Using default content
12369                  *    $(document).ready( function() {
12370                  *      $('#example').dataTable( {
12371                  *        "columnDefs": [ {
12372                  *          "targets": [ 0 ],
12373                  *          "data": null,
12374                  *          "defaultContent": "Click to edit"
12375                  *        } ]
12376                  *      } );
12377                  *    } );
12378                  *
12379                  *  @example
12380                  *    // Using array notation - outputting a list from an array
12381                  *    $(document).ready( function() {
12382                  *      $('#example').dataTable( {
12383                  *        "columnDefs": [ {
12384                  *          "targets": [ 0 ],
12385                  *          "data": "name[, ]"
12386                  *        } ]
12387                  *      } );
12388                  *    } );
12389                  *
12390                  */
12391                 "mData": null,
12392         
12393         
12394                 /**
12395                  * This property is the rendering partner to `data` and it is suggested that
12396                  * when you want to manipulate data for display (including filtering,
12397                  * sorting etc) without altering the underlying data for the table, use this
12398                  * property. `render` can be considered to be the the read only companion to
12399                  * `data` which is read / write (then as such more complex). Like `data`
12400                  * this option can be given in a number of different ways to effect its
12401                  * behaviour:
12402                  *
12403                  * * `integer` - treated as an array index for the data source. This is the
12404                  *   default that DataTables uses (incrementally increased for each column).
12405                  * * `string` - read an object property from the data source. There are
12406                  *   three 'special' options that can be used in the string to alter how
12407                  *   DataTables reads the data from the source object:
12408                  *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12409                  *      Javascript to read from nested objects, so to can the options
12410                  *      specified in `data`. For example: `browser.version` or
12411                  *      `browser.name`. If your object parameter name contains a period, use
12412                  *      `\\` to escape it - i.e. `first\\.name`.
12413                  *    * `[]` - Array notation. DataTables can automatically combine data
12414                  *      from and array source, joining the data with the characters provided
12415                  *      between the two brackets. For example: `name[, ]` would provide a
12416                  *      comma-space separated list from the source array. If no characters
12417                  *      are provided between the brackets, the original array source is
12418                  *      returned.
12419                  *    * `()` - Function notation. Adding `()` to the end of a parameter will
12420                  *      execute a function of the name given. For example: `browser()` for a
12421                  *      simple function on the data source, `browser.version()` for a
12422                  *      function in a nested property or even `browser().version` to get an
12423                  *      object property if the function called returns an object.
12424                  * * `object` - use different data for the different data types requested by
12425                  *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12426                  *   of the object is the data type the property refers to and the value can
12427                  *   defined using an integer, string or function using the same rules as
12428                  *   `render` normally does. Note that an `_` option _must_ be specified.
12429                  *   This is the default value to use if you haven't specified a value for
12430                  *   the data type requested by DataTables.
12431                  * * `function` - the function given will be executed whenever DataTables
12432                  *   needs to set or get the data for a cell in the column. The function
12433                  *   takes three parameters:
12434                  *    * Parameters:
12435                  *      * {array|object} The data source for the row (based on `data`)
12436                  *      * {string} The type call data requested - this will be 'filter',
12437                  *        'display', 'type' or 'sort'.
12438                  *      * {array|object} The full data source for the row (not based on
12439                  *        `data`)
12440                  *    * Return:
12441                  *      * The return value from the function is what will be used for the
12442                  *        data requested.
12443                  *
12444                  *  @type string|int|function|object|null
12445                  *  @default null Use the data source value.
12446                  *
12447                  *  @name DataTable.defaults.column.render
12448                  *  @dtopt Columns
12449                  *
12450                  *  @example
12451                  *    // Create a comma separated list from an array of objects
12452                  *    $(document).ready( function() {
12453                  *      $('#example').dataTable( {
12454                  *        "ajaxSource": "sources/deep.txt",
12455                  *        "columns": [
12456                  *          { "data": "engine" },
12457                  *          { "data": "browser" },
12458                  *          {
12459                  *            "data": "platform",
12460                  *            "render": "[, ].name"
12461                  *          }
12462                  *        ]
12463                  *      } );
12464                  *    } );
12465                  *
12466                  *  @example
12467                  *    // Execute a function to obtain data
12468                  *    $(document).ready( function() {
12469                  *      $('#example').dataTable( {
12470                  *        "columnDefs": [ {
12471                  *          "targets": [ 0 ],
12472                  *          "data": null, // Use the full data source object for the renderer's source
12473                  *          "render": "browserName()"
12474                  *        } ]
12475                  *      } );
12476                  *    } );
12477                  *
12478                  *  @example
12479                  *    // As an object, extracting different data for the different types
12480                  *    // This would be used with a data source such as:
12481                  *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12482                  *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12483                  *    // (which has both forms) is used for filtering for if a user inputs either format, while
12484                  *    // the formatted phone number is the one that is shown in the table.
12485                  *    $(document).ready( function() {
12486                  *      $('#example').dataTable( {
12487                  *        "columnDefs": [ {
12488                  *          "targets": [ 0 ],
12489                  *          "data": null, // Use the full data source object for the renderer's source
12490                  *          "render": {
12491                  *            "_": "phone",
12492                  *            "filter": "phone_filter",
12493                  *            "display": "phone_display"
12494                  *          }
12495                  *        } ]
12496                  *      } );
12497                  *    } );
12498                  *
12499                  *  @example
12500                  *    // Use as a function to create a link from the data source
12501                  *    $(document).ready( function() {
12502                  *      $('#example').dataTable( {
12503                  *        "columnDefs": [ {
12504                  *          "targets": [ 0 ],
12505                  *          "data": "download_link",
12506                  *          "render": function ( data, type, full ) {
12507                  *            return '<a href="'+data+'">Download</a>';
12508                  *          }
12509                  *        } ]
12510                  *      } );
12511                  *    } );
12512                  */
12513                 "mRender": null,
12514         
12515         
12516                 /**
12517                  * Change the cell type created for the column - either TD cells or TH cells. This
12518                  * can be useful as TH cells have semantic meaning in the table body, allowing them
12519                  * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12520                  *  @type string
12521                  *  @default td
12522                  *
12523                  *  @name DataTable.defaults.column.cellType
12524                  *  @dtopt Columns
12525                  *
12526                  *  @example
12527                  *    // Make the first column use TH cells
12528                  *    $(document).ready( function() {
12529                  *      $('#example').dataTable( {
12530                  *        "columnDefs": [ {
12531                  *          "targets": [ 0 ],
12532                  *          "cellType": "th"
12533                  *        } ]
12534                  *      } );
12535                  *    } );
12536                  */
12537                 "sCellType": "td",
12538         
12539         
12540                 /**
12541                  * Class to give to each cell in this column.
12542                  *  @type string
12543                  *  @default <i>Empty string</i>
12544                  *
12545                  *  @name DataTable.defaults.column.class
12546                  *  @dtopt Columns
12547                  *
12548                  *  @example
12549                  *    // Using `columnDefs`
12550                  *    $(document).ready( function() {
12551                  *      $('#example').dataTable( {
12552                  *        "columnDefs": [
12553                  *          { "class": "my_class", "targets": [ 0 ] }
12554                  *        ]
12555                  *      } );
12556                  *    } );
12557                  *
12558                  *  @example
12559                  *    // Using `columns`
12560                  *    $(document).ready( function() {
12561                  *      $('#example').dataTable( {
12562                  *        "columns": [
12563                  *          { "class": "my_class" },
12564                  *          null,
12565                  *          null,
12566                  *          null,
12567                  *          null
12568                  *        ]
12569                  *      } );
12570                  *    } );
12571                  */
12572                 "sClass": "",
12573         
12574                 /**
12575                  * When DataTables calculates the column widths to assign to each column,
12576                  * it finds the longest string in each column and then constructs a
12577                  * temporary table and reads the widths from that. The problem with this
12578                  * is that "mmm" is much wider then "iiii", but the latter is a longer
12579                  * string - thus the calculation can go wrong (doing it properly and putting
12580                  * it into an DOM object and measuring that is horribly(!) slow). Thus as
12581                  * a "work around" we provide this option. It will append its value to the
12582                  * text that is found to be the longest string for the column - i.e. padding.
12583                  * Generally you shouldn't need this!
12584                  *  @type string
12585                  *  @default <i>Empty string<i>
12586                  *
12587                  *  @name DataTable.defaults.column.contentPadding
12588                  *  @dtopt Columns
12589                  *
12590                  *  @example
12591                  *    // Using `columns`
12592                  *    $(document).ready( function() {
12593                  *      $('#example').dataTable( {
12594                  *        "columns": [
12595                  *          null,
12596                  *          null,
12597                  *          null,
12598                  *          {
12599                  *            "contentPadding": "mmm"
12600                  *          }
12601                  *        ]
12602                  *      } );
12603                  *    } );
12604                  */
12605                 "sContentPadding": "",
12606         
12607         
12608                 /**
12609                  * Allows a default value to be given for a column's data, and will be used
12610                  * whenever a null data source is encountered (this can be because `data`
12611                  * is set to null, or because the data source itself is null).
12612                  *  @type string
12613                  *  @default null
12614                  *
12615                  *  @name DataTable.defaults.column.defaultContent
12616                  *  @dtopt Columns
12617                  *
12618                  *  @example
12619                  *    // Using `columnDefs`
12620                  *    $(document).ready( function() {
12621                  *      $('#example').dataTable( {
12622                  *        "columnDefs": [
12623                  *          {
12624                  *            "data": null,
12625                  *            "defaultContent": "Edit",
12626                  *            "targets": [ -1 ]
12627                  *          }
12628                  *        ]
12629                  *      } );
12630                  *    } );
12631                  *
12632                  *  @example
12633                  *    // Using `columns`
12634                  *    $(document).ready( function() {
12635                  *      $('#example').dataTable( {
12636                  *        "columns": [
12637                  *          null,
12638                  *          null,
12639                  *          null,
12640                  *          {
12641                  *            "data": null,
12642                  *            "defaultContent": "Edit"
12643                  *          }
12644                  *        ]
12645                  *      } );
12646                  *    } );
12647                  */
12648                 "sDefaultContent": null,
12649         
12650         
12651                 /**
12652                  * This parameter is only used in DataTables' server-side processing. It can
12653                  * be exceptionally useful to know what columns are being displayed on the
12654                  * client side, and to map these to database fields. When defined, the names
12655                  * also allow DataTables to reorder information from the server if it comes
12656                  * back in an unexpected order (i.e. if you switch your columns around on the
12657                  * client-side, your server-side code does not also need updating).
12658                  *  @type string
12659                  *  @default <i>Empty string</i>
12660                  *
12661                  *  @name DataTable.defaults.column.name
12662                  *  @dtopt Columns
12663                  *
12664                  *  @example
12665                  *    // Using `columnDefs`
12666                  *    $(document).ready( function() {
12667                  *      $('#example').dataTable( {
12668                  *        "columnDefs": [
12669                  *          { "name": "engine", "targets": [ 0 ] },
12670                  *          { "name": "browser", "targets": [ 1 ] },
12671                  *          { "name": "platform", "targets": [ 2 ] },
12672                  *          { "name": "version", "targets": [ 3 ] },
12673                  *          { "name": "grade", "targets": [ 4 ] }
12674                  *        ]
12675                  *      } );
12676                  *    } );
12677                  *
12678                  *  @example
12679                  *    // Using `columns`
12680                  *    $(document).ready( function() {
12681                  *      $('#example').dataTable( {
12682                  *        "columns": [
12683                  *          { "name": "engine" },
12684                  *          { "name": "browser" },
12685                  *          { "name": "platform" },
12686                  *          { "name": "version" },
12687                  *          { "name": "grade" }
12688                  *        ]
12689                  *      } );
12690                  *    } );
12691                  */
12692                 "sName": "",
12693         
12694         
12695                 /**
12696                  * Defines a data source type for the ordering which can be used to read
12697                  * real-time information from the table (updating the internally cached
12698                  * version) prior to ordering. This allows ordering to occur on user
12699                  * editable elements such as form inputs.
12700                  *  @type string
12701                  *  @default std
12702                  *
12703                  *  @name DataTable.defaults.column.orderDataType
12704                  *  @dtopt Columns
12705                  *
12706                  *  @example
12707                  *    // Using `columnDefs`
12708                  *    $(document).ready( function() {
12709                  *      $('#example').dataTable( {
12710                  *        "columnDefs": [
12711                  *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12712                  *          { "type": "numeric", "targets": [ 3 ] },
12713                  *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12714                  *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12715                  *        ]
12716                  *      } );
12717                  *    } );
12718                  *
12719                  *  @example
12720                  *    // Using `columns`
12721                  *    $(document).ready( function() {
12722                  *      $('#example').dataTable( {
12723                  *        "columns": [
12724                  *          null,
12725                  *          null,
12726                  *          { "orderDataType": "dom-text" },
12727                  *          { "orderDataType": "dom-text", "type": "numeric" },
12728                  *          { "orderDataType": "dom-select" },
12729                  *          { "orderDataType": "dom-checkbox" }
12730                  *        ]
12731                  *      } );
12732                  *    } );
12733                  */
12734                 "sSortDataType": "std",
12735         
12736         
12737                 /**
12738                  * The title of this column.
12739                  *  @type string
12740                  *  @default null <i>Derived from the 'TH' value for this column in the
12741                  *    original HTML table.</i>
12742                  *
12743                  *  @name DataTable.defaults.column.title
12744                  *  @dtopt Columns
12745                  *
12746                  *  @example
12747                  *    // Using `columnDefs`
12748                  *    $(document).ready( function() {
12749                  *      $('#example').dataTable( {
12750                  *        "columnDefs": [
12751                  *          { "title": "My column title", "targets": [ 0 ] }
12752                  *        ]
12753                  *      } );
12754                  *    } );
12755                  *
12756                  *  @example
12757                  *    // Using `columns`
12758                  *    $(document).ready( function() {
12759                  *      $('#example').dataTable( {
12760                  *        "columns": [
12761                  *          { "title": "My column title" },
12762                  *          null,
12763                  *          null,
12764                  *          null,
12765                  *          null
12766                  *        ]
12767                  *      } );
12768                  *    } );
12769                  */
12770                 "sTitle": null,
12771         
12772         
12773                 /**
12774                  * The type allows you to specify how the data for this column will be
12775                  * ordered. Four types (string, numeric, date and html (which will strip
12776                  * HTML tags before ordering)) are currently available. Note that only date
12777                  * formats understood by Javascript's Date() object will be accepted as type
12778                  * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12779                  * 'numeric', 'date' or 'html' (by default). Further types can be adding
12780                  * through plug-ins.
12781                  *  @type string
12782                  *  @default null <i>Auto-detected from raw data</i>
12783                  *
12784                  *  @name DataTable.defaults.column.type
12785                  *  @dtopt Columns
12786                  *
12787                  *  @example
12788                  *    // Using `columnDefs`
12789                  *    $(document).ready( function() {
12790                  *      $('#example').dataTable( {
12791                  *        "columnDefs": [
12792                  *          { "type": "html", "targets": [ 0 ] }
12793                  *        ]
12794                  *      } );
12795                  *    } );
12796                  *
12797                  *  @example
12798                  *    // Using `columns`
12799                  *    $(document).ready( function() {
12800                  *      $('#example').dataTable( {
12801                  *        "columns": [
12802                  *          { "type": "html" },
12803                  *          null,
12804                  *          null,
12805                  *          null,
12806                  *          null
12807                  *        ]
12808                  *      } );
12809                  *    } );
12810                  */
12811                 "sType": null,
12812         
12813         
12814                 /**
12815                  * Defining the width of the column, this parameter may take any CSS value
12816                  * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12817                  * been given a specific width through this interface ensuring that the table
12818                  * remains readable.
12819                  *  @type string
12820                  *  @default null <i>Automatic</i>
12821                  *
12822                  *  @name DataTable.defaults.column.width
12823                  *  @dtopt Columns
12824                  *
12825                  *  @example
12826                  *    // Using `columnDefs`
12827                  *    $(document).ready( function() {
12828                  *      $('#example').dataTable( {
12829                  *        "columnDefs": [
12830                  *          { "width": "20%", "targets": [ 0 ] }
12831                  *        ]
12832                  *      } );
12833                  *    } );
12834                  *
12835                  *  @example
12836                  *    // Using `columns`
12837                  *    $(document).ready( function() {
12838                  *      $('#example').dataTable( {
12839                  *        "columns": [
12840                  *          { "width": "20%" },
12841                  *          null,
12842                  *          null,
12843                  *          null,
12844                  *          null
12845                  *        ]
12846                  *      } );
12847                  *    } );
12848                  */
12849                 "sWidth": null
12850         };
12851         
12852         _fnHungarianMap( DataTable.defaults.column );
12853         
12854         
12855         
12856         /**
12857          * DataTables settings object - this holds all the information needed for a
12858          * given table, including configuration, data and current application of the
12859          * table options. DataTables does not have a single instance for each DataTable
12860          * with the settings attached to that instance, but rather instances of the
12861          * DataTable "class" are created on-the-fly as needed (typically by a
12862          * $().dataTable() call) and the settings object is then applied to that
12863          * instance.
12864          *
12865          * Note that this object is related to {@link DataTable.defaults} but this
12866          * one is the internal data store for DataTables's cache of columns. It should
12867          * NOT be manipulated outside of DataTables. Any configuration should be done
12868          * through the initialisation options.
12869          *  @namespace
12870          *  @todo Really should attach the settings object to individual instances so we
12871          *    don't need to create new instances on each $().dataTable() call (if the
12872          *    table already exists). It would also save passing oSettings around and
12873          *    into every single function. However, this is a very significant
12874          *    architecture change for DataTables and will almost certainly break
12875          *    backwards compatibility with older installations. This is something that
12876          *    will be done in 2.0.
12877          */
12878         DataTable.models.oSettings = {
12879                 /**
12880                  * Primary features of DataTables and their enablement state.
12881                  *  @namespace
12882                  */
12883                 "oFeatures": {
12884         
12885                         /**
12886                          * Flag to say if DataTables should automatically try to calculate the
12887                          * optimum table and columns widths (true) or not (false).
12888                          * Note that this parameter will be set by the initialisation routine. To
12889                          * set a default use {@link DataTable.defaults}.
12890                          *  @type boolean
12891                          */
12892                         "bAutoWidth": null,
12893         
12894                         /**
12895                          * Delay the creation of TR and TD elements until they are actually
12896                          * needed by a driven page draw. This can give a significant speed
12897                          * increase for Ajax source and Javascript source data, but makes no
12898                          * difference at all fro DOM and server-side processing tables.
12899                          * Note that this parameter will be set by the initialisation routine. To
12900                          * set a default use {@link DataTable.defaults}.
12901                          *  @type boolean
12902                          */
12903                         "bDeferRender": null,
12904         
12905                         /**
12906                          * Enable filtering on the table or not. Note that if this is disabled
12907                          * then there is no filtering at all on the table, including fnFilter.
12908                          * To just remove the filtering input use sDom and remove the 'f' option.
12909                          * Note that this parameter will be set by the initialisation routine. To
12910                          * set a default use {@link DataTable.defaults}.
12911                          *  @type boolean
12912                          */
12913                         "bFilter": null,
12914         
12915                         /**
12916                          * Table information element (the 'Showing x of y records' div) enable
12917                          * flag.
12918                          * Note that this parameter will be set by the initialisation routine. To
12919                          * set a default use {@link DataTable.defaults}.
12920                          *  @type boolean
12921                          */
12922                         "bInfo": null,
12923         
12924                         /**
12925                          * Present a user control allowing the end user to change the page size
12926                          * when pagination is enabled.
12927                          * Note that this parameter will be set by the initialisation routine. To
12928                          * set a default use {@link DataTable.defaults}.
12929                          *  @type boolean
12930                          */
12931                         "bLengthChange": null,
12932         
12933                         /**
12934                          * Pagination enabled or not. Note that if this is disabled then length
12935                          * changing must also be disabled.
12936                          * Note that this parameter will be set by the initialisation routine. To
12937                          * set a default use {@link DataTable.defaults}.
12938                          *  @type boolean
12939                          */
12940                         "bPaginate": null,
12941         
12942                         /**
12943                          * Processing indicator enable flag whenever DataTables is enacting a
12944                          * user request - typically an Ajax request for server-side processing.
12945                          * Note that this parameter will be set by the initialisation routine. To
12946                          * set a default use {@link DataTable.defaults}.
12947                          *  @type boolean
12948                          */
12949                         "bProcessing": null,
12950         
12951                         /**
12952                          * Server-side processing enabled flag - when enabled DataTables will
12953                          * get all data from the server for every draw - there is no filtering,
12954                          * sorting or paging done on the client-side.
12955                          * Note that this parameter will be set by the initialisation routine. To
12956                          * set a default use {@link DataTable.defaults}.
12957                          *  @type boolean
12958                          */
12959                         "bServerSide": null,
12960         
12961                         /**
12962                          * Sorting enablement flag.
12963                          * Note that this parameter will be set by the initialisation routine. To
12964                          * set a default use {@link DataTable.defaults}.
12965                          *  @type boolean
12966                          */
12967                         "bSort": null,
12968         
12969                         /**
12970                          * Multi-column sorting
12971                          * Note that this parameter will be set by the initialisation routine. To
12972                          * set a default use {@link DataTable.defaults}.
12973                          *  @type boolean
12974                          */
12975                         "bSortMulti": null,
12976         
12977                         /**
12978                          * Apply a class to the columns which are being sorted to provide a
12979                          * visual highlight or not. This can slow things down when enabled since
12980                          * there is a lot of DOM interaction.
12981                          * Note that this parameter will be set by the initialisation routine. To
12982                          * set a default use {@link DataTable.defaults}.
12983                          *  @type boolean
12984                          */
12985                         "bSortClasses": null,
12986         
12987                         /**
12988                          * State saving enablement flag.
12989                          * Note that this parameter will be set by the initialisation routine. To
12990                          * set a default use {@link DataTable.defaults}.
12991                          *  @type boolean
12992                          */
12993                         "bStateSave": null
12994                 },
12995         
12996         
12997                 /**
12998                  * Scrolling settings for a table.
12999                  *  @namespace
13000                  */
13001                 "oScroll": {
13002                         /**
13003                          * When the table is shorter in height than sScrollY, collapse the
13004                          * table container down to the height of the table (when true).
13005                          * Note that this parameter will be set by the initialisation routine. To
13006                          * set a default use {@link DataTable.defaults}.
13007                          *  @type boolean
13008                          */
13009                         "bCollapse": null,
13010         
13011                         /**
13012                          * Width of the scrollbar for the web-browser's platform. Calculated
13013                          * during table initialisation.
13014                          *  @type int
13015                          *  @default 0
13016                          */
13017                         "iBarWidth": 0,
13018         
13019                         /**
13020                          * Viewport width for horizontal scrolling. Horizontal scrolling is
13021                          * disabled if an empty string.
13022                          * Note that this parameter will be set by the initialisation routine. To
13023                          * set a default use {@link DataTable.defaults}.
13024                          *  @type string
13025                          */
13026                         "sX": null,
13027         
13028                         /**
13029                          * Width to expand the table to when using x-scrolling. Typically you
13030                          * should not need to use this.
13031                          * Note that this parameter will be set by the initialisation routine. To
13032                          * set a default use {@link DataTable.defaults}.
13033                          *  @type string
13034                          *  @deprecated
13035                          */
13036                         "sXInner": null,
13037         
13038                         /**
13039                          * Viewport height for vertical scrolling. Vertical scrolling is disabled
13040                          * if an empty string.
13041                          * Note that this parameter will be set by the initialisation routine. To
13042                          * set a default use {@link DataTable.defaults}.
13043                          *  @type string
13044                          */
13045                         "sY": null
13046                 },
13047         
13048                 /**
13049                  * Language information for the table.
13050                  *  @namespace
13051                  *  @extends DataTable.defaults.oLanguage
13052                  */
13053                 "oLanguage": {
13054                         /**
13055                          * Information callback function. See
13056                          * {@link DataTable.defaults.fnInfoCallback}
13057                          *  @type function
13058                          *  @default null
13059                          */
13060                         "fnInfoCallback": null
13061                 },
13062         
13063                 /**
13064                  * Browser support parameters
13065                  *  @namespace
13066                  */
13067                 "oBrowser": {
13068                         /**
13069                          * Indicate if the browser incorrectly calculates width:100% inside a
13070                          * scrolling element (IE6/7)
13071                          *  @type boolean
13072                          *  @default false
13073                          */
13074                         "bScrollOversize": false,
13075         
13076                         /**
13077                          * Determine if the vertical scrollbar is on the right or left of the
13078                          * scrolling container - needed for rtl language layout, although not
13079                          * all browsers move the scrollbar (Safari).
13080                          *  @type boolean
13081                          *  @default false
13082                          */
13083                         "bScrollbarLeft": false,
13084         
13085                         /**
13086                          * Flag for if `getBoundingClientRect` is fully supported or not
13087                          *  @type boolean
13088                          *  @default false
13089                          */
13090                         "bBounding": false,
13091         
13092                         /**
13093                          * Browser scrollbar width
13094                          *  @type integer
13095                          *  @default 0
13096                          */
13097                         "barWidth": 0
13098                 },
13099         
13100         
13101                 "ajax": null,
13102         
13103         
13104                 /**
13105                  * Array referencing the nodes which are used for the features. The
13106                  * parameters of this object match what is allowed by sDom - i.e.
13107                  *   <ul>
13108                  *     <li>'l' - Length changing</li>
13109                  *     <li>'f' - Filtering input</li>
13110                  *     <li>'t' - The table!</li>
13111                  *     <li>'i' - Information</li>
13112                  *     <li>'p' - Pagination</li>
13113                  *     <li>'r' - pRocessing</li>
13114                  *   </ul>
13115                  *  @type array
13116                  *  @default []
13117                  */
13118                 "aanFeatures": [],
13119         
13120                 /**
13121                  * Store data information - see {@link DataTable.models.oRow} for detailed
13122                  * information.
13123                  *  @type array
13124                  *  @default []
13125                  */
13126                 "aoData": [],
13127         
13128                 /**
13129                  * Array of indexes which are in the current display (after filtering etc)
13130                  *  @type array
13131                  *  @default []
13132                  */
13133                 "aiDisplay": [],
13134         
13135                 /**
13136                  * Array of indexes for display - no filtering
13137                  *  @type array
13138                  *  @default []
13139                  */
13140                 "aiDisplayMaster": [],
13141         
13142                 /**
13143                  * Map of row ids to data indexes
13144                  *  @type object
13145                  *  @default {}
13146                  */
13147                 "aIds": {},
13148         
13149                 /**
13150                  * Store information about each column that is in use
13151                  *  @type array
13152                  *  @default []
13153                  */
13154                 "aoColumns": [],
13155         
13156                 /**
13157                  * Store information about the table's header
13158                  *  @type array
13159                  *  @default []
13160                  */
13161                 "aoHeader": [],
13162         
13163                 /**
13164                  * Store information about the table's footer
13165                  *  @type array
13166                  *  @default []
13167                  */
13168                 "aoFooter": [],
13169         
13170                 /**
13171                  * Store the applied global search information in case we want to force a
13172                  * research or compare the old search to a new one.
13173                  * Note that this parameter will be set by the initialisation routine. To
13174                  * set a default use {@link DataTable.defaults}.
13175                  *  @namespace
13176                  *  @extends DataTable.models.oSearch
13177                  */
13178                 "oPreviousSearch": {},
13179         
13180                 /**
13181                  * Store the applied search for each column - see
13182                  * {@link DataTable.models.oSearch} for the format that is used for the
13183                  * filtering information for each column.
13184                  *  @type array
13185                  *  @default []
13186                  */
13187                 "aoPreSearchCols": [],
13188         
13189                 /**
13190                  * Sorting that is applied to the table. Note that the inner arrays are
13191                  * used in the following manner:
13192                  * <ul>
13193                  *   <li>Index 0 - column number</li>
13194                  *   <li>Index 1 - current sorting direction</li>
13195                  * </ul>
13196                  * Note that this parameter will be set by the initialisation routine. To
13197                  * set a default use {@link DataTable.defaults}.
13198                  *  @type array
13199                  *  @todo These inner arrays should really be objects
13200                  */
13201                 "aaSorting": null,
13202         
13203                 /**
13204                  * Sorting that is always applied to the table (i.e. prefixed in front of
13205                  * aaSorting).
13206                  * Note that this parameter will be set by the initialisation routine. To
13207                  * set a default use {@link DataTable.defaults}.
13208                  *  @type array
13209                  *  @default []
13210                  */
13211                 "aaSortingFixed": [],
13212         
13213                 /**
13214                  * Classes to use for the striping of a table.
13215                  * Note that this parameter will be set by the initialisation routine. To
13216                  * set a default use {@link DataTable.defaults}.
13217                  *  @type array
13218                  *  @default []
13219                  */
13220                 "asStripeClasses": null,
13221         
13222                 /**
13223                  * If restoring a table - we should restore its striping classes as well
13224                  *  @type array
13225                  *  @default []
13226                  */
13227                 "asDestroyStripes": [],
13228         
13229                 /**
13230                  * If restoring a table - we should restore its width
13231                  *  @type int
13232                  *  @default 0
13233                  */
13234                 "sDestroyWidth": 0,
13235         
13236                 /**
13237                  * Callback functions array for every time a row is inserted (i.e. on a draw).
13238                  *  @type array
13239                  *  @default []
13240                  */
13241                 "aoRowCallback": [],
13242         
13243                 /**
13244                  * Callback functions for the header on each draw.
13245                  *  @type array
13246                  *  @default []
13247                  */
13248                 "aoHeaderCallback": [],
13249         
13250                 /**
13251                  * Callback function for the footer on each draw.
13252                  *  @type array
13253                  *  @default []
13254                  */
13255                 "aoFooterCallback": [],
13256         
13257                 /**
13258                  * Array of callback functions for draw callback functions
13259                  *  @type array
13260                  *  @default []
13261                  */
13262                 "aoDrawCallback": [],
13263         
13264                 /**
13265                  * Array of callback functions for row created function
13266                  *  @type array
13267                  *  @default []
13268                  */
13269                 "aoRowCreatedCallback": [],
13270         
13271                 /**
13272                  * Callback functions for just before the table is redrawn. A return of
13273                  * false will be used to cancel the draw.
13274                  *  @type array
13275                  *  @default []
13276                  */
13277                 "aoPreDrawCallback": [],
13278         
13279                 /**
13280                  * Callback functions for when the table has been initialised.
13281                  *  @type array
13282                  *  @default []
13283                  */
13284                 "aoInitComplete": [],
13285         
13286         
13287                 /**
13288                  * Callbacks for modifying the settings to be stored for state saving, prior to
13289                  * saving state.
13290                  *  @type array
13291                  *  @default []
13292                  */
13293                 "aoStateSaveParams": [],
13294         
13295                 /**
13296                  * Callbacks for modifying the settings that have been stored for state saving
13297                  * prior to using the stored values to restore the state.
13298                  *  @type array
13299                  *  @default []
13300                  */
13301                 "aoStateLoadParams": [],
13302         
13303                 /**
13304                  * Callbacks for operating on the settings object once the saved state has been
13305                  * loaded
13306                  *  @type array
13307                  *  @default []
13308                  */
13309                 "aoStateLoaded": [],
13310         
13311                 /**
13312                  * Cache the table ID for quick access
13313                  *  @type string
13314                  *  @default <i>Empty string</i>
13315                  */
13316                 "sTableId": "",
13317         
13318                 /**
13319                  * The TABLE node for the main table
13320                  *  @type node
13321                  *  @default null
13322                  */
13323                 "nTable": null,
13324         
13325                 /**
13326                  * Permanent ref to the thead element
13327                  *  @type node
13328                  *  @default null
13329                  */
13330                 "nTHead": null,
13331         
13332                 /**
13333                  * Permanent ref to the tfoot element - if it exists
13334                  *  @type node
13335                  *  @default null
13336                  */
13337                 "nTFoot": null,
13338         
13339                 /**
13340                  * Permanent ref to the tbody element
13341                  *  @type node
13342                  *  @default null
13343                  */
13344                 "nTBody": null,
13345         
13346                 /**
13347                  * Cache the wrapper node (contains all DataTables controlled elements)
13348                  *  @type node
13349                  *  @default null
13350                  */
13351                 "nTableWrapper": null,
13352         
13353                 /**
13354                  * Indicate if when using server-side processing the loading of data
13355                  * should be deferred until the second draw.
13356                  * Note that this parameter will be set by the initialisation routine. To
13357                  * set a default use {@link DataTable.defaults}.
13358                  *  @type boolean
13359                  *  @default false
13360                  */
13361                 "bDeferLoading": false,
13362         
13363                 /**
13364                  * Indicate if all required information has been read in
13365                  *  @type boolean
13366                  *  @default false
13367                  */
13368                 "bInitialised": false,
13369         
13370                 /**
13371                  * Information about open rows. Each object in the array has the parameters
13372                  * 'nTr' and 'nParent'
13373                  *  @type array
13374                  *  @default []
13375                  */
13376                 "aoOpenRows": [],
13377         
13378                 /**
13379                  * Dictate the positioning of DataTables' control elements - see
13380                  * {@link DataTable.model.oInit.sDom}.
13381                  * Note that this parameter will be set by the initialisation routine. To
13382                  * set a default use {@link DataTable.defaults}.
13383                  *  @type string
13384                  *  @default null
13385                  */
13386                 "sDom": null,
13387         
13388                 /**
13389                  * Search delay (in mS)
13390                  *  @type integer
13391                  *  @default null
13392                  */
13393                 "searchDelay": null,
13394         
13395                 /**
13396                  * Which type of pagination should be used.
13397                  * Note that this parameter will be set by the initialisation routine. To
13398                  * set a default use {@link DataTable.defaults}.
13399                  *  @type string
13400                  *  @default two_button
13401                  */
13402                 "sPaginationType": "two_button",
13403         
13404                 /**
13405                  * The state duration (for `stateSave`) in seconds.
13406                  * Note that this parameter will be set by the initialisation routine. To
13407                  * set a default use {@link DataTable.defaults}.
13408                  *  @type int
13409                  *  @default 0
13410                  */
13411                 "iStateDuration": 0,
13412         
13413                 /**
13414                  * Array of callback functions for state saving. Each array element is an
13415                  * object with the following parameters:
13416                  *   <ul>
13417                  *     <li>function:fn - function to call. Takes two parameters, oSettings
13418                  *       and the JSON string to save that has been thus far created. Returns
13419                  *       a JSON string to be inserted into a json object
13420                  *       (i.e. '"param": [ 0, 1, 2]')</li>
13421                  *     <li>string:sName - name of callback</li>
13422                  *   </ul>
13423                  *  @type array
13424                  *  @default []
13425                  */
13426                 "aoStateSave": [],
13427         
13428                 /**
13429                  * Array of callback functions for state loading. Each array element is an
13430                  * object with the following parameters:
13431                  *   <ul>
13432                  *     <li>function:fn - function to call. Takes two parameters, oSettings
13433                  *       and the object stored. May return false to cancel state loading</li>
13434                  *     <li>string:sName - name of callback</li>
13435                  *   </ul>
13436                  *  @type array
13437                  *  @default []
13438                  */
13439                 "aoStateLoad": [],
13440         
13441                 /**
13442                  * State that was saved. Useful for back reference
13443                  *  @type object
13444                  *  @default null
13445                  */
13446                 "oSavedState": null,
13447         
13448                 /**
13449                  * State that was loaded. Useful for back reference
13450                  *  @type object
13451                  *  @default null
13452                  */
13453                 "oLoadedState": null,
13454         
13455                 /**
13456                  * Source url for AJAX data for the table.
13457                  * Note that this parameter will be set by the initialisation routine. To
13458                  * set a default use {@link DataTable.defaults}.
13459                  *  @type string
13460                  *  @default null
13461                  */
13462                 "sAjaxSource": null,
13463         
13464                 /**
13465                  * Property from a given object from which to read the table data from. This
13466                  * can be an empty string (when not server-side processing), in which case
13467                  * it is  assumed an an array is given directly.
13468                  * Note that this parameter will be set by the initialisation routine. To
13469                  * set a default use {@link DataTable.defaults}.
13470                  *  @type string
13471                  */
13472                 "sAjaxDataProp": null,
13473         
13474                 /**
13475                  * Note if draw should be blocked while getting data
13476                  *  @type boolean
13477                  *  @default true
13478                  */
13479                 "bAjaxDataGet": true,
13480         
13481                 /**
13482                  * The last jQuery XHR object that was used for server-side data gathering.
13483                  * This can be used for working with the XHR information in one of the
13484                  * callbacks
13485                  *  @type object
13486                  *  @default null
13487                  */
13488                 "jqXHR": null,
13489         
13490                 /**
13491                  * JSON returned from the server in the last Ajax request
13492                  *  @type object
13493                  *  @default undefined
13494                  */
13495                 "json": undefined,
13496         
13497                 /**
13498                  * Data submitted as part of the last Ajax request
13499                  *  @type object
13500                  *  @default undefined
13501                  */
13502                 "oAjaxData": undefined,
13503         
13504                 /**
13505                  * Function to get the server-side data.
13506                  * Note that this parameter will be set by the initialisation routine. To
13507                  * set a default use {@link DataTable.defaults}.
13508                  *  @type function
13509                  */
13510                 "fnServerData": null,
13511         
13512                 /**
13513                  * Functions which are called prior to sending an Ajax request so extra
13514                  * parameters can easily be sent to the server
13515                  *  @type array
13516                  *  @default []
13517                  */
13518                 "aoServerParams": [],
13519         
13520                 /**
13521                  * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13522                  * required).
13523                  * Note that this parameter will be set by the initialisation routine. To
13524                  * set a default use {@link DataTable.defaults}.
13525                  *  @type string
13526                  */
13527                 "sServerMethod": null,
13528         
13529                 /**
13530                  * Format numbers for display.
13531                  * Note that this parameter will be set by the initialisation routine. To
13532                  * set a default use {@link DataTable.defaults}.
13533                  *  @type function
13534                  */
13535                 "fnFormatNumber": null,
13536         
13537                 /**
13538                  * List of options that can be used for the user selectable length menu.
13539                  * Note that this parameter will be set by the initialisation routine. To
13540                  * set a default use {@link DataTable.defaults}.
13541                  *  @type array
13542                  *  @default []
13543                  */
13544                 "aLengthMenu": null,
13545         
13546                 /**
13547                  * Counter for the draws that the table does. Also used as a tracker for
13548                  * server-side processing
13549                  *  @type int
13550                  *  @default 0
13551                  */
13552                 "iDraw": 0,
13553         
13554                 /**
13555                  * Indicate if a redraw is being done - useful for Ajax
13556                  *  @type boolean
13557                  *  @default false
13558                  */
13559                 "bDrawing": false,
13560         
13561                 /**
13562                  * Draw index (iDraw) of the last error when parsing the returned data
13563                  *  @type int
13564                  *  @default -1
13565                  */
13566                 "iDrawError": -1,
13567         
13568                 /**
13569                  * Paging display length
13570                  *  @type int
13571                  *  @default 10
13572                  */
13573                 "_iDisplayLength": 10,
13574         
13575                 /**
13576                  * Paging start point - aiDisplay index
13577                  *  @type int
13578                  *  @default 0
13579                  */
13580                 "_iDisplayStart": 0,
13581         
13582                 /**
13583                  * Server-side processing - number of records in the result set
13584                  * (i.e. before filtering), Use fnRecordsTotal rather than
13585                  * this property to get the value of the number of records, regardless of
13586                  * the server-side processing setting.
13587                  *  @type int
13588                  *  @default 0
13589                  *  @private
13590                  */
13591                 "_iRecordsTotal": 0,
13592         
13593                 /**
13594                  * Server-side processing - number of records in the current display set
13595                  * (i.e. after filtering). Use fnRecordsDisplay rather than
13596                  * this property to get the value of the number of records, regardless of
13597                  * the server-side processing setting.
13598                  *  @type boolean
13599                  *  @default 0
13600                  *  @private
13601                  */
13602                 "_iRecordsDisplay": 0,
13603         
13604                 /**
13605                  * Flag to indicate if jQuery UI marking and classes should be used.
13606                  * Note that this parameter will be set by the initialisation routine. To
13607                  * set a default use {@link DataTable.defaults}.
13608                  *  @type boolean
13609                  */
13610                 "bJUI": null,
13611         
13612                 /**
13613                  * The classes to use for the table
13614                  *  @type object
13615                  *  @default {}
13616                  */
13617                 "oClasses": {},
13618         
13619                 /**
13620                  * Flag attached to the settings object so you can check in the draw
13621                  * callback if filtering has been done in the draw. Deprecated in favour of
13622                  * events.
13623                  *  @type boolean
13624                  *  @default false
13625                  *  @deprecated
13626                  */
13627                 "bFiltered": false,
13628         
13629                 /**
13630                  * Flag attached to the settings object so you can check in the draw
13631                  * callback if sorting has been done in the draw. Deprecated in favour of
13632                  * events.
13633                  *  @type boolean
13634                  *  @default false
13635                  *  @deprecated
13636                  */
13637                 "bSorted": false,
13638         
13639                 /**
13640                  * Indicate that if multiple rows are in the header and there is more than
13641                  * one unique cell per column, if the top one (true) or bottom one (false)
13642                  * should be used for sorting / title by DataTables.
13643                  * Note that this parameter will be set by the initialisation routine. To
13644                  * set a default use {@link DataTable.defaults}.
13645                  *  @type boolean
13646                  */
13647                 "bSortCellsTop": null,
13648         
13649                 /**
13650                  * Initialisation object that is used for the table
13651                  *  @type object
13652                  *  @default null
13653                  */
13654                 "oInit": null,
13655         
13656                 /**
13657                  * Destroy callback functions - for plug-ins to attach themselves to the
13658                  * destroy so they can clean up markup and events.
13659                  *  @type array
13660                  *  @default []
13661                  */
13662                 "aoDestroyCallback": [],
13663         
13664         
13665                 /**
13666                  * Get the number of records in the current record set, before filtering
13667                  *  @type function
13668                  */
13669                 "fnRecordsTotal": function ()
13670                 {
13671                         return _fnDataSource( this ) == 'ssp' ?
13672                                 this._iRecordsTotal * 1 :
13673                                 this.aiDisplayMaster.length;
13674                 },
13675         
13676                 /**
13677                  * Get the number of records in the current record set, after filtering
13678                  *  @type function
13679                  */
13680                 "fnRecordsDisplay": function ()
13681                 {
13682                         return _fnDataSource( this ) == 'ssp' ?
13683                                 this._iRecordsDisplay * 1 :
13684                                 this.aiDisplay.length;
13685                 },
13686         
13687                 /**
13688                  * Get the display end point - aiDisplay index
13689                  *  @type function
13690                  */
13691                 "fnDisplayEnd": function ()
13692                 {
13693                         var
13694                                 len      = this._iDisplayLength,
13695                                 start    = this._iDisplayStart,
13696                                 calc     = start + len,
13697                                 records  = this.aiDisplay.length,
13698                                 features = this.oFeatures,
13699                                 paginate = features.bPaginate;
13700         
13701                         if ( features.bServerSide ) {
13702                                 return paginate === false || len === -1 ?
13703                                         start + records :
13704                                         Math.min( start+len, this._iRecordsDisplay );
13705                         }
13706                         else {
13707                                 return ! paginate || calc>records || len===-1 ?
13708                                         records :
13709                                         calc;
13710                         }
13711                 },
13712         
13713                 /**
13714                  * The DataTables object for this table
13715                  *  @type object
13716                  *  @default null
13717                  */
13718                 "oInstance": null,
13719         
13720                 /**
13721                  * Unique identifier for each instance of the DataTables object. If there
13722                  * is an ID on the table node, then it takes that value, otherwise an
13723                  * incrementing internal counter is used.
13724                  *  @type string
13725                  *  @default null
13726                  */
13727                 "sInstance": null,
13728         
13729                 /**
13730                  * tabindex attribute value that is added to DataTables control elements, allowing
13731                  * keyboard navigation of the table and its controls.
13732                  */
13733                 "iTabIndex": 0,
13734         
13735                 /**
13736                  * DIV container for the footer scrolling table if scrolling
13737                  */
13738                 "nScrollHead": null,
13739         
13740                 /**
13741                  * DIV container for the footer scrolling table if scrolling
13742                  */
13743                 "nScrollFoot": null,
13744         
13745                 /**
13746                  * Last applied sort
13747                  *  @type array
13748                  *  @default []
13749                  */
13750                 "aLastSort": [],
13751         
13752                 /**
13753                  * Stored plug-in instances
13754                  *  @type object
13755                  *  @default {}
13756                  */
13757                 "oPlugins": {},
13758         
13759                 /**
13760                  * Function used to get a row's id from the row's data
13761                  *  @type function
13762                  *  @default null
13763                  */
13764                 "rowIdFn": null,
13765         
13766                 /**
13767                  * Data location where to store a row's id
13768                  *  @type string
13769                  *  @default null
13770                  */
13771                 "rowId": null
13772         };
13774         /**
13775          * Extension object for DataTables that is used to provide all extension
13776          * options.
13777          *
13778          * Note that the `DataTable.ext` object is available through
13779          * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13780          * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13781          *  @namespace
13782          *  @extends DataTable.models.ext
13783          */
13784         
13785         
13786         /**
13787          * DataTables extensions
13788          * 
13789          * This namespace acts as a collection area for plug-ins that can be used to
13790          * extend DataTables capabilities. Indeed many of the build in methods
13791          * use this method to provide their own capabilities (sorting methods for
13792          * example).
13793          *
13794          * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13795          * reasons
13796          *
13797          *  @namespace
13798          */
13799         DataTable.ext = _ext = {
13800                 /**
13801                  * Buttons. For use with the Buttons extension for DataTables. This is
13802                  * defined here so other extensions can define buttons regardless of load
13803                  * order. It is _not_ used by DataTables core.
13804                  *
13805                  *  @type object
13806                  *  @default {}
13807                  */
13808                 buttons: {},
13809         
13810         
13811                 /**
13812                  * Element class names
13813                  *
13814                  *  @type object
13815                  *  @default {}
13816                  */
13817                 classes: {},
13818         
13819         
13820                 /**
13821                  * DataTables build type (expanded by the download builder)
13822                  *
13823                  *  @type string
13824                  */
13825                 builder: "-source-",
13826         
13827         
13828                 /**
13829                  * Error reporting.
13830                  * 
13831                  * How should DataTables report an error. Can take the value 'alert',
13832                  * 'throw', 'none' or a function.
13833                  *
13834                  *  @type string|function
13835                  *  @default alert
13836                  */
13837                 errMode: "alert",
13838         
13839         
13840                 /**
13841                  * Feature plug-ins.
13842                  * 
13843                  * This is an array of objects which describe the feature plug-ins that are
13844                  * available to DataTables. These feature plug-ins are then available for
13845                  * use through the `dom` initialisation option.
13846                  * 
13847                  * Each feature plug-in is described by an object which must have the
13848                  * following properties:
13849                  * 
13850                  * * `fnInit` - function that is used to initialise the plug-in,
13851                  * * `cFeature` - a character so the feature can be enabled by the `dom`
13852                  *   instillation option. This is case sensitive.
13853                  *
13854                  * The `fnInit` function has the following input parameters:
13855                  *
13856                  * 1. `{object}` DataTables settings object: see
13857                  *    {@link DataTable.models.oSettings}
13858                  *
13859                  * And the following return is expected:
13860                  * 
13861                  * * {node|null} The element which contains your feature. Note that the
13862                  *   return may also be void if your plug-in does not require to inject any
13863                  *   DOM elements into DataTables control (`dom`) - for example this might
13864                  *   be useful when developing a plug-in which allows table control via
13865                  *   keyboard entry
13866                  *
13867                  *  @type array
13868                  *
13869                  *  @example
13870                  *    $.fn.dataTable.ext.features.push( {
13871                  *      "fnInit": function( oSettings ) {
13872                  *        return new TableTools( { "oDTSettings": oSettings } );
13873                  *      },
13874                  *      "cFeature": "T"
13875                  *    } );
13876                  */
13877                 feature: [],
13878         
13879         
13880                 /**
13881                  * Row searching.
13882                  * 
13883                  * This method of searching is complimentary to the default type based
13884                  * searching, and a lot more comprehensive as it allows you complete control
13885                  * over the searching logic. Each element in this array is a function
13886                  * (parameters described below) that is called for every row in the table,
13887                  * and your logic decides if it should be included in the searching data set
13888                  * or not.
13889                  *
13890                  * Searching functions have the following input parameters:
13891                  *
13892                  * 1. `{object}` DataTables settings object: see
13893                  *    {@link DataTable.models.oSettings}
13894                  * 2. `{array|object}` Data for the row to be processed (same as the
13895                  *    original format that was passed in as the data source, or an array
13896                  *    from a DOM data source
13897                  * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13898                  *    can be useful to retrieve the `TR` element if you need DOM interaction.
13899                  *
13900                  * And the following return is expected:
13901                  *
13902                  * * {boolean} Include the row in the searched result set (true) or not
13903                  *   (false)
13904                  *
13905                  * Note that as with the main search ability in DataTables, technically this
13906                  * is "filtering", since it is subtractive. However, for consistency in
13907                  * naming we call it searching here.
13908                  *
13909                  *  @type array
13910                  *  @default []
13911                  *
13912                  *  @example
13913                  *    // The following example shows custom search being applied to the
13914                  *    // fourth column (i.e. the data[3] index) based on two input values
13915                  *    // from the end-user, matching the data in a certain range.
13916                  *    $.fn.dataTable.ext.search.push(
13917                  *      function( settings, data, dataIndex ) {
13918                  *        var min = document.getElementById('min').value * 1;
13919                  *        var max = document.getElementById('max').value * 1;
13920                  *        var version = data[3] == "-" ? 0 : data[3]*1;
13921                  *
13922                  *        if ( min == "" && max == "" ) {
13923                  *          return true;
13924                  *        }
13925                  *        else if ( min == "" && version < max ) {
13926                  *          return true;
13927                  *        }
13928                  *        else if ( min < version && "" == max ) {
13929                  *          return true;
13930                  *        }
13931                  *        else if ( min < version && version < max ) {
13932                  *          return true;
13933                  *        }
13934                  *        return false;
13935                  *      }
13936                  *    );
13937                  */
13938                 search: [],
13939         
13940         
13941                 /**
13942                  * Selector extensions
13943                  *
13944                  * The `selector` option can be used to extend the options available for the
13945                  * selector modifier options (`selector-modifier` object data type) that
13946                  * each of the three built in selector types offer (row, column and cell +
13947                  * their plural counterparts). For example the Select extension uses this
13948                  * mechanism to provide an option to select only rows, columns and cells
13949                  * that have been marked as selected by the end user (`{selected: true}`),
13950                  * which can be used in conjunction with the existing built in selector
13951                  * options.
13952                  *
13953                  * Each property is an array to which functions can be pushed. The functions
13954                  * take three attributes:
13955                  *
13956                  * * Settings object for the host table
13957                  * * Options object (`selector-modifier` object type)
13958                  * * Array of selected item indexes
13959                  *
13960                  * The return is an array of the resulting item indexes after the custom
13961                  * selector has been applied.
13962                  *
13963                  *  @type object
13964                  */
13965                 selector: {
13966                         cell: [],
13967                         column: [],
13968                         row: []
13969                 },
13970         
13971         
13972                 /**
13973                  * Internal functions, exposed for used in plug-ins.
13974                  * 
13975                  * Please note that you should not need to use the internal methods for
13976                  * anything other than a plug-in (and even then, try to avoid if possible).
13977                  * The internal function may change between releases.
13978                  *
13979                  *  @type object
13980                  *  @default {}
13981                  */
13982                 internal: {},
13983         
13984         
13985                 /**
13986                  * Legacy configuration options. Enable and disable legacy options that
13987                  * are available in DataTables.
13988                  *
13989                  *  @type object
13990                  */
13991                 legacy: {
13992                         /**
13993                          * Enable / disable DataTables 1.9 compatible server-side processing
13994                          * requests
13995                          *
13996                          *  @type boolean
13997                          *  @default null
13998                          */
13999                         ajax: null
14000                 },
14001         
14002         
14003                 /**
14004                  * Pagination plug-in methods.
14005                  * 
14006                  * Each entry in this object is a function and defines which buttons should
14007                  * be shown by the pagination rendering method that is used for the table:
14008                  * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14009                  * buttons are displayed in the document, while the functions here tell it
14010                  * what buttons to display. This is done by returning an array of button
14011                  * descriptions (what each button will do).
14012                  *
14013                  * Pagination types (the four built in options and any additional plug-in
14014                  * options defined here) can be used through the `paginationType`
14015                  * initialisation parameter.
14016                  *
14017                  * The functions defined take two parameters:
14018                  *
14019                  * 1. `{int} page` The current page index
14020                  * 2. `{int} pages` The number of pages in the table
14021                  *
14022                  * Each function is expected to return an array where each element of the
14023                  * array can be one of:
14024                  *
14025                  * * `first` - Jump to first page when activated
14026                  * * `last` - Jump to last page when activated
14027                  * * `previous` - Show previous page when activated
14028                  * * `next` - Show next page when activated
14029                  * * `{int}` - Show page of the index given
14030                  * * `{array}` - A nested array containing the above elements to add a
14031                  *   containing 'DIV' element (might be useful for styling).
14032                  *
14033                  * Note that DataTables v1.9- used this object slightly differently whereby
14034                  * an object with two functions would be defined for each plug-in. That
14035                  * ability is still supported by DataTables 1.10+ to provide backwards
14036                  * compatibility, but this option of use is now decremented and no longer
14037                  * documented in DataTables 1.10+.
14038                  *
14039                  *  @type object
14040                  *  @default {}
14041                  *
14042                  *  @example
14043                  *    // Show previous, next and current page buttons only
14044                  *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14045                  *      return [ 'previous', page, 'next' ];
14046                  *    };
14047                  */
14048                 pager: {},
14049         
14050         
14051                 renderer: {
14052                         pageButton: {},
14053                         header: {}
14054                 },
14055         
14056         
14057                 /**
14058                  * Ordering plug-ins - custom data source
14059                  * 
14060                  * The extension options for ordering of data available here is complimentary
14061                  * to the default type based ordering that DataTables typically uses. It
14062                  * allows much greater control over the the data that is being used to
14063                  * order a column, but is necessarily therefore more complex.
14064                  * 
14065                  * This type of ordering is useful if you want to do ordering based on data
14066                  * live from the DOM (for example the contents of an 'input' element) rather
14067                  * than just the static string that DataTables knows of.
14068                  * 
14069                  * The way these plug-ins work is that you create an array of the values you
14070                  * wish to be ordering for the column in question and then return that
14071                  * array. The data in the array much be in the index order of the rows in
14072                  * the table (not the currently ordering order!). Which order data gathering
14073                  * function is run here depends on the `dt-init columns.orderDataType`
14074                  * parameter that is used for the column (if any).
14075                  *
14076                  * The functions defined take two parameters:
14077                  *
14078                  * 1. `{object}` DataTables settings object: see
14079                  *    {@link DataTable.models.oSettings}
14080                  * 2. `{int}` Target column index
14081                  *
14082                  * Each function is expected to return an array:
14083                  *
14084                  * * `{array}` Data for the column to be ordering upon
14085                  *
14086                  *  @type array
14087                  *
14088                  *  @example
14089                  *    // Ordering using `input` node values
14090                  *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
14091                  *    {
14092                  *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14093                  *        return $('input', td).val();
14094                  *      } );
14095                  *    }
14096                  */
14097                 order: {},
14098         
14099         
14100                 /**
14101                  * Type based plug-ins.
14102                  *
14103                  * Each column in DataTables has a type assigned to it, either by automatic
14104                  * detection or by direct assignment using the `type` option for the column.
14105                  * The type of a column will effect how it is ordering and search (plug-ins
14106                  * can also make use of the column type if required).
14107                  *
14108                  * @namespace
14109                  */
14110                 type: {
14111                         /**
14112                          * Type detection functions.
14113                          *
14114                          * The functions defined in this object are used to automatically detect
14115                          * a column's type, making initialisation of DataTables super easy, even
14116                          * when complex data is in the table.
14117                          *
14118                          * The functions defined take two parameters:
14119                          *
14120                      *  1. `{*}` Data from the column cell to be analysed
14121                      *  2. `{settings}` DataTables settings object. This can be used to
14122                      *     perform context specific type detection - for example detection
14123                      *     based on language settings such as using a comma for a decimal
14124                      *     place. Generally speaking the options from the settings will not
14125                      *     be required
14126                          *
14127                          * Each function is expected to return:
14128                          *
14129                          * * `{string|null}` Data type detected, or null if unknown (and thus
14130                          *   pass it on to the other type detection functions.
14131                          *
14132                          *  @type array
14133                          *
14134                          *  @example
14135                          *    // Currency type detection plug-in:
14136                          *    $.fn.dataTable.ext.type.detect.push(
14137                          *      function ( data, settings ) {
14138                          *        // Check the numeric part
14139                          *        if ( ! $.isNumeric( data.substring(1) ) ) {
14140                          *          return null;
14141                          *        }
14142                          *
14143                          *        // Check prefixed by currency
14144                          *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14145                          *          return 'currency';
14146                          *        }
14147                          *        return null;
14148                          *      }
14149                          *    );
14150                          */
14151                         detect: [],
14152         
14153         
14154                         /**
14155                          * Type based search formatting.
14156                          *
14157                          * The type based searching functions can be used to pre-format the
14158                          * data to be search on. For example, it can be used to strip HTML
14159                          * tags or to de-format telephone numbers for numeric only searching.
14160                          *
14161                          * Note that is a search is not defined for a column of a given type,
14162                          * no search formatting will be performed.
14163                          * 
14164                          * Pre-processing of searching data plug-ins - When you assign the sType
14165                          * for a column (or have it automatically detected for you by DataTables
14166                          * or a type detection plug-in), you will typically be using this for
14167                          * custom sorting, but it can also be used to provide custom searching
14168                          * by allowing you to pre-processing the data and returning the data in
14169                          * the format that should be searched upon. This is done by adding
14170                          * functions this object with a parameter name which matches the sType
14171                          * for that target column. This is the corollary of <i>afnSortData</i>
14172                          * for searching data.
14173                          *
14174                          * The functions defined take a single parameter:
14175                          *
14176                      *  1. `{*}` Data from the column cell to be prepared for searching
14177                          *
14178                          * Each function is expected to return:
14179                          *
14180                          * * `{string|null}` Formatted string that will be used for the searching.
14181                          *
14182                          *  @type object
14183                          *  @default {}
14184                          *
14185                          *  @example
14186                          *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14187                          *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14188                          *    }
14189                          */
14190                         search: {},
14191         
14192         
14193                         /**
14194                          * Type based ordering.
14195                          *
14196                          * The column type tells DataTables what ordering to apply to the table
14197                          * when a column is sorted upon. The order for each type that is defined,
14198                          * is defined by the functions available in this object.
14199                          *
14200                          * Each ordering option can be described by three properties added to
14201                          * this object:
14202                          *
14203                          * * `{type}-pre` - Pre-formatting function
14204                          * * `{type}-asc` - Ascending order function
14205                          * * `{type}-desc` - Descending order function
14206                          *
14207                          * All three can be used together, only `{type}-pre` or only
14208                          * `{type}-asc` and `{type}-desc` together. It is generally recommended
14209                          * that only `{type}-pre` is used, as this provides the optimal
14210                          * implementation in terms of speed, although the others are provided
14211                          * for compatibility with existing Javascript sort functions.
14212                          *
14213                          * `{type}-pre`: Functions defined take a single parameter:
14214                          *
14215                      *  1. `{*}` Data from the column cell to be prepared for ordering
14216                          *
14217                          * And return:
14218                          *
14219                          * * `{*}` Data to be sorted upon
14220                          *
14221                          * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14222                          * functions, taking two parameters:
14223                          *
14224                      *  1. `{*}` Data to compare to the second parameter
14225                      *  2. `{*}` Data to compare to the first parameter
14226                          *
14227                          * And returning:
14228                          *
14229                          * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14230                          *   than the second parameter, ===0 if the two parameters are equal and
14231                          *   >0 if the first parameter should be sorted height than the second
14232                          *   parameter.
14233                          * 
14234                          *  @type object
14235                          *  @default {}
14236                          *
14237                          *  @example
14238                          *    // Numeric ordering of formatted numbers with a pre-formatter
14239                          *    $.extend( $.fn.dataTable.ext.type.order, {
14240                          *      "string-pre": function(x) {
14241                          *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14242                          *        return parseFloat( a );
14243                          *      }
14244                          *    } );
14245                          *
14246                          *  @example
14247                          *    // Case-sensitive string ordering, with no pre-formatting method
14248                          *    $.extend( $.fn.dataTable.ext.order, {
14249                          *      "string-case-asc": function(x,y) {
14250                          *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14251                          *      },
14252                          *      "string-case-desc": function(x,y) {
14253                          *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14254                          *      }
14255                          *    } );
14256                          */
14257                         order: {}
14258                 },
14259         
14260                 /**
14261                  * Unique DataTables instance counter
14262                  *
14263                  * @type int
14264                  * @private
14265                  */
14266                 _unique: 0,
14267         
14268         
14269                 //
14270                 // Depreciated
14271                 // The following properties are retained for backwards compatiblity only.
14272                 // The should not be used in new projects and will be removed in a future
14273                 // version
14274                 //
14275         
14276                 /**
14277                  * Version check function.
14278                  *  @type function
14279                  *  @depreciated Since 1.10
14280                  */
14281                 fnVersionCheck: DataTable.fnVersionCheck,
14282         
14283         
14284                 /**
14285                  * Index for what 'this' index API functions should use
14286                  *  @type int
14287                  *  @deprecated Since v1.10
14288                  */
14289                 iApiIndex: 0,
14290         
14291         
14292                 /**
14293                  * jQuery UI class container
14294                  *  @type object
14295                  *  @deprecated Since v1.10
14296                  */
14297                 oJUIClasses: {},
14298         
14299         
14300                 /**
14301                  * Software version
14302                  *  @type string
14303                  *  @deprecated Since v1.10
14304                  */
14305                 sVersion: DataTable.version
14306         };
14307         
14308         
14309         //
14310         // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14311         //
14312         $.extend( _ext, {
14313                 afnFiltering: _ext.search,
14314                 aTypes:       _ext.type.detect,
14315                 ofnSearch:    _ext.type.search,
14316                 oSort:        _ext.type.order,
14317                 afnSortData:  _ext.order,
14318                 aoFeatures:   _ext.feature,
14319                 oApi:         _ext.internal,
14320                 oStdClasses:  _ext.classes,
14321                 oPagination:  _ext.pager
14322         } );
14323         
14324         
14325         $.extend( DataTable.ext.classes, {
14326                 "sTable": "dataTable",
14327                 "sNoFooter": "no-footer",
14328         
14329                 /* Paging buttons */
14330                 "sPageButton": "paginate_button",
14331                 "sPageButtonActive": "current",
14332                 "sPageButtonDisabled": "disabled",
14333         
14334                 /* Striping classes */
14335                 "sStripeOdd": "odd",
14336                 "sStripeEven": "even",
14337         
14338                 /* Empty row */
14339                 "sRowEmpty": "dataTables_empty",
14340         
14341                 /* Features */
14342                 "sWrapper": "dataTables_wrapper",
14343                 "sFilter": "dataTables_filter",
14344                 "sInfo": "dataTables_info",
14345                 "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14346                 "sLength": "dataTables_length",
14347                 "sProcessing": "dataTables_processing",
14348         
14349                 /* Sorting */
14350                 "sSortAsc": "sorting_asc",
14351                 "sSortDesc": "sorting_desc",
14352                 "sSortable": "sorting", /* Sortable in both directions */
14353                 "sSortableAsc": "sorting_asc_disabled",
14354                 "sSortableDesc": "sorting_desc_disabled",
14355                 "sSortableNone": "sorting_disabled",
14356                 "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14357         
14358                 /* Filtering */
14359                 "sFilterInput": "",
14360         
14361                 /* Page length */
14362                 "sLengthSelect": "",
14363         
14364                 /* Scrolling */
14365                 "sScrollWrapper": "dataTables_scroll",
14366                 "sScrollHead": "dataTables_scrollHead",
14367                 "sScrollHeadInner": "dataTables_scrollHeadInner",
14368                 "sScrollBody": "dataTables_scrollBody",
14369                 "sScrollFoot": "dataTables_scrollFoot",
14370                 "sScrollFootInner": "dataTables_scrollFootInner",
14371         
14372                 /* Misc */
14373                 "sHeaderTH": "",
14374                 "sFooterTH": "",
14375         
14376                 // Deprecated
14377                 "sSortJUIAsc": "",
14378                 "sSortJUIDesc": "",
14379                 "sSortJUI": "",
14380                 "sSortJUIAscAllowed": "",
14381                 "sSortJUIDescAllowed": "",
14382                 "sSortJUIWrapper": "",
14383                 "sSortIcon": "",
14384                 "sJUIHeader": "",
14385                 "sJUIFooter": ""
14386         } );
14387         
14388         
14389         (function() {
14390         
14391         // Reused strings for better compression. Closure compiler appears to have a
14392         // weird edge case where it is trying to expand strings rather than use the
14393         // variable version. This results in about 200 bytes being added, for very
14394         // little preference benefit since it this run on script load only.
14395         var _empty = '';
14396         _empty = '';
14397         
14398         var _stateDefault = _empty + 'ui-state-default';
14399         var _sortIcon     = _empty + 'css_right ui-icon ui-icon-';
14400         var _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix';
14401         
14402         $.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, {
14403                 /* Full numbers paging buttons */
14404                 "sPageButton":         "fg-button ui-button "+_stateDefault,
14405                 "sPageButtonActive":   "ui-state-disabled",
14406                 "sPageButtonDisabled": "ui-state-disabled",
14407         
14408                 /* Features */
14409                 "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
14410                         "ui-buttonset-multi paging_", /* Note that the type is postfixed */
14411         
14412                 /* Sorting */
14413                 "sSortAsc":            _stateDefault+" sorting_asc",
14414                 "sSortDesc":           _stateDefault+" sorting_desc",
14415                 "sSortable":           _stateDefault+" sorting",
14416                 "sSortableAsc":        _stateDefault+" sorting_asc_disabled",
14417                 "sSortableDesc":       _stateDefault+" sorting_desc_disabled",
14418                 "sSortableNone":       _stateDefault+" sorting_disabled",
14419                 "sSortJUIAsc":         _sortIcon+"triangle-1-n",
14420                 "sSortJUIDesc":        _sortIcon+"triangle-1-s",
14421                 "sSortJUI":            _sortIcon+"carat-2-n-s",
14422                 "sSortJUIAscAllowed":  _sortIcon+"carat-1-n",
14423                 "sSortJUIDescAllowed": _sortIcon+"carat-1-s",
14424                 "sSortJUIWrapper":     "DataTables_sort_wrapper",
14425                 "sSortIcon":           "DataTables_sort_icon",
14426         
14427                 /* Scrolling */
14428                 "sScrollHead": "dataTables_scrollHead "+_stateDefault,
14429                 "sScrollFoot": "dataTables_scrollFoot "+_stateDefault,
14430         
14431                 /* Misc */
14432                 "sHeaderTH":  _stateDefault,
14433                 "sFooterTH":  _stateDefault,
14434                 "sJUIHeader": _headerFooter+" ui-corner-tl ui-corner-tr",
14435                 "sJUIFooter": _headerFooter+" ui-corner-bl ui-corner-br"
14436         } );
14437         
14438         }());
14439         
14440         
14441         
14442         var extPagination = DataTable.ext.pager;
14443         
14444         function _numbers ( page, pages ) {
14445                 var
14446                         numbers = [],
14447                         buttons = extPagination.numbers_length,
14448                         half = Math.floor( buttons / 2 ),
14449                         i = 1;
14450         
14451                 if ( pages <= buttons ) {
14452                         numbers = _range( 0, pages );
14453                 }
14454                 else if ( page <= half ) {
14455                         numbers = _range( 0, buttons-2 );
14456                         numbers.push( 'ellipsis' );
14457                         numbers.push( pages-1 );
14458                 }
14459                 else if ( page >= pages - 1 - half ) {
14460                         numbers = _range( pages-(buttons-2), pages );
14461                         numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14462                         numbers.splice( 0, 0, 0 );
14463                 }
14464                 else {
14465                         numbers = _range( page-half+2, page+half-1 );
14466                         numbers.push( 'ellipsis' );
14467                         numbers.push( pages-1 );
14468                         numbers.splice( 0, 0, 'ellipsis' );
14469                         numbers.splice( 0, 0, 0 );
14470                 }
14471         
14472                 numbers.DT_el = 'span';
14473                 return numbers;
14474         }
14475         
14476         
14477         $.extend( extPagination, {
14478                 simple: function ( page, pages ) {
14479                         return [ 'previous', 'next' ];
14480                 },
14481         
14482                 full: function ( page, pages ) {
14483                         return [  'first', 'previous', 'next', 'last' ];
14484                 },
14485         
14486                 numbers: function ( page, pages ) {
14487                         return [ _numbers(page, pages) ];
14488                 },
14489         
14490                 simple_numbers: function ( page, pages ) {
14491                         return [ 'previous', _numbers(page, pages), 'next' ];
14492                 },
14493         
14494                 full_numbers: function ( page, pages ) {
14495                         return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14496                 },
14497         
14498                 // For testing and plug-ins to use
14499                 _numbers: _numbers,
14500         
14501                 // Number of number buttons (including ellipsis) to show. _Must be odd!_
14502                 numbers_length: 7
14503         } );
14504         
14505         
14506         $.extend( true, DataTable.ext.renderer, {
14507                 pageButton: {
14508                         _: function ( settings, host, idx, buttons, page, pages ) {
14509                                 var classes = settings.oClasses;
14510                                 var lang = settings.oLanguage.oPaginate;
14511                                 var aria = settings.oLanguage.oAria.paginate || {};
14512                                 var btnDisplay, btnClass, counter=0;
14513         
14514                                 var attach = function( container, buttons ) {
14515                                         var i, ien, node, button;
14516                                         var clickHandler = function ( e ) {
14517                                                 _fnPageChange( settings, e.data.action, true );
14518                                         };
14519         
14520                                         for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14521                                                 button = buttons[i];
14522         
14523                                                 if ( $.isArray( button ) ) {
14524                                                         var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14525                                                                 .appendTo( container );
14526                                                         attach( inner, button );
14527                                                 }
14528                                                 else {
14529                                                         btnDisplay = null;
14530                                                         btnClass = '';
14531         
14532                                                         switch ( button ) {
14533                                                                 case 'ellipsis':
14534                                                                         container.append('<span class="ellipsis">&#x2026;</span>');
14535                                                                         break;
14536         
14537                                                                 case 'first':
14538                                                                         btnDisplay = lang.sFirst;
14539                                                                         btnClass = button + (page > 0 ?
14540                                                                                 '' : ' '+classes.sPageButtonDisabled);
14541                                                                         break;
14542         
14543                                                                 case 'previous':
14544                                                                         btnDisplay = lang.sPrevious;
14545                                                                         btnClass = button + (page > 0 ?
14546                                                                                 '' : ' '+classes.sPageButtonDisabled);
14547                                                                         break;
14548         
14549                                                                 case 'next':
14550                                                                         btnDisplay = lang.sNext;
14551                                                                         btnClass = button + (page < pages-1 ?
14552                                                                                 '' : ' '+classes.sPageButtonDisabled);
14553                                                                         break;
14554         
14555                                                                 case 'last':
14556                                                                         btnDisplay = lang.sLast;
14557                                                                         btnClass = button + (page < pages-1 ?
14558                                                                                 '' : ' '+classes.sPageButtonDisabled);
14559                                                                         break;
14560         
14561                                                                 default:
14562                                                                         btnDisplay = button + 1;
14563                                                                         btnClass = page === button ?
14564                                                                                 classes.sPageButtonActive : '';
14565                                                                         break;
14566                                                         }
14567         
14568                                                         if ( btnDisplay !== null ) {
14569                                                                 node = $('<a>', {
14570                                                                                 'class': classes.sPageButton+' '+btnClass,
14571                                                                                 'aria-controls': settings.sTableId,
14572                                                                                 'aria-label': aria[ button ],
14573                                                                                 'data-dt-idx': counter,
14574                                                                                 'tabindex': settings.iTabIndex,
14575                                                                                 'id': idx === 0 && typeof button === 'string' ?
14576                                                                                         settings.sTableId +'_'+ button :
14577                                                                                         null
14578                                                                         } )
14579                                                                         .html( btnDisplay )
14580                                                                         .appendTo( container );
14581         
14582                                                                 _fnBindAction(
14583                                                                         node, {action: button}, clickHandler
14584                                                                 );
14585         
14586                                                                 counter++;
14587                                                         }
14588                                                 }
14589                                         }
14590                                 };
14591         
14592                                 // IE9 throws an 'unknown error' if document.activeElement is used
14593                                 // inside an iframe or frame. Try / catch the error. Not good for
14594                                 // accessibility, but neither are frames.
14595                                 var activeEl;
14596         
14597                                 try {
14598                                         // Because this approach is destroying and recreating the paging
14599                                         // elements, focus is lost on the select button which is bad for
14600                                         // accessibility. So we want to restore focus once the draw has
14601                                         // completed
14602                                         activeEl = $(host).find(document.activeElement).data('dt-idx');
14603                                 }
14604                                 catch (e) {}
14605         
14606                                 attach( $(host).empty(), buttons );
14607         
14608                                 if ( activeEl ) {
14609                                         $(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14610                                 }
14611                         }
14612                 }
14613         } );
14614         
14615         
14616         
14617         // Built in type detection. See model.ext.aTypes for information about
14618         // what is required from this methods.
14619         $.extend( DataTable.ext.type.detect, [
14620                 // Plain numbers - first since V8 detects some plain numbers as dates
14621                 // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14622                 function ( d, settings )
14623                 {
14624                         var decimal = settings.oLanguage.sDecimal;
14625                         return _isNumber( d, decimal ) ? 'num'+decimal : null;
14626                 },
14627         
14628                 // Dates (only those recognised by the browser's Date.parse)
14629                 function ( d, settings )
14630                 {
14631                         // V8 will remove any unknown characters at the start and end of the
14632                         // expression, leading to false matches such as `$245.12` or `10%` being
14633                         // a valid date. See forum thread 18941 for detail.
14634                         if ( d && !(d instanceof Date) && ( ! _re_date_start.test(d) || ! _re_date_end.test(d) ) ) {
14635                                 return null;
14636                         }
14637                         var parsed = Date.parse(d);
14638                         return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14639                 },
14640         
14641                 // Formatted numbers
14642                 function ( d, settings )
14643                 {
14644                         var decimal = settings.oLanguage.sDecimal;
14645                         return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14646                 },
14647         
14648                 // HTML numeric
14649                 function ( d, settings )
14650                 {
14651                         var decimal = settings.oLanguage.sDecimal;
14652                         return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14653                 },
14654         
14655                 // HTML numeric, formatted
14656                 function ( d, settings )
14657                 {
14658                         var decimal = settings.oLanguage.sDecimal;
14659                         return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14660                 },
14661         
14662                 // HTML (this is strict checking - there must be html)
14663                 function ( d, settings )
14664                 {
14665                         return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14666                                 'html' : null;
14667                 }
14668         ] );
14669         
14670         
14671         
14672         // Filter formatting functions. See model.ext.ofnSearch for information about
14673         // what is required from these methods.
14674         // 
14675         // Note that additional search methods are added for the html numbers and
14676         // html formatted numbers by `_addNumericSort()` when we know what the decimal
14677         // place is
14678         
14679         
14680         $.extend( DataTable.ext.type.search, {
14681                 html: function ( data ) {
14682                         return _empty(data) ?
14683                                 data :
14684                                 typeof data === 'string' ?
14685                                         data
14686                                                 .replace( _re_new_lines, " " )
14687                                                 .replace( _re_html, "" ) :
14688                                         '';
14689                 },
14690         
14691                 string: function ( data ) {
14692                         return _empty(data) ?
14693                                 data :
14694                                 typeof data === 'string' ?
14695                                         data.replace( _re_new_lines, " " ) :
14696                                         data;
14697                 }
14698         } );
14699         
14700         
14701         
14702         var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14703                 if ( d !== 0 && (!d || d === '-') ) {
14704                         return -Infinity;
14705                 }
14706         
14707                 // If a decimal place other than `.` is used, it needs to be given to the
14708                 // function so we can detect it and replace with a `.` which is the only
14709                 // decimal place Javascript recognises - it is not locale aware.
14710                 if ( decimalPlace ) {
14711                         d = _numToDecimal( d, decimalPlace );
14712                 }
14713         
14714                 if ( d.replace ) {
14715                         if ( re1 ) {
14716                                 d = d.replace( re1, '' );
14717                         }
14718         
14719                         if ( re2 ) {
14720                                 d = d.replace( re2, '' );
14721                         }
14722                 }
14723         
14724                 return d * 1;
14725         };
14726         
14727         
14728         // Add the numeric 'deformatting' functions for sorting and search. This is done
14729         // in a function to provide an easy ability for the language options to add
14730         // additional methods if a non-period decimal place is used.
14731         function _addNumericSort ( decimalPlace ) {
14732                 $.each(
14733                         {
14734                                 // Plain numbers
14735                                 "num": function ( d ) {
14736                                         return __numericReplace( d, decimalPlace );
14737                                 },
14738         
14739                                 // Formatted numbers
14740                                 "num-fmt": function ( d ) {
14741                                         return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14742                                 },
14743         
14744                                 // HTML numeric
14745                                 "html-num": function ( d ) {
14746                                         return __numericReplace( d, decimalPlace, _re_html );
14747                                 },
14748         
14749                                 // HTML numeric, formatted
14750                                 "html-num-fmt": function ( d ) {
14751                                         return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14752                                 }
14753                         },
14754                         function ( key, fn ) {
14755                                 // Add the ordering method
14756                                 _ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14757         
14758                                 // For HTML types add a search formatter that will strip the HTML
14759                                 if ( key.match(/^html\-/) ) {
14760                                         _ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
14761                                 }
14762                         }
14763                 );
14764         }
14765         
14766         
14767         // Default sort methods
14768         $.extend( _ext.type.order, {
14769                 // Dates
14770                 "date-pre": function ( d ) {
14771                         return Date.parse( d ) || 0;
14772                 },
14773         
14774                 // html
14775                 "html-pre": function ( a ) {
14776                         return _empty(a) ?
14777                                 '' :
14778                                 a.replace ?
14779                                         a.replace( /<.*?>/g, "" ).toLowerCase() :
14780                                         a+'';
14781                 },
14782         
14783                 // string
14784                 "string-pre": function ( a ) {
14785                         // This is a little complex, but faster than always calling toString,
14786                         // http://jsperf.com/tostring-v-check
14787                         return _empty(a) ?
14788                                 '' :
14789                                 typeof a === 'string' ?
14790                                         a.toLowerCase() :
14791                                         ! a.toString ?
14792                                                 '' :
14793                                                 a.toString();
14794                 },
14795         
14796                 // string-asc and -desc are retained only for compatibility with the old
14797                 // sort methods
14798                 "string-asc": function ( x, y ) {
14799                         return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14800                 },
14801         
14802                 "string-desc": function ( x, y ) {
14803                         return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14804                 }
14805         } );
14806         
14807         
14808         // Numeric sorting types - order doesn't matter here
14809         _addNumericSort( '' );
14810         
14811         
14812         $.extend( true, DataTable.ext.renderer, {
14813                 header: {
14814                         _: function ( settings, cell, column, classes ) {
14815                                 // No additional mark-up required
14816                                 // Attach a sort listener to update on sort - note that using the
14817                                 // `DT` namespace will allow the event to be removed automatically
14818                                 // on destroy, while the `dt` namespaced event is the one we are
14819                                 // listening for
14820                                 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14821                                         if ( settings !== ctx ) { // need to check this this is the host
14822                                                 return;               // table, not a nested one
14823                                         }
14824         
14825                                         var colIdx = column.idx;
14826         
14827                                         cell
14828                                                 .removeClass(
14829                                                         column.sSortingClass +' '+
14830                                                         classes.sSortAsc +' '+
14831                                                         classes.sSortDesc
14832                                                 )
14833                                                 .addClass( columns[ colIdx ] == 'asc' ?
14834                                                         classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14835                                                                 classes.sSortDesc :
14836                                                                 column.sSortingClass
14837                                                 );
14838                                 } );
14839                         },
14840         
14841                         jqueryui: function ( settings, cell, column, classes ) {
14842                                 $('<div/>')
14843                                         .addClass( classes.sSortJUIWrapper )
14844                                         .append( cell.contents() )
14845                                         .append( $('<span/>')
14846                                                 .addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
14847                                         )
14848                                         .appendTo( cell );
14849         
14850                                 // Attach a sort listener to update on sort
14851                                 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14852                                         if ( settings !== ctx ) {
14853                                                 return;
14854                                         }
14855         
14856                                         var colIdx = column.idx;
14857         
14858                                         cell
14859                                                 .removeClass( classes.sSortAsc +" "+classes.sSortDesc )
14860                                                 .addClass( columns[ colIdx ] == 'asc' ?
14861                                                         classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14862                                                                 classes.sSortDesc :
14863                                                                 column.sSortingClass
14864                                                 );
14865         
14866                                         cell
14867                                                 .find( 'span.'+classes.sSortIcon )
14868                                                 .removeClass(
14869                                                         classes.sSortJUIAsc +" "+
14870                                                         classes.sSortJUIDesc +" "+
14871                                                         classes.sSortJUI +" "+
14872                                                         classes.sSortJUIAscAllowed +" "+
14873                                                         classes.sSortJUIDescAllowed
14874                                                 )
14875                                                 .addClass( columns[ colIdx ] == 'asc' ?
14876                                                         classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14877                                                                 classes.sSortJUIDesc :
14878                                                                 column.sSortingClassJUI
14879                                                 );
14880                                 } );
14881                         }
14882                 }
14883         } );
14884         
14885         /*
14886          * Public helper functions. These aren't used internally by DataTables, or
14887          * called by any of the options passed into DataTables, but they can be used
14888          * externally by developers working with DataTables. They are helper functions
14889          * to make working with DataTables a little bit easier.
14890          */
14891         
14892         var __htmlEscapeEntities = function ( d ) {
14893                 return typeof d === 'string' ?
14894                         d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') :
14895                         d;
14896         };
14897         
14898         /**
14899          * Helpers for `columns.render`.
14900          *
14901          * The options defined here can be used with the `columns.render` initialisation
14902          * option to provide a display renderer. The following functions are defined:
14903          *
14904          * * `number` - Will format numeric data (defined by `columns.data`) for
14905          *   display, retaining the original unformatted data for sorting and filtering.
14906          *   It takes 5 parameters:
14907          *   * `string` - Thousands grouping separator
14908          *   * `string` - Decimal point indicator
14909          *   * `integer` - Number of decimal points to show
14910          *   * `string` (optional) - Prefix.
14911          *   * `string` (optional) - Postfix (/suffix).
14912          * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
14913          *   parameters.
14914          *
14915          * @example
14916          *   // Column definition using the number renderer
14917          *   {
14918          *     data: "salary",
14919          *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14920          *   }
14921          *
14922          * @namespace
14923          */
14924         DataTable.render = {
14925                 number: function ( thousands, decimal, precision, prefix, postfix ) {
14926                         return {
14927                                 display: function ( d ) {
14928                                         if ( typeof d !== 'number' && typeof d !== 'string' ) {
14929                                                 return d;
14930                                         }
14931         
14932                                         var negative = d < 0 ? '-' : '';
14933                                         var flo = parseFloat( d );
14934         
14935                                         // If NaN then there isn't much formatting that we can do - just
14936                                         // return immediately, escaping any HTML (this was supposed to
14937                                         // be a number after all)
14938                                         if ( isNaN( flo ) ) {
14939                                                 return __htmlEscapeEntities( d );
14940                                         }
14941         
14942                                         d = Math.abs( flo );
14943         
14944                                         var intPart = parseInt( d, 10 );
14945                                         var floatPart = precision ?
14946                                                 decimal+(d - intPart).toFixed( precision ).substring( 2 ):
14947                                                 '';
14948         
14949                                         return negative + (prefix||'') +
14950                                                 intPart.toString().replace(
14951                                                         /\B(?=(\d{3})+(?!\d))/g, thousands
14952                                                 ) +
14953                                                 floatPart +
14954                                                 (postfix||'');
14955                                 }
14956                         };
14957                 },
14958         
14959                 text: function () {
14960                         return {
14961                                 display: __htmlEscapeEntities
14962                         };
14963                 }
14964         };
14965         
14966         
14967         /*
14968          * This is really a good bit rubbish this method of exposing the internal methods
14969          * publicly... - To be fixed in 2.0 using methods on the prototype
14970          */
14971         
14972         
14973         /**
14974          * Create a wrapper function for exporting an internal functions to an external API.
14975          *  @param {string} fn API function name
14976          *  @returns {function} wrapped function
14977          *  @memberof DataTable#internal
14978          */
14979         function _fnExternApiFunc (fn)
14980         {
14981                 return function() {
14982                         var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
14983                                 Array.prototype.slice.call(arguments)
14984                         );
14985                         return DataTable.ext.internal[fn].apply( this, args );
14986                 };
14987         }
14988         
14989         
14990         /**
14991          * Reference to internal functions for use by plug-in developers. Note that
14992          * these methods are references to internal functions and are considered to be
14993          * private. If you use these methods, be aware that they are liable to change
14994          * between versions.
14995          *  @namespace
14996          */
14997         $.extend( DataTable.ext.internal, {
14998                 _fnExternApiFunc: _fnExternApiFunc,
14999                 _fnBuildAjax: _fnBuildAjax,
15000                 _fnAjaxUpdate: _fnAjaxUpdate,
15001                 _fnAjaxParameters: _fnAjaxParameters,
15002                 _fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
15003                 _fnAjaxDataSrc: _fnAjaxDataSrc,
15004                 _fnAddColumn: _fnAddColumn,
15005                 _fnColumnOptions: _fnColumnOptions,
15006                 _fnAdjustColumnSizing: _fnAdjustColumnSizing,
15007                 _fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
15008                 _fnColumnIndexToVisible: _fnColumnIndexToVisible,
15009                 _fnVisbleColumns: _fnVisbleColumns,
15010                 _fnGetColumns: _fnGetColumns,
15011                 _fnColumnTypes: _fnColumnTypes,
15012                 _fnApplyColumnDefs: _fnApplyColumnDefs,
15013                 _fnHungarianMap: _fnHungarianMap,
15014                 _fnCamelToHungarian: _fnCamelToHungarian,
15015                 _fnLanguageCompat: _fnLanguageCompat,
15016                 _fnBrowserDetect: _fnBrowserDetect,
15017                 _fnAddData: _fnAddData,
15018                 _fnAddTr: _fnAddTr,
15019                 _fnNodeToDataIndex: _fnNodeToDataIndex,
15020                 _fnNodeToColumnIndex: _fnNodeToColumnIndex,
15021                 _fnGetCellData: _fnGetCellData,
15022                 _fnSetCellData: _fnSetCellData,
15023                 _fnSplitObjNotation: _fnSplitObjNotation,
15024                 _fnGetObjectDataFn: _fnGetObjectDataFn,
15025                 _fnSetObjectDataFn: _fnSetObjectDataFn,
15026                 _fnGetDataMaster: _fnGetDataMaster,
15027                 _fnClearTable: _fnClearTable,
15028                 _fnDeleteIndex: _fnDeleteIndex,
15029                 _fnInvalidate: _fnInvalidate,
15030                 _fnGetRowElements: _fnGetRowElements,
15031                 _fnCreateTr: _fnCreateTr,
15032                 _fnBuildHead: _fnBuildHead,
15033                 _fnDrawHead: _fnDrawHead,
15034                 _fnDraw: _fnDraw,
15035                 _fnReDraw: _fnReDraw,
15036                 _fnAddOptionsHtml: _fnAddOptionsHtml,
15037                 _fnDetectHeader: _fnDetectHeader,
15038                 _fnGetUniqueThs: _fnGetUniqueThs,
15039                 _fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
15040                 _fnFilterComplete: _fnFilterComplete,
15041                 _fnFilterCustom: _fnFilterCustom,
15042                 _fnFilterColumn: _fnFilterColumn,
15043                 _fnFilter: _fnFilter,
15044                 _fnFilterCreateSearch: _fnFilterCreateSearch,
15045                 _fnEscapeRegex: _fnEscapeRegex,
15046                 _fnFilterData: _fnFilterData,
15047                 _fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
15048                 _fnUpdateInfo: _fnUpdateInfo,
15049                 _fnInfoMacros: _fnInfoMacros,
15050                 _fnInitialise: _fnInitialise,
15051                 _fnInitComplete: _fnInitComplete,
15052                 _fnLengthChange: _fnLengthChange,
15053                 _fnFeatureHtmlLength: _fnFeatureHtmlLength,
15054                 _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
15055                 _fnPageChange: _fnPageChange,
15056                 _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
15057                 _fnProcessingDisplay: _fnProcessingDisplay,
15058                 _fnFeatureHtmlTable: _fnFeatureHtmlTable,
15059                 _fnScrollDraw: _fnScrollDraw,
15060                 _fnApplyToChildren: _fnApplyToChildren,
15061                 _fnCalculateColumnWidths: _fnCalculateColumnWidths,
15062                 _fnThrottle: _fnThrottle,
15063                 _fnConvertToWidth: _fnConvertToWidth,
15064                 _fnGetWidestNode: _fnGetWidestNode,
15065                 _fnGetMaxLenString: _fnGetMaxLenString,
15066                 _fnStringToCss: _fnStringToCss,
15067                 _fnSortFlatten: _fnSortFlatten,
15068                 _fnSort: _fnSort,
15069                 _fnSortAria: _fnSortAria,
15070                 _fnSortListener: _fnSortListener,
15071                 _fnSortAttachListener: _fnSortAttachListener,
15072                 _fnSortingClasses: _fnSortingClasses,
15073                 _fnSortData: _fnSortData,
15074                 _fnSaveState: _fnSaveState,
15075                 _fnLoadState: _fnLoadState,
15076                 _fnSettingsFromNode: _fnSettingsFromNode,
15077                 _fnLog: _fnLog,
15078                 _fnMap: _fnMap,
15079                 _fnBindAction: _fnBindAction,
15080                 _fnCallbackReg: _fnCallbackReg,
15081                 _fnCallbackFire: _fnCallbackFire,
15082                 _fnLengthOverflow: _fnLengthOverflow,
15083                 _fnRenderer: _fnRenderer,
15084                 _fnDataSource: _fnDataSource,
15085                 _fnRowAttributes: _fnRowAttributes,
15086                 _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
15087                                                 // in 1.10, so this dead-end function is
15088                                                 // added to prevent errors
15089         } );
15090         
15092         // jQuery access
15093         $.fn.dataTable = DataTable;
15095         // Provide access to the host jQuery object (circular reference)
15096         DataTable.$ = $;
15098         // Legacy aliases
15099         $.fn.dataTableSettings = DataTable.settings;
15100         $.fn.dataTableExt = DataTable.ext;
15102         // With a capital `D` we return a DataTables API instance rather than a
15103         // jQuery object
15104         $.fn.DataTable = function ( opts ) {
15105                 return $(this).dataTable( opts ).api();
15106         };
15108         // All properties that are available to $.fn.dataTable should also be
15109         // available on $.fn.DataTable
15110         $.each( DataTable, function ( prop, val ) {
15111                 $.fn.DataTable[ prop ] = val;
15112         } );
15115         // Information about events fired by DataTables - for documentation.
15116         /**
15117          * Draw event, fired whenever the table is redrawn on the page, at the same
15118          * point as fnDrawCallback. This may be useful for binding events or
15119          * performing calculations when the table is altered at all.
15120          *  @name DataTable#draw.dt
15121          *  @event
15122          *  @param {event} e jQuery event object
15123          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15124          */
15126         /**
15127          * Search event, fired when the searching applied to the table (using the
15128          * built-in global search, or column filters) is altered.
15129          *  @name DataTable#search.dt
15130          *  @event
15131          *  @param {event} e jQuery event object
15132          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15133          */
15135         /**
15136          * Page change event, fired when the paging of the table is altered.
15137          *  @name DataTable#page.dt
15138          *  @event
15139          *  @param {event} e jQuery event object
15140          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15141          */
15143         /**
15144          * Order event, fired when the ordering applied to the table is altered.
15145          *  @name DataTable#order.dt
15146          *  @event
15147          *  @param {event} e jQuery event object
15148          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15149          */
15151         /**
15152          * DataTables initialisation complete event, fired when the table is fully
15153          * drawn, including Ajax data loaded, if Ajax data is required.
15154          *  @name DataTable#init.dt
15155          *  @event
15156          *  @param {event} e jQuery event object
15157          *  @param {object} oSettings DataTables settings object
15158          *  @param {object} json The JSON object request from the server - only
15159          *    present if client-side Ajax sourced data is used</li></ol>
15160          */
15162         /**
15163          * State save event, fired when the table has changed state a new state save
15164          * is required. This event allows modification of the state saving object
15165          * prior to actually doing the save, including addition or other state
15166          * properties (for plug-ins) or modification of a DataTables core property.
15167          *  @name DataTable#stateSaveParams.dt
15168          *  @event
15169          *  @param {event} e jQuery event object
15170          *  @param {object} oSettings DataTables settings object
15171          *  @param {object} json The state information to be saved
15172          */
15174         /**
15175          * State load event, fired when the table is loading state from the stored
15176          * data, but prior to the settings object being modified by the saved state
15177          * - allowing modification of the saved state is required or loading of
15178          * state for a plug-in.
15179          *  @name DataTable#stateLoadParams.dt
15180          *  @event
15181          *  @param {event} e jQuery event object
15182          *  @param {object} oSettings DataTables settings object
15183          *  @param {object} json The saved state information
15184          */
15186         /**
15187          * State loaded event, fired when state has been loaded from stored data and
15188          * the settings object has been modified by the loaded data.
15189          *  @name DataTable#stateLoaded.dt
15190          *  @event
15191          *  @param {event} e jQuery event object
15192          *  @param {object} oSettings DataTables settings object
15193          *  @param {object} json The saved state information
15194          */
15196         /**
15197          * Processing event, fired when DataTables is doing some kind of processing
15198          * (be it, order, searcg or anything else). It can be used to indicate to
15199          * the end user that there is something happening, or that something has
15200          * finished.
15201          *  @name DataTable#processing.dt
15202          *  @event
15203          *  @param {event} e jQuery event object
15204          *  @param {object} oSettings DataTables settings object
15205          *  @param {boolean} bShow Flag for if DataTables is doing processing or not
15206          */
15208         /**
15209          * Ajax (XHR) event, fired whenever an Ajax request is completed from a
15210          * request to made to the server for new data. This event is called before
15211          * DataTables processed the returned data, so it can also be used to pre-
15212          * process the data returned from the server, if needed.
15213          *
15214          * Note that this trigger is called in `fnServerData`, if you override
15215          * `fnServerData` and which to use this event, you need to trigger it in you
15216          * success function.
15217          *  @name DataTable#xhr.dt
15218          *  @event
15219          *  @param {event} e jQuery event object
15220          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15221          *  @param {object} json JSON returned from the server
15222          *
15223          *  @example
15224          *     // Use a custom property returned from the server in another DOM element
15225          *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15226          *       $('#status').html( json.status );
15227          *     } );
15228          *
15229          *  @example
15230          *     // Pre-process the data returned from the server
15231          *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15232          *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
15233          *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
15234          *       }
15235          *       // Note no return - manipulate the data directly in the JSON object.
15236          *     } );
15237          */
15239         /**
15240          * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
15241          * or passing the bDestroy:true parameter in the initialisation object. This
15242          * can be used to remove bound events, added DOM nodes, etc.
15243          *  @name DataTable#destroy.dt
15244          *  @event
15245          *  @param {event} e jQuery event object
15246          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15247          */
15249         /**
15250          * Page length change event, fired when number of records to show on each
15251          * page (the length) is changed.
15252          *  @name DataTable#length.dt
15253          *  @event
15254          *  @param {event} e jQuery event object
15255          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15256          *  @param {integer} len New length
15257          */
15259         /**
15260          * Column sizing has changed.
15261          *  @name DataTable#column-sizing.dt
15262          *  @event
15263          *  @param {event} e jQuery event object
15264          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15265          */
15267         /**
15268          * Column visibility has changed.
15269          *  @name DataTable#column-visibility.dt
15270          *  @event
15271          *  @param {event} e jQuery event object
15272          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15273          *  @param {int} column Column index
15274          *  @param {bool} vis `false` if column now hidden, or `true` if visible
15275          */
15277         return $.fn.dataTable;
15278 }));