Built motion from commit b598105.|2.0.7
[motion2.git] / public / bower_components / datatables / media / js / jquery.dataTables.js
1 /*! DataTables 1.10.15
2  * ©2008-2017 SpryMedia Ltd - datatables.net/license
3  */
4
5 /**
6  * @summary     DataTables
7  * @description Paginate, search and order HTML tables
8  * @version     1.10.15
9  * @file        jquery.dataTables.js
10  * @author      SpryMedia Ltd
11  * @contact     www.datatables.net
12  * @copyright   Copyright 2008-2017 SpryMedia Ltd.
13  *
14  * This source file is free software, available under the following license:
15  *   MIT license - http://datatables.net/license
16  *
17  * This source file is distributed in the hope that it will be useful, but
18  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19  * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
20  *
21  * For details please refer to: http://www.datatables.net
22  */
23
24 /*jslint evil: true, undef: true, browser: true */
25 /*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
26
27 (function( factory ) {
28         "use strict";
29
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                         }
44
45                         if ( ! $ ) {
46                                 $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window
47                                         require('jquery') :
48                                         require('jquery')( root );
49                         }
50
51                         return factory( $, root, root.document );
52                 };
53         }
54         else {
55                 // Browser
56                 factory( jQuery, window, document );
57         }
58 }
59 (function( $, window, document, undefined ) {
60         "use strict";
61
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).on('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                 
851
852                 var _that = this;
853                 var emptyInit = options === undefined;
854                 var len = this.length;
855
856                 if ( emptyInit ) {
857                         options = {};
858                 }
859
860                 this.oApi = this.internal = _ext.internal;
861
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                 }
868
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;
876
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                         var loadedInit = function () {
1217                                 /*
1218                                  * Sorting
1219                                  * @todo For modularisation (1.11) this needs to do into a sort start up handler
1220                                  */
1221                         
1222                                 // If aaSorting is not defined, then we use the first indicator in asSorting
1223                                 // in case that has been altered, so the default sort reflects that option
1224                                 if ( oInit.aaSorting === undefined ) {
1225                                         var sorting = oSettings.aaSorting;
1226                                         for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) {
1227                                                 sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
1228                                         }
1229                                 }
1230                         
1231                                 /* Do a first pass on the sorting classes (allows any size changes to be taken into
1232                                  * account, and also will apply sorting disabled classes if disabled
1233                                  */
1234                                 _fnSortingClasses( oSettings );
1235                         
1236                                 if ( features.bSort ) {
1237                                         _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1238                                                 if ( oSettings.bSorted ) {
1239                                                         var aSort = _fnSortFlatten( oSettings );
1240                                                         var sortedColumns = {};
1241                         
1242                                                         $.each( aSort, function (i, val) {
1243                                                                 sortedColumns[ val.src ] = val.dir;
1244                                                         } );
1245                         
1246                                                         _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
1247                                                         _fnSortAria( oSettings );
1248                                                 }
1249                                         } );
1250                                 }
1251                         
1252                                 _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
1253                                         if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
1254                                                 _fnSortingClasses( oSettings );
1255                                         }
1256                                 }, 'sc' );
1257                         
1258                         
1259                                 /*
1260                                  * Final init
1261                                  * Cache the header, body and footer as required, creating them if needed
1262                                  */
1263                         
1264                                 // Work around for Webkit bug 83867 - store the caption-side before removing from doc
1265                                 var captions = $this.children('caption').each( function () {
1266                                         this._captionSide = $(this).css('caption-side');
1267                                 } );
1268                         
1269                                 var thead = $this.children('thead');
1270                                 if ( thead.length === 0 ) {
1271                                         thead = $('<thead/>').appendTo($this);
1272                                 }
1273                                 oSettings.nTHead = thead[0];
1274                         
1275                                 var tbody = $this.children('tbody');
1276                                 if ( tbody.length === 0 ) {
1277                                         tbody = $('<tbody/>').appendTo($this);
1278                                 }
1279                                 oSettings.nTBody = tbody[0];
1280                         
1281                                 var tfoot = $this.children('tfoot');
1282                                 if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) {
1283                                         // If we are a scrolling table, and no footer has been given, then we need to create
1284                                         // a tfoot element for the caption element to be appended to
1285                                         tfoot = $('<tfoot/>').appendTo($this);
1286                                 }
1287                         
1288                                 if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
1289                                         $this.addClass( oClasses.sNoFooter );
1290                                 }
1291                                 else if ( tfoot.length > 0 ) {
1292                                         oSettings.nTFoot = tfoot[0];
1293                                         _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
1294                                 }
1295                         
1296                                 /* Check if there is data passing into the constructor */
1297                                 if ( oInit.aaData ) {
1298                                         for ( i=0 ; i<oInit.aaData.length ; i++ ) {
1299                                                 _fnAddData( oSettings, oInit.aaData[ i ] );
1300                                         }
1301                                 }
1302                                 else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) {
1303                                         /* Grab the data from the page - only do this when deferred loading or no Ajax
1304                                          * source since there is no point in reading the DOM data if we are then going
1305                                          * to replace it with Ajax data
1306                                          */
1307                                         _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
1308                                 }
1309                         
1310                                 /* Copy the data index array */
1311                                 oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
1312                         
1313                                 /* Initialisation complete - table can be drawn */
1314                                 oSettings.bInitialised = true;
1315                         
1316                                 /* Check if we need to initialise the table (it might not have been handed off to the
1317                                  * language processor)
1318                                  */
1319                                 if ( bInitHandedOff === false ) {
1320                                         _fnInitialise( oSettings );
1321                                 }
1322                         };
1323                         
1324                         /* Must be done after everything which can be overridden by the state saving! */
1325                         if ( oInit.bStateSave )
1326                         {
1327                                 features.bStateSave = true;
1328                                 _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
1329                                 _fnLoadState( oSettings, oInit, loadedInit );
1330                         }
1331                         else {
1332                                 loadedInit();
1333                         }
1334                         
1335                 } );
1336                 _that = null;
1337                 return this;
1338         };
1339
1340         
1341         /*
1342          * It is useful to have variables which are scoped locally so only the
1343          * DataTables functions can access them and they don't leak into global space.
1344          * At the same time these functions are often useful over multiple files in the
1345          * core and API, so we list, or at least document, all variables which are used
1346          * by DataTables as private variables here. This also ensures that there is no
1347          * clashing of variable names and that they can easily referenced for reuse.
1348          */
1349         
1350         
1351         // Defined else where
1352         //  _selector_run
1353         //  _selector_opts
1354         //  _selector_first
1355         //  _selector_row_indexes
1356         
1357         var _ext; // DataTable.ext
1358         var _Api; // DataTable.Api
1359         var _api_register; // DataTable.Api.register
1360         var _api_registerPlural; // DataTable.Api.registerPlural
1361         
1362         var _re_dic = {};
1363         var _re_new_lines = /[\r\n]/g;
1364         var _re_html = /<.*?>/g;
1365         
1366         // This is not strict ISO8601 - Date.parse() is quite lax, although
1367         // implementations differ between browsers.
1368         var _re_date = /^\d{2,4}[\.\/\-]\d{1,2}[\.\/\-]\d{1,2}([T ]{1}\d{1,2}[:\.]\d{2}([\.:]\d{2})?)?$/;
1369         
1370         // Escape regular expression special characters
1371         var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
1372         
1373         // http://en.wikipedia.org/wiki/Foreign_exchange_market
1374         // - \u20BD - Russian ruble.
1375         // - \u20a9 - South Korean Won
1376         // - \u20BA - Turkish Lira
1377         // - \u20B9 - Indian Rupee
1378         // - R - Brazil (R$) and South Africa
1379         // - fr - Swiss Franc
1380         // - kr - Swedish krona, Norwegian krone and Danish krone
1381         // - \u2009 is thin space and \u202F is narrow no-break space, both used in many
1382         //   standards as thousands separators.
1383         var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi;
1384         
1385         
1386         var _empty = function ( d ) {
1387                 return !d || d === true || d === '-' ? true : false;
1388         };
1389         
1390         
1391         var _intVal = function ( s ) {
1392                 var integer = parseInt( s, 10 );
1393                 return !isNaN(integer) && isFinite(s) ? integer : null;
1394         };
1395         
1396         // Convert from a formatted number with characters other than `.` as the
1397         // decimal place, to a Javascript number
1398         var _numToDecimal = function ( num, decimalPoint ) {
1399                 // Cache created regular expressions for speed as this function is called often
1400                 if ( ! _re_dic[ decimalPoint ] ) {
1401                         _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
1402                 }
1403                 return typeof num === 'string' && decimalPoint !== '.' ?
1404                         num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
1405                         num;
1406         };
1407         
1408         
1409         var _isNumber = function ( d, decimalPoint, formatted ) {
1410                 var strType = typeof d === 'string';
1411         
1412                 // If empty return immediately so there must be a number if it is a
1413                 // formatted string (this stops the string "k", or "kr", etc being detected
1414                 // as a formatted number for currency
1415                 if ( _empty( d ) ) {
1416                         return true;
1417                 }
1418         
1419                 if ( decimalPoint && strType ) {
1420                         d = _numToDecimal( d, decimalPoint );
1421                 }
1422         
1423                 if ( formatted && strType ) {
1424                         d = d.replace( _re_formatted_numeric, '' );
1425                 }
1426         
1427                 return !isNaN( parseFloat(d) ) && isFinite( d );
1428         };
1429         
1430         
1431         // A string without HTML in it can be considered to be HTML still
1432         var _isHtml = function ( d ) {
1433                 return _empty( d ) || typeof d === 'string';
1434         };
1435         
1436         
1437         var _htmlNumeric = function ( d, decimalPoint, formatted ) {
1438                 if ( _empty( d ) ) {
1439                         return true;
1440                 }
1441         
1442                 var html = _isHtml( d );
1443                 return ! html ?
1444                         null :
1445                         _isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
1446                                 true :
1447                                 null;
1448         };
1449         
1450         
1451         var _pluck = function ( a, prop, prop2 ) {
1452                 var out = [];
1453                 var i=0, ien=a.length;
1454         
1455                 // Could have the test in the loop for slightly smaller code, but speed
1456                 // is essential here
1457                 if ( prop2 !== undefined ) {
1458                         for ( ; i<ien ; i++ ) {
1459                                 if ( a[i] && a[i][ prop ] ) {
1460                                         out.push( a[i][ prop ][ prop2 ] );
1461                                 }
1462                         }
1463                 }
1464                 else {
1465                         for ( ; i<ien ; i++ ) {
1466                                 if ( a[i] ) {
1467                                         out.push( a[i][ prop ] );
1468                                 }
1469                         }
1470                 }
1471         
1472                 return out;
1473         };
1474         
1475         
1476         // Basically the same as _pluck, but rather than looping over `a` we use `order`
1477         // as the indexes to pick from `a`
1478         var _pluck_order = function ( a, order, prop, prop2 )
1479         {
1480                 var out = [];
1481                 var i=0, ien=order.length;
1482         
1483                 // Could have the test in the loop for slightly smaller code, but speed
1484                 // is essential here
1485                 if ( prop2 !== undefined ) {
1486                         for ( ; i<ien ; i++ ) {
1487                                 if ( a[ order[i] ][ prop ] ) {
1488                                         out.push( a[ order[i] ][ prop ][ prop2 ] );
1489                                 }
1490                         }
1491                 }
1492                 else {
1493                         for ( ; i<ien ; i++ ) {
1494                                 out.push( a[ order[i] ][ prop ] );
1495                         }
1496                 }
1497         
1498                 return out;
1499         };
1500         
1501         
1502         var _range = function ( len, start )
1503         {
1504                 var out = [];
1505                 var end;
1506         
1507                 if ( start === undefined ) {
1508                         start = 0;
1509                         end = len;
1510                 }
1511                 else {
1512                         end = start;
1513                         start = len;
1514                 }
1515         
1516                 for ( var i=start ; i<end ; i++ ) {
1517                         out.push( i );
1518                 }
1519         
1520                 return out;
1521         };
1522         
1523         
1524         var _removeEmpty = function ( a )
1525         {
1526                 var out = [];
1527         
1528                 for ( var i=0, ien=a.length ; i<ien ; i++ ) {
1529                         if ( a[i] ) { // careful - will remove all falsy values!
1530                                 out.push( a[i] );
1531                         }
1532                 }
1533         
1534                 return out;
1535         };
1536         
1537         
1538         var _stripHtml = function ( d ) {
1539                 return d.replace( _re_html, '' );
1540         };
1541         
1542         
1543         /**
1544          * Determine if all values in the array are unique. This means we can short
1545          * cut the _unique method at the cost of a single loop. A sorted array is used
1546          * to easily check the values.
1547          *
1548          * @param  {array} src Source array
1549          * @return {boolean} true if all unique, false otherwise
1550          * @ignore
1551          */
1552         var _areAllUnique = function ( src ) {
1553                 if ( src.length < 2 ) {
1554                         return true;
1555                 }
1556         
1557                 var sorted = src.slice().sort();
1558                 var last = sorted[0];
1559         
1560                 for ( var i=1, ien=sorted.length ; i<ien ; i++ ) {
1561                         if ( sorted[i] === last ) {
1562                                 return false;
1563                         }
1564         
1565                         last = sorted[i];
1566                 }
1567         
1568                 return true;
1569         };
1570         
1571         
1572         /**
1573          * Find the unique elements in a source array.
1574          *
1575          * @param  {array} src Source array
1576          * @return {array} Array of unique items
1577          * @ignore
1578          */
1579         var _unique = function ( src )
1580         {
1581                 if ( _areAllUnique( src ) ) {
1582                         return src.slice();
1583                 }
1584         
1585                 // A faster unique method is to use object keys to identify used values,
1586                 // but this doesn't work with arrays or objects, which we must also
1587                 // consider. See jsperf.com/compare-array-unique-versions/4 for more
1588                 // information.
1589                 var
1590                         out = [],
1591                         val,
1592                         i, ien=src.length,
1593                         j, k=0;
1594         
1595                 again: for ( i=0 ; i<ien ; i++ ) {
1596                         val = src[i];
1597         
1598                         for ( j=0 ; j<k ; j++ ) {
1599                                 if ( out[j] === val ) {
1600                                         continue again;
1601                                 }
1602                         }
1603         
1604                         out.push( val );
1605                         k++;
1606                 }
1607         
1608                 return out;
1609         };
1610         
1611         
1612         /**
1613          * DataTables utility methods
1614          * 
1615          * This namespace provides helper methods that DataTables uses internally to
1616          * create a DataTable, but which are not exclusively used only for DataTables.
1617          * These methods can be used by extension authors to save the duplication of
1618          * code.
1619          *
1620          *  @namespace
1621          */
1622         DataTable.util = {
1623                 /**
1624                  * Throttle the calls to a function. Arguments and context are maintained
1625                  * for the throttled function.
1626                  *
1627                  * @param {function} fn Function to be called
1628                  * @param {integer} freq Call frequency in mS
1629                  * @return {function} Wrapped function
1630                  */
1631                 throttle: function ( fn, freq ) {
1632                         var
1633                                 frequency = freq !== undefined ? freq : 200,
1634                                 last,
1635                                 timer;
1636         
1637                         return function () {
1638                                 var
1639                                         that = this,
1640                                         now  = +new Date(),
1641                                         args = arguments;
1642         
1643                                 if ( last && now < last + frequency ) {
1644                                         clearTimeout( timer );
1645         
1646                                         timer = setTimeout( function () {
1647                                                 last = undefined;
1648                                                 fn.apply( that, args );
1649                                         }, frequency );
1650                                 }
1651                                 else {
1652                                         last = now;
1653                                         fn.apply( that, args );
1654                                 }
1655                         };
1656                 },
1657         
1658         
1659                 /**
1660                  * Escape a string such that it can be used in a regular expression
1661                  *
1662                  *  @param {string} val string to escape
1663                  *  @returns {string} escaped string
1664                  */
1665                 escapeRegex: function ( val ) {
1666                         return val.replace( _re_escape_regex, '\\$1' );
1667                 }
1668         };
1669         
1670         
1671         
1672         /**
1673          * Create a mapping object that allows camel case parameters to be looked up
1674          * for their Hungarian counterparts. The mapping is stored in a private
1675          * parameter called `_hungarianMap` which can be accessed on the source object.
1676          *  @param {object} o
1677          *  @memberof DataTable#oApi
1678          */
1679         function _fnHungarianMap ( o )
1680         {
1681                 var
1682                         hungarian = 'a aa ai ao as b fn i m o s ',
1683                         match,
1684                         newKey,
1685                         map = {};
1686         
1687                 $.each( o, function (key, val) {
1688                         match = key.match(/^([^A-Z]+?)([A-Z])/);
1689         
1690                         if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
1691                         {
1692                                 newKey = key.replace( match[0], match[2].toLowerCase() );
1693                                 map[ newKey ] = key;
1694         
1695                                 if ( match[1] === 'o' )
1696                                 {
1697                                         _fnHungarianMap( o[key] );
1698                                 }
1699                         }
1700                 } );
1701         
1702                 o._hungarianMap = map;
1703         }
1704         
1705         
1706         /**
1707          * Convert from camel case parameters to Hungarian, based on a Hungarian map
1708          * created by _fnHungarianMap.
1709          *  @param {object} src The model object which holds all parameters that can be
1710          *    mapped.
1711          *  @param {object} user The object to convert from camel case to Hungarian.
1712          *  @param {boolean} force When set to `true`, properties which already have a
1713          *    Hungarian value in the `user` object will be overwritten. Otherwise they
1714          *    won't be.
1715          *  @memberof DataTable#oApi
1716          */
1717         function _fnCamelToHungarian ( src, user, force )
1718         {
1719                 if ( ! src._hungarianMap ) {
1720                         _fnHungarianMap( src );
1721                 }
1722         
1723                 var hungarianKey;
1724         
1725                 $.each( user, function (key, val) {
1726                         hungarianKey = src._hungarianMap[ key ];
1727         
1728                         if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
1729                         {
1730                                 // For objects, we need to buzz down into the object to copy parameters
1731                                 if ( hungarianKey.charAt(0) === 'o' )
1732                                 {
1733                                         // Copy the camelCase options over to the hungarian
1734                                         if ( ! user[ hungarianKey ] ) {
1735                                                 user[ hungarianKey ] = {};
1736                                         }
1737                                         $.extend( true, user[hungarianKey], user[key] );
1738         
1739                                         _fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
1740                                 }
1741                                 else {
1742                                         user[hungarianKey] = user[ key ];
1743                                 }
1744                         }
1745                 } );
1746         }
1747         
1748         
1749         /**
1750          * Language compatibility - when certain options are given, and others aren't, we
1751          * need to duplicate the values over, in order to provide backwards compatibility
1752          * with older language files.
1753          *  @param {object} oSettings dataTables settings object
1754          *  @memberof DataTable#oApi
1755          */
1756         function _fnLanguageCompat( lang )
1757         {
1758                 var defaults = DataTable.defaults.oLanguage;
1759                 var zeroRecords = lang.sZeroRecords;
1760         
1761                 /* Backwards compatibility - if there is no sEmptyTable given, then use the same as
1762                  * sZeroRecords - assuming that is given.
1763                  */
1764                 if ( ! lang.sEmptyTable && zeroRecords &&
1765                         defaults.sEmptyTable === "No data available in table" )
1766                 {
1767                         _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
1768                 }
1769         
1770                 /* Likewise with loading records */
1771                 if ( ! lang.sLoadingRecords && zeroRecords &&
1772                         defaults.sLoadingRecords === "Loading..." )
1773                 {
1774                         _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
1775                 }
1776         
1777                 // Old parameter name of the thousands separator mapped onto the new
1778                 if ( lang.sInfoThousands ) {
1779                         lang.sThousands = lang.sInfoThousands;
1780                 }
1781         
1782                 var decimal = lang.sDecimal;
1783                 if ( decimal ) {
1784                         _addNumericSort( decimal );
1785                 }
1786         }
1787         
1788         
1789         /**
1790          * Map one parameter onto another
1791          *  @param {object} o Object to map
1792          *  @param {*} knew The new parameter name
1793          *  @param {*} old The old parameter name
1794          */
1795         var _fnCompatMap = function ( o, knew, old ) {
1796                 if ( o[ knew ] !== undefined ) {
1797                         o[ old ] = o[ knew ];
1798                 }
1799         };
1800         
1801         
1802         /**
1803          * Provide backwards compatibility for the main DT options. Note that the new
1804          * options are mapped onto the old parameters, so this is an external interface
1805          * change only.
1806          *  @param {object} init Object to map
1807          */
1808         function _fnCompatOpts ( init )
1809         {
1810                 _fnCompatMap( init, 'ordering',      'bSort' );
1811                 _fnCompatMap( init, 'orderMulti',    'bSortMulti' );
1812                 _fnCompatMap( init, 'orderClasses',  'bSortClasses' );
1813                 _fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
1814                 _fnCompatMap( init, 'order',         'aaSorting' );
1815                 _fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
1816                 _fnCompatMap( init, 'paging',        'bPaginate' );
1817                 _fnCompatMap( init, 'pagingType',    'sPaginationType' );
1818                 _fnCompatMap( init, 'pageLength',    'iDisplayLength' );
1819                 _fnCompatMap( init, 'searching',     'bFilter' );
1820         
1821                 // Boolean initialisation of x-scrolling
1822                 if ( typeof init.sScrollX === 'boolean' ) {
1823                         init.sScrollX = init.sScrollX ? '100%' : '';
1824                 }
1825                 if ( typeof init.scrollX === 'boolean' ) {
1826                         init.scrollX = init.scrollX ? '100%' : '';
1827                 }
1828         
1829                 // Column search objects are in an array, so it needs to be converted
1830                 // element by element
1831                 var searchCols = init.aoSearchCols;
1832         
1833                 if ( searchCols ) {
1834                         for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
1835                                 if ( searchCols[i] ) {
1836                                         _fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
1837                                 }
1838                         }
1839                 }
1840         }
1841         
1842         
1843         /**
1844          * Provide backwards compatibility for column options. Note that the new options
1845          * are mapped onto the old parameters, so this is an external interface change
1846          * only.
1847          *  @param {object} init Object to map
1848          */
1849         function _fnCompatCols ( init )
1850         {
1851                 _fnCompatMap( init, 'orderable',     'bSortable' );
1852                 _fnCompatMap( init, 'orderData',     'aDataSort' );
1853                 _fnCompatMap( init, 'orderSequence', 'asSorting' );
1854                 _fnCompatMap( init, 'orderDataType', 'sortDataType' );
1855         
1856                 // orderData can be given as an integer
1857                 var dataSort = init.aDataSort;
1858                 if ( typeof dataSort === 'number' && ! $.isArray( dataSort ) ) {
1859                         init.aDataSort = [ dataSort ];
1860                 }
1861         }
1862         
1863         
1864         /**
1865          * Browser feature detection for capabilities, quirks
1866          *  @param {object} settings dataTables settings object
1867          *  @memberof DataTable#oApi
1868          */
1869         function _fnBrowserDetect( settings )
1870         {
1871                 // We don't need to do this every time DataTables is constructed, the values
1872                 // calculated are specific to the browser and OS configuration which we
1873                 // don't expect to change between initialisations
1874                 if ( ! DataTable.__browser ) {
1875                         var browser = {};
1876                         DataTable.__browser = browser;
1877         
1878                         // Scrolling feature / quirks detection
1879                         var n = $('<div/>')
1880                                 .css( {
1881                                         position: 'fixed',
1882                                         top: 0,
1883                                         left: $(window).scrollLeft()*-1, // allow for scrolling
1884                                         height: 1,
1885                                         width: 1,
1886                                         overflow: 'hidden'
1887                                 } )
1888                                 .append(
1889                                         $('<div/>')
1890                                                 .css( {
1891                                                         position: 'absolute',
1892                                                         top: 1,
1893                                                         left: 1,
1894                                                         width: 100,
1895                                                         overflow: 'scroll'
1896                                                 } )
1897                                                 .append(
1898                                                         $('<div/>')
1899                                                                 .css( {
1900                                                                         width: '100%',
1901                                                                         height: 10
1902                                                                 } )
1903                                                 )
1904                                 )
1905                                 .appendTo( 'body' );
1906         
1907                         var outer = n.children();
1908                         var inner = outer.children();
1909         
1910                         // Numbers below, in order, are:
1911                         // inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth
1912                         //
1913                         // IE6 XP:                           100 100 100  83
1914                         // IE7 Vista:                        100 100 100  83
1915                         // IE 8+ Windows:                     83  83 100  83
1916                         // Evergreen Windows:                 83  83 100  83
1917                         // Evergreen Mac with scrollbars:     85  85 100  85
1918                         // Evergreen Mac without scrollbars: 100 100 100 100
1919         
1920                         // Get scrollbar width
1921                         browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;
1922         
1923                         // IE6/7 will oversize a width 100% element inside a scrolling element, to
1924                         // include the width of the scrollbar, while other browsers ensure the inner
1925                         // element is contained without forcing scrolling
1926                         browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;
1927         
1928                         // In rtl text layout, some browsers (most, but not all) will place the
1929                         // scrollbar on the left, rather than the right.
1930                         browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;
1931         
1932                         // IE8- don't provide height and width for getBoundingClientRect
1933                         browser.bBounding = n[0].getBoundingClientRect().width ? true : false;
1934         
1935                         n.remove();
1936                 }
1937         
1938                 $.extend( settings.oBrowser, DataTable.__browser );
1939                 settings.oScroll.iBarWidth = DataTable.__browser.barWidth;
1940         }
1941         
1942         
1943         /**
1944          * Array.prototype reduce[Right] method, used for browsers which don't support
1945          * JS 1.6. Done this way to reduce code size, since we iterate either way
1946          *  @param {object} settings dataTables settings object
1947          *  @memberof DataTable#oApi
1948          */
1949         function _fnReduce ( that, fn, init, start, end, inc )
1950         {
1951                 var
1952                         i = start,
1953                         value,
1954                         isSet = false;
1955         
1956                 if ( init !== undefined ) {
1957                         value = init;
1958                         isSet = true;
1959                 }
1960         
1961                 while ( i !== end ) {
1962                         if ( ! that.hasOwnProperty(i) ) {
1963                                 continue;
1964                         }
1965         
1966                         value = isSet ?
1967                                 fn( value, that[i], i, that ) :
1968                                 that[i];
1969         
1970                         isSet = true;
1971                         i += inc;
1972                 }
1973         
1974                 return value;
1975         }
1976         
1977         /**
1978          * Add a column to the list used for the table with default values
1979          *  @param {object} oSettings dataTables settings object
1980          *  @param {node} nTh The th element for this column
1981          *  @memberof DataTable#oApi
1982          */
1983         function _fnAddColumn( oSettings, nTh )
1984         {
1985                 // Add column to aoColumns array
1986                 var oDefaults = DataTable.defaults.column;
1987                 var iCol = oSettings.aoColumns.length;
1988                 var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
1989                         "nTh": nTh ? nTh : document.createElement('th'),
1990                         "sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
1991                         "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
1992                         "mData": oDefaults.mData ? oDefaults.mData : iCol,
1993                         idx: iCol
1994                 } );
1995                 oSettings.aoColumns.push( oCol );
1996         
1997                 // Add search object for column specific search. Note that the `searchCols[ iCol ]`
1998                 // passed into extend can be undefined. This allows the user to give a default
1999                 // with only some of the parameters defined, and also not give a default
2000                 var searchCols = oSettings.aoPreSearchCols;
2001                 searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
2002         
2003                 // Use the default column options function to initialise classes etc
2004                 _fnColumnOptions( oSettings, iCol, $(nTh).data() );
2005         }
2006         
2007         
2008         /**
2009          * Apply options for a column
2010          *  @param {object} oSettings dataTables settings object
2011          *  @param {int} iCol column index to consider
2012          *  @param {object} oOptions object with sType, bVisible and bSearchable etc
2013          *  @memberof DataTable#oApi
2014          */
2015         function _fnColumnOptions( oSettings, iCol, oOptions )
2016         {
2017                 var oCol = oSettings.aoColumns[ iCol ];
2018                 var oClasses = oSettings.oClasses;
2019                 var th = $(oCol.nTh);
2020         
2021                 // Try to get width information from the DOM. We can't get it from CSS
2022                 // as we'd need to parse the CSS stylesheet. `width` option can override
2023                 if ( ! oCol.sWidthOrig ) {
2024                         // Width attribute
2025                         oCol.sWidthOrig = th.attr('width') || null;
2026         
2027                         // Style attribute
2028                         var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
2029                         if ( t ) {
2030                                 oCol.sWidthOrig = t[1];
2031                         }
2032                 }
2033         
2034                 /* User specified column options */
2035                 if ( oOptions !== undefined && oOptions !== null )
2036                 {
2037                         // Backwards compatibility
2038                         _fnCompatCols( oOptions );
2039         
2040                         // Map camel case parameters to their Hungarian counterparts
2041                         _fnCamelToHungarian( DataTable.defaults.column, oOptions );
2042         
2043                         /* Backwards compatibility for mDataProp */
2044                         if ( oOptions.mDataProp !== undefined && !oOptions.mData )
2045                         {
2046                                 oOptions.mData = oOptions.mDataProp;
2047                         }
2048         
2049                         if ( oOptions.sType )
2050                         {
2051                                 oCol._sManualType = oOptions.sType;
2052                         }
2053         
2054                         // `class` is a reserved word in Javascript, so we need to provide
2055                         // the ability to use a valid name for the camel case input
2056                         if ( oOptions.className && ! oOptions.sClass )
2057                         {
2058                                 oOptions.sClass = oOptions.className;
2059                         }
2060         
2061                         $.extend( oCol, oOptions );
2062                         _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
2063         
2064                         /* iDataSort to be applied (backwards compatibility), but aDataSort will take
2065                          * priority if defined
2066                          */
2067                         if ( oOptions.iDataSort !== undefined )
2068                         {
2069                                 oCol.aDataSort = [ oOptions.iDataSort ];
2070                         }
2071                         _fnMap( oCol, oOptions, "aDataSort" );
2072                 }
2073         
2074                 /* Cache the data get and set functions for speed */
2075                 var mDataSrc = oCol.mData;
2076                 var mData = _fnGetObjectDataFn( mDataSrc );
2077                 var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
2078         
2079                 var attrTest = function( src ) {
2080                         return typeof src === 'string' && src.indexOf('@') !== -1;
2081                 };
2082                 oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
2083                         attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
2084                 );
2085                 oCol._setter = null;
2086         
2087                 oCol.fnGetData = function (rowData, type, meta) {
2088                         var innerData = mData( rowData, type, undefined, meta );
2089         
2090                         return mRender && type ?
2091                                 mRender( innerData, type, rowData, meta ) :
2092                                 innerData;
2093                 };
2094                 oCol.fnSetData = function ( rowData, val, meta ) {
2095                         return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
2096                 };
2097         
2098                 // Indicate if DataTables should read DOM data as an object or array
2099                 // Used in _fnGetRowElements
2100                 if ( typeof mDataSrc !== 'number' ) {
2101                         oSettings._rowReadObject = true;
2102                 }
2103         
2104                 /* Feature sorting overrides column specific when off */
2105                 if ( !oSettings.oFeatures.bSort )
2106                 {
2107                         oCol.bSortable = false;
2108                         th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
2109                 }
2110         
2111                 /* Check that the class assignment is correct for sorting */
2112                 var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
2113                 var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
2114                 if ( !oCol.bSortable || (!bAsc && !bDesc) )
2115                 {
2116                         oCol.sSortingClass = oClasses.sSortableNone;
2117                         oCol.sSortingClassJUI = "";
2118                 }
2119                 else if ( bAsc && !bDesc )
2120                 {
2121                         oCol.sSortingClass = oClasses.sSortableAsc;
2122                         oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
2123                 }
2124                 else if ( !bAsc && bDesc )
2125                 {
2126                         oCol.sSortingClass = oClasses.sSortableDesc;
2127                         oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
2128                 }
2129                 else
2130                 {
2131                         oCol.sSortingClass = oClasses.sSortable;
2132                         oCol.sSortingClassJUI = oClasses.sSortJUI;
2133                 }
2134         }
2135         
2136         
2137         /**
2138          * Adjust the table column widths for new data. Note: you would probably want to
2139          * do a redraw after calling this function!
2140          *  @param {object} settings dataTables settings object
2141          *  @memberof DataTable#oApi
2142          */
2143         function _fnAdjustColumnSizing ( settings )
2144         {
2145                 /* Not interested in doing column width calculation if auto-width is disabled */
2146                 if ( settings.oFeatures.bAutoWidth !== false )
2147                 {
2148                         var columns = settings.aoColumns;
2149         
2150                         _fnCalculateColumnWidths( settings );
2151                         for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
2152                         {
2153                                 columns[i].nTh.style.width = columns[i].sWidth;
2154                         }
2155                 }
2156         
2157                 var scroll = settings.oScroll;
2158                 if ( scroll.sY !== '' || scroll.sX !== '')
2159                 {
2160                         _fnScrollDraw( settings );
2161                 }
2162         
2163                 _fnCallbackFire( settings, null, 'column-sizing', [settings] );
2164         }
2165         
2166         
2167         /**
2168          * Covert the index of a visible column to the index in the data array (take account
2169          * of hidden columns)
2170          *  @param {object} oSettings dataTables settings object
2171          *  @param {int} iMatch Visible column index to lookup
2172          *  @returns {int} i the data index
2173          *  @memberof DataTable#oApi
2174          */
2175         function _fnVisibleToColumnIndex( oSettings, iMatch )
2176         {
2177                 var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2178         
2179                 return typeof aiVis[iMatch] === 'number' ?
2180                         aiVis[iMatch] :
2181                         null;
2182         }
2183         
2184         
2185         /**
2186          * Covert the index of an index in the data array and convert it to the visible
2187          *   column index (take account of hidden columns)
2188          *  @param {int} iMatch Column index to lookup
2189          *  @param {object} oSettings dataTables settings object
2190          *  @returns {int} i the data index
2191          *  @memberof DataTable#oApi
2192          */
2193         function _fnColumnIndexToVisible( oSettings, iMatch )
2194         {
2195                 var aiVis = _fnGetColumns( oSettings, 'bVisible' );
2196                 var iPos = $.inArray( iMatch, aiVis );
2197         
2198                 return iPos !== -1 ? iPos : null;
2199         }
2200         
2201         
2202         /**
2203          * Get the number of visible columns
2204          *  @param {object} oSettings dataTables settings object
2205          *  @returns {int} i the number of visible columns
2206          *  @memberof DataTable#oApi
2207          */
2208         function _fnVisbleColumns( oSettings )
2209         {
2210                 var vis = 0;
2211         
2212                 // No reduce in IE8, use a loop for now
2213                 $.each( oSettings.aoColumns, function ( i, col ) {
2214                         if ( col.bVisible && $(col.nTh).css('display') !== 'none' ) {
2215                                 vis++;
2216                         }
2217                 } );
2218         
2219                 return vis;
2220         }
2221         
2222         
2223         /**
2224          * Get an array of column indexes that match a given property
2225          *  @param {object} oSettings dataTables settings object
2226          *  @param {string} sParam Parameter in aoColumns to look for - typically
2227          *    bVisible or bSearchable
2228          *  @returns {array} Array of indexes with matched properties
2229          *  @memberof DataTable#oApi
2230          */
2231         function _fnGetColumns( oSettings, sParam )
2232         {
2233                 var a = [];
2234         
2235                 $.map( oSettings.aoColumns, function(val, i) {
2236                         if ( val[sParam] ) {
2237                                 a.push( i );
2238                         }
2239                 } );
2240         
2241                 return a;
2242         }
2243         
2244         
2245         /**
2246          * Calculate the 'type' of a column
2247          *  @param {object} settings dataTables settings object
2248          *  @memberof DataTable#oApi
2249          */
2250         function _fnColumnTypes ( settings )
2251         {
2252                 var columns = settings.aoColumns;
2253                 var data = settings.aoData;
2254                 var types = DataTable.ext.type.detect;
2255                 var i, ien, j, jen, k, ken;
2256                 var col, cell, detectedType, cache;
2257         
2258                 // For each column, spin over the 
2259                 for ( i=0, ien=columns.length ; i<ien ; i++ ) {
2260                         col = columns[i];
2261                         cache = [];
2262         
2263                         if ( ! col.sType && col._sManualType ) {
2264                                 col.sType = col._sManualType;
2265                         }
2266                         else if ( ! col.sType ) {
2267                                 for ( j=0, jen=types.length ; j<jen ; j++ ) {
2268                                         for ( k=0, ken=data.length ; k<ken ; k++ ) {
2269                                                 // Use a cache array so we only need to get the type data
2270                                                 // from the formatter once (when using multiple detectors)
2271                                                 if ( cache[k] === undefined ) {
2272                                                         cache[k] = _fnGetCellData( settings, k, i, 'type' );
2273                                                 }
2274         
2275                                                 detectedType = types[j]( cache[k], settings );
2276         
2277                                                 // If null, then this type can't apply to this column, so
2278                                                 // rather than testing all cells, break out. There is an
2279                                                 // exception for the last type which is `html`. We need to
2280                                                 // scan all rows since it is possible to mix string and HTML
2281                                                 // types
2282                                                 if ( ! detectedType && j !== types.length-1 ) {
2283                                                         break;
2284                                                 }
2285         
2286                                                 // Only a single match is needed for html type since it is
2287                                                 // bottom of the pile and very similar to string
2288                                                 if ( detectedType === 'html' ) {
2289                                                         break;
2290                                                 }
2291                                         }
2292         
2293                                         // Type is valid for all data points in the column - use this
2294                                         // type
2295                                         if ( detectedType ) {
2296                                                 col.sType = detectedType;
2297                                                 break;
2298                                         }
2299                                 }
2300         
2301                                 // Fall back - if no type was detected, always use string
2302                                 if ( ! col.sType ) {
2303                                         col.sType = 'string';
2304                                 }
2305                         }
2306                 }
2307         }
2308         
2309         
2310         /**
2311          * Take the column definitions and static columns arrays and calculate how
2312          * they relate to column indexes. The callback function will then apply the
2313          * definition found for a column to a suitable configuration object.
2314          *  @param {object} oSettings dataTables settings object
2315          *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
2316          *  @param {array} aoCols The aoColumns array that defines columns individually
2317          *  @param {function} fn Callback function - takes two parameters, the calculated
2318          *    column index and the definition for that column.
2319          *  @memberof DataTable#oApi
2320          */
2321         function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
2322         {
2323                 var i, iLen, j, jLen, k, kLen, def;
2324                 var columns = oSettings.aoColumns;
2325         
2326                 // Column definitions with aTargets
2327                 if ( aoColDefs )
2328                 {
2329                         /* Loop over the definitions array - loop in reverse so first instance has priority */
2330                         for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
2331                         {
2332                                 def = aoColDefs[i];
2333         
2334                                 /* Each definition can target multiple columns, as it is an array */
2335                                 var aTargets = def.targets !== undefined ?
2336                                         def.targets :
2337                                         def.aTargets;
2338         
2339                                 if ( ! $.isArray( aTargets ) )
2340                                 {
2341                                         aTargets = [ aTargets ];
2342                                 }
2343         
2344                                 for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
2345                                 {
2346                                         if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
2347                                         {
2348                                                 /* Add columns that we don't yet know about */
2349                                                 while( columns.length <= aTargets[j] )
2350                                                 {
2351                                                         _fnAddColumn( oSettings );
2352                                                 }
2353         
2354                                                 /* Integer, basic index */
2355                                                 fn( aTargets[j], def );
2356                                         }
2357                                         else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
2358                                         {
2359                                                 /* Negative integer, right to left column counting */
2360                                                 fn( columns.length+aTargets[j], def );
2361                                         }
2362                                         else if ( typeof aTargets[j] === 'string' )
2363                                         {
2364                                                 /* Class name matching on TH element */
2365                                                 for ( k=0, kLen=columns.length ; k<kLen ; k++ )
2366                                                 {
2367                                                         if ( aTargets[j] == "_all" ||
2368                                                              $(columns[k].nTh).hasClass( aTargets[j] ) )
2369                                                         {
2370                                                                 fn( k, def );
2371                                                         }
2372                                                 }
2373                                         }
2374                                 }
2375                         }
2376                 }
2377         
2378                 // Statically defined columns array
2379                 if ( aoCols )
2380                 {
2381                         for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
2382                         {
2383                                 fn( i, aoCols[i] );
2384                         }
2385                 }
2386         }
2387         
2388         /**
2389          * Add a data array to the table, creating DOM node etc. This is the parallel to
2390          * _fnGatherData, but for adding rows from a Javascript source, rather than a
2391          * DOM source.
2392          *  @param {object} oSettings dataTables settings object
2393          *  @param {array} aData data array to be added
2394          *  @param {node} [nTr] TR element to add to the table - optional. If not given,
2395          *    DataTables will create a row automatically
2396          *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
2397          *    if nTr is.
2398          *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
2399          *  @memberof DataTable#oApi
2400          */
2401         function _fnAddData ( oSettings, aDataIn, nTr, anTds )
2402         {
2403                 /* Create the object for storing information about this new row */
2404                 var iRow = oSettings.aoData.length;
2405                 var oData = $.extend( true, {}, DataTable.models.oRow, {
2406                         src: nTr ? 'dom' : 'data',
2407                         idx: iRow
2408                 } );
2409         
2410                 oData._aData = aDataIn;
2411                 oSettings.aoData.push( oData );
2412         
2413                 /* Create the cells */
2414                 var nTd, sThisType;
2415                 var columns = oSettings.aoColumns;
2416         
2417                 // Invalidate the column types as the new data needs to be revalidated
2418                 for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
2419                 {
2420                         columns[i].sType = null;
2421                 }
2422         
2423                 /* Add to the display array */
2424                 oSettings.aiDisplayMaster.push( iRow );
2425         
2426                 var id = oSettings.rowIdFn( aDataIn );
2427                 if ( id !== undefined ) {
2428                         oSettings.aIds[ id ] = oData;
2429                 }
2430         
2431                 /* Create the DOM information, or register it if already present */
2432                 if ( nTr || ! oSettings.oFeatures.bDeferRender )
2433                 {
2434                         _fnCreateTr( oSettings, iRow, nTr, anTds );
2435                 }
2436         
2437                 return iRow;
2438         }
2439         
2440         
2441         /**
2442          * Add one or more TR elements to the table. Generally we'd expect to
2443          * use this for reading data from a DOM sourced table, but it could be
2444          * used for an TR element. Note that if a TR is given, it is used (i.e.
2445          * it is not cloned).
2446          *  @param {object} settings dataTables settings object
2447          *  @param {array|node|jQuery} trs The TR element(s) to add to the table
2448          *  @returns {array} Array of indexes for the added rows
2449          *  @memberof DataTable#oApi
2450          */
2451         function _fnAddTr( settings, trs )
2452         {
2453                 var row;
2454         
2455                 // Allow an individual node to be passed in
2456                 if ( ! (trs instanceof $) ) {
2457                         trs = $(trs);
2458                 }
2459         
2460                 return trs.map( function (i, el) {
2461                         row = _fnGetRowElements( settings, el );
2462                         return _fnAddData( settings, row.data, el, row.cells );
2463                 } );
2464         }
2465         
2466         
2467         /**
2468          * Take a TR element and convert it to an index in aoData
2469          *  @param {object} oSettings dataTables settings object
2470          *  @param {node} n the TR element to find
2471          *  @returns {int} index if the node is found, null if not
2472          *  @memberof DataTable#oApi
2473          */
2474         function _fnNodeToDataIndex( oSettings, n )
2475         {
2476                 return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
2477         }
2478         
2479         
2480         /**
2481          * Take a TD element and convert it into a column data index (not the visible index)
2482          *  @param {object} oSettings dataTables settings object
2483          *  @param {int} iRow The row number the TD/TH can be found in
2484          *  @param {node} n The TD/TH element to find
2485          *  @returns {int} index if the node is found, -1 if not
2486          *  @memberof DataTable#oApi
2487          */
2488         function _fnNodeToColumnIndex( oSettings, iRow, n )
2489         {
2490                 return $.inArray( n, oSettings.aoData[ iRow ].anCells );
2491         }
2492         
2493         
2494         /**
2495          * Get the data for a given cell from the internal cache, taking into account data mapping
2496          *  @param {object} settings dataTables settings object
2497          *  @param {int} rowIdx aoData row id
2498          *  @param {int} colIdx Column index
2499          *  @param {string} type data get type ('display', 'type' 'filter' 'sort')
2500          *  @returns {*} Cell data
2501          *  @memberof DataTable#oApi
2502          */
2503         function _fnGetCellData( settings, rowIdx, colIdx, type )
2504         {
2505                 var draw           = settings.iDraw;
2506                 var col            = settings.aoColumns[colIdx];
2507                 var rowData        = settings.aoData[rowIdx]._aData;
2508                 var defaultContent = col.sDefaultContent;
2509                 var cellData       = col.fnGetData( rowData, type, {
2510                         settings: settings,
2511                         row:      rowIdx,
2512                         col:      colIdx
2513                 } );
2514         
2515                 if ( cellData === undefined ) {
2516                         if ( settings.iDrawError != draw && defaultContent === null ) {
2517                                 _fnLog( settings, 0, "Requested unknown parameter "+
2518                                         (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
2519                                         " for row "+rowIdx+", column "+colIdx, 4 );
2520                                 settings.iDrawError = draw;
2521                         }
2522                         return defaultContent;
2523                 }
2524         
2525                 // When the data source is null and a specific data type is requested (i.e.
2526                 // not the original data), we can use default column data
2527                 if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {
2528                         cellData = defaultContent;
2529                 }
2530                 else if ( typeof cellData === 'function' ) {
2531                         // If the data source is a function, then we run it and use the return,
2532                         // executing in the scope of the data object (for instances)
2533                         return cellData.call( rowData );
2534                 }
2535         
2536                 if ( cellData === null && type == 'display' ) {
2537                         return '';
2538                 }
2539                 return cellData;
2540         }
2541         
2542         
2543         /**
2544          * Set the value for a specific cell, into the internal data cache
2545          *  @param {object} settings dataTables settings object
2546          *  @param {int} rowIdx aoData row id
2547          *  @param {int} colIdx Column index
2548          *  @param {*} val Value to set
2549          *  @memberof DataTable#oApi
2550          */
2551         function _fnSetCellData( settings, rowIdx, colIdx, val )
2552         {
2553                 var col     = settings.aoColumns[colIdx];
2554                 var rowData = settings.aoData[rowIdx]._aData;
2555         
2556                 col.fnSetData( rowData, val, {
2557                         settings: settings,
2558                         row:      rowIdx,
2559                         col:      colIdx
2560                 }  );
2561         }
2562         
2563         
2564         // Private variable that is used to match action syntax in the data property object
2565         var __reArray = /\[.*?\]$/;
2566         var __reFn = /\(\)$/;
2567         
2568         /**
2569          * Split string on periods, taking into account escaped periods
2570          * @param  {string} str String to split
2571          * @return {array} Split string
2572          */
2573         function _fnSplitObjNotation( str )
2574         {
2575                 return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {
2576                         return s.replace(/\\\./g, '.');
2577                 } );
2578         }
2579         
2580         
2581         /**
2582          * Return a function that can be used to get data from a source object, taking
2583          * into account the ability to use nested objects as a source
2584          *  @param {string|int|function} mSource The data source for the object
2585          *  @returns {function} Data get function
2586          *  @memberof DataTable#oApi
2587          */
2588         function _fnGetObjectDataFn( mSource )
2589         {
2590                 if ( $.isPlainObject( mSource ) )
2591                 {
2592                         /* Build an object of get functions, and wrap them in a single call */
2593                         var o = {};
2594                         $.each( mSource, function (key, val) {
2595                                 if ( val ) {
2596                                         o[key] = _fnGetObjectDataFn( val );
2597                                 }
2598                         } );
2599         
2600                         return function (data, type, row, meta) {
2601                                 var t = o[type] || o._;
2602                                 return t !== undefined ?
2603                                         t(data, type, row, meta) :
2604                                         data;
2605                         };
2606                 }
2607                 else if ( mSource === null )
2608                 {
2609                         /* Give an empty string for rendering / sorting etc */
2610                         return function (data) { // type, row and meta also passed, but not used
2611                                 return data;
2612                         };
2613                 }
2614                 else if ( typeof mSource === 'function' )
2615                 {
2616                         return function (data, type, row, meta) {
2617                                 return mSource( data, type, row, meta );
2618                         };
2619                 }
2620                 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2621                               mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2622                 {
2623                         /* If there is a . in the source string then the data source is in a
2624                          * nested object so we loop over the data for each level to get the next
2625                          * level down. On each loop we test for undefined, and if found immediately
2626                          * return. This allows entire objects to be missing and sDefaultContent to
2627                          * be used if defined, rather than throwing an error
2628                          */
2629                         var fetchData = function (data, type, src) {
2630                                 var arrayNotation, funcNotation, out, innerSrc;
2631         
2632                                 if ( src !== "" )
2633                                 {
2634                                         var a = _fnSplitObjNotation( src );
2635         
2636                                         for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2637                                         {
2638                                                 // Check if we are dealing with special notation
2639                                                 arrayNotation = a[i].match(__reArray);
2640                                                 funcNotation = a[i].match(__reFn);
2641         
2642                                                 if ( arrayNotation )
2643                                                 {
2644                                                         // Array notation
2645                                                         a[i] = a[i].replace(__reArray, '');
2646         
2647                                                         // Condition allows simply [] to be passed in
2648                                                         if ( a[i] !== "" ) {
2649                                                                 data = data[ a[i] ];
2650                                                         }
2651                                                         out = [];
2652         
2653                                                         // Get the remainder of the nested object to get
2654                                                         a.splice( 0, i+1 );
2655                                                         innerSrc = a.join('.');
2656         
2657                                                         // Traverse each entry in the array getting the properties requested
2658                                                         if ( $.isArray( data ) ) {
2659                                                                 for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
2660                                                                         out.push( fetchData( data[j], type, innerSrc ) );
2661                                                                 }
2662                                                         }
2663         
2664                                                         // If a string is given in between the array notation indicators, that
2665                                                         // is used to join the strings together, otherwise an array is returned
2666                                                         var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
2667                                                         data = (join==="") ? out : out.join(join);
2668         
2669                                                         // The inner call to fetchData has already traversed through the remainder
2670                                                         // of the source requested, so we exit from the loop
2671                                                         break;
2672                                                 }
2673                                                 else if ( funcNotation )
2674                                                 {
2675                                                         // Function call
2676                                                         a[i] = a[i].replace(__reFn, '');
2677                                                         data = data[ a[i] ]();
2678                                                         continue;
2679                                                 }
2680         
2681                                                 if ( data === null || data[ a[i] ] === undefined )
2682                                                 {
2683                                                         return undefined;
2684                                                 }
2685                                                 data = data[ a[i] ];
2686                                         }
2687                                 }
2688         
2689                                 return data;
2690                         };
2691         
2692                         return function (data, type) { // row and meta also passed, but not used
2693                                 return fetchData( data, type, mSource );
2694                         };
2695                 }
2696                 else
2697                 {
2698                         /* Array or flat object mapping */
2699                         return function (data, type) { // row and meta also passed, but not used
2700                                 return data[mSource];
2701                         };
2702                 }
2703         }
2704         
2705         
2706         /**
2707          * Return a function that can be used to set data from a source object, taking
2708          * into account the ability to use nested objects as a source
2709          *  @param {string|int|function} mSource The data source for the object
2710          *  @returns {function} Data set function
2711          *  @memberof DataTable#oApi
2712          */
2713         function _fnSetObjectDataFn( mSource )
2714         {
2715                 if ( $.isPlainObject( mSource ) )
2716                 {
2717                         /* Unlike get, only the underscore (global) option is used for for
2718                          * setting data since we don't know the type here. This is why an object
2719                          * option is not documented for `mData` (which is read/write), but it is
2720                          * for `mRender` which is read only.
2721                          */
2722                         return _fnSetObjectDataFn( mSource._ );
2723                 }
2724                 else if ( mSource === null )
2725                 {
2726                         /* Nothing to do when the data source is null */
2727                         return function () {};
2728                 }
2729                 else if ( typeof mSource === 'function' )
2730                 {
2731                         return function (data, val, meta) {
2732                                 mSource( data, 'set', val, meta );
2733                         };
2734                 }
2735                 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
2736                               mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
2737                 {
2738                         /* Like the get, we need to get data from a nested object */
2739                         var setData = function (data, val, src) {
2740                                 var a = _fnSplitObjNotation( src ), b;
2741                                 var aLast = a[a.length-1];
2742                                 var arrayNotation, funcNotation, o, innerSrc;
2743         
2744                                 for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
2745                                 {
2746                                         // Check if we are dealing with an array notation request
2747                                         arrayNotation = a[i].match(__reArray);
2748                                         funcNotation = a[i].match(__reFn);
2749         
2750                                         if ( arrayNotation )
2751                                         {
2752                                                 a[i] = a[i].replace(__reArray, '');
2753                                                 data[ a[i] ] = [];
2754         
2755                                                 // Get the remainder of the nested object to set so we can recurse
2756                                                 b = a.slice();
2757                                                 b.splice( 0, i+1 );
2758                                                 innerSrc = b.join('.');
2759         
2760                                                 // Traverse each entry in the array setting the properties requested
2761                                                 if ( $.isArray( val ) )
2762                                                 {
2763                                                         for ( var j=0, jLen=val.length ; j<jLen ; j++ )
2764                                                         {
2765                                                                 o = {};
2766                                                                 setData( o, val[j], innerSrc );
2767                                                                 data[ a[i] ].push( o );
2768                                                         }
2769                                                 }
2770                                                 else
2771                                                 {
2772                                                         // We've been asked to save data to an array, but it
2773                                                         // isn't array data to be saved. Best that can be done
2774                                                         // is to just save the value.
2775                                                         data[ a[i] ] = val;
2776                                                 }
2777         
2778                                                 // The inner call to setData has already traversed through the remainder
2779                                                 // of the source and has set the data, thus we can exit here
2780                                                 return;
2781                                         }
2782                                         else if ( funcNotation )
2783                                         {
2784                                                 // Function call
2785                                                 a[i] = a[i].replace(__reFn, '');
2786                                                 data = data[ a[i] ]( val );
2787                                         }
2788         
2789                                         // If the nested object doesn't currently exist - since we are
2790                                         // trying to set the value - create it
2791                                         if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
2792                                         {
2793                                                 data[ a[i] ] = {};
2794                                         }
2795                                         data = data[ a[i] ];
2796                                 }
2797         
2798                                 // Last item in the input - i.e, the actual set
2799                                 if ( aLast.match(__reFn ) )
2800                                 {
2801                                         // Function call
2802                                         data = data[ aLast.replace(__reFn, '') ]( val );
2803                                 }
2804                                 else
2805                                 {
2806                                         // If array notation is used, we just want to strip it and use the property name
2807                                         // and assign the value. If it isn't used, then we get the result we want anyway
2808                                         data[ aLast.replace(__reArray, '') ] = val;
2809                                 }
2810                         };
2811         
2812                         return function (data, val) { // meta is also passed in, but not used
2813                                 return setData( data, val, mSource );
2814                         };
2815                 }
2816                 else
2817                 {
2818                         /* Array or flat object mapping */
2819                         return function (data, val) { // meta is also passed in, but not used
2820                                 data[mSource] = val;
2821                         };
2822                 }
2823         }
2824         
2825         
2826         /**
2827          * Return an array with the full table data
2828          *  @param {object} oSettings dataTables settings object
2829          *  @returns array {array} aData Master data array
2830          *  @memberof DataTable#oApi
2831          */
2832         function _fnGetDataMaster ( settings )
2833         {
2834                 return _pluck( settings.aoData, '_aData' );
2835         }
2836         
2837         
2838         /**
2839          * Nuke the table
2840          *  @param {object} oSettings dataTables settings object
2841          *  @memberof DataTable#oApi
2842          */
2843         function _fnClearTable( settings )
2844         {
2845                 settings.aoData.length = 0;
2846                 settings.aiDisplayMaster.length = 0;
2847                 settings.aiDisplay.length = 0;
2848                 settings.aIds = {};
2849         }
2850         
2851         
2852          /**
2853          * Take an array of integers (index array) and remove a target integer (value - not
2854          * the key!)
2855          *  @param {array} a Index array to target
2856          *  @param {int} iTarget value to find
2857          *  @memberof DataTable#oApi
2858          */
2859         function _fnDeleteIndex( a, iTarget, splice )
2860         {
2861                 var iTargetIndex = -1;
2862         
2863                 for ( var i=0, iLen=a.length ; i<iLen ; i++ )
2864                 {
2865                         if ( a[i] == iTarget )
2866                         {
2867                                 iTargetIndex = i;
2868                         }
2869                         else if ( a[i] > iTarget )
2870                         {
2871                                 a[i]--;
2872                         }
2873                 }
2874         
2875                 if ( iTargetIndex != -1 && splice === undefined )
2876                 {
2877                         a.splice( iTargetIndex, 1 );
2878                 }
2879         }
2880         
2881         
2882         /**
2883          * Mark cached data as invalid such that a re-read of the data will occur when
2884          * the cached data is next requested. Also update from the data source object.
2885          *
2886          * @param {object} settings DataTables settings object
2887          * @param {int}    rowIdx   Row index to invalidate
2888          * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'
2889          *     or 'data'
2890          * @param {int}    [colIdx] Column index to invalidate. If undefined the whole
2891          *     row will be invalidated
2892          * @memberof DataTable#oApi
2893          *
2894          * @todo For the modularisation of v1.11 this will need to become a callback, so
2895          *   the sort and filter methods can subscribe to it. That will required
2896          *   initialisation options for sorting, which is why it is not already baked in
2897          */
2898         function _fnInvalidate( settings, rowIdx, src, colIdx )
2899         {
2900                 var row = settings.aoData[ rowIdx ];
2901                 var i, ien;
2902                 var cellWrite = function ( cell, col ) {
2903                         // This is very frustrating, but in IE if you just write directly
2904                         // to innerHTML, and elements that are overwritten are GC'ed,
2905                         // even if there is a reference to them elsewhere
2906                         while ( cell.childNodes.length ) {
2907                                 cell.removeChild( cell.firstChild );
2908                         }
2909         
2910                         cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );
2911                 };
2912         
2913                 // Are we reading last data from DOM or the data object?
2914                 if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
2915                         // Read the data from the DOM
2916                         row._aData = _fnGetRowElements(
2917                                         settings, row, colIdx, colIdx === undefined ? undefined : row._aData
2918                                 )
2919                                 .data;
2920                 }
2921                 else {
2922                         // Reading from data object, update the DOM
2923                         var cells = row.anCells;
2924         
2925                         if ( cells ) {
2926                                 if ( colIdx !== undefined ) {
2927                                         cellWrite( cells[colIdx], colIdx );
2928                                 }
2929                                 else {
2930                                         for ( i=0, ien=cells.length ; i<ien ; i++ ) {
2931                                                 cellWrite( cells[i], i );
2932                                         }
2933                                 }
2934                         }
2935                 }
2936         
2937                 // For both row and cell invalidation, the cached data for sorting and
2938                 // filtering is nulled out
2939                 row._aSortData = null;
2940                 row._aFilterData = null;
2941         
2942                 // Invalidate the type for a specific column (if given) or all columns since
2943                 // the data might have changed
2944                 var cols = settings.aoColumns;
2945                 if ( colIdx !== undefined ) {
2946                         cols[ colIdx ].sType = null;
2947                 }
2948                 else {
2949                         for ( i=0, ien=cols.length ; i<ien ; i++ ) {
2950                                 cols[i].sType = null;
2951                         }
2952         
2953                         // Update DataTables special `DT_*` attributes for the row
2954                         _fnRowAttributes( settings, row );
2955                 }
2956         }
2957         
2958         
2959         /**
2960          * Build a data source object from an HTML row, reading the contents of the
2961          * cells that are in the row.
2962          *
2963          * @param {object} settings DataTables settings object
2964          * @param {node|object} TR element from which to read data or existing row
2965          *   object from which to re-read the data from the cells
2966          * @param {int} [colIdx] Optional column index
2967          * @param {array|object} [d] Data source object. If `colIdx` is given then this
2968          *   parameter should also be given and will be used to write the data into.
2969          *   Only the column in question will be written
2970          * @returns {object} Object with two parameters: `data` the data read, in
2971          *   document order, and `cells` and array of nodes (they can be useful to the
2972          *   caller, so rather than needing a second traversal to get them, just return
2973          *   them from here).
2974          * @memberof DataTable#oApi
2975          */
2976         function _fnGetRowElements( settings, row, colIdx, d )
2977         {
2978                 var
2979                         tds = [],
2980                         td = row.firstChild,
2981                         name, col, o, i=0, contents,
2982                         columns = settings.aoColumns,
2983                         objectRead = settings._rowReadObject;
2984         
2985                 // Allow the data object to be passed in, or construct
2986                 d = d !== undefined ?
2987                         d :
2988                         objectRead ?
2989                                 {} :
2990                                 [];
2991         
2992                 var attr = function ( str, td  ) {
2993                         if ( typeof str === 'string' ) {
2994                                 var idx = str.indexOf('@');
2995         
2996                                 if ( idx !== -1 ) {
2997                                         var attr = str.substring( idx+1 );
2998                                         var setter = _fnSetObjectDataFn( str );
2999                                         setter( d, td.getAttribute( attr ) );
3000                                 }
3001                         }
3002                 };
3003         
3004                 // Read data from a cell and store into the data object
3005                 var cellProcess = function ( cell ) {
3006                         if ( colIdx === undefined || colIdx === i ) {
3007                                 col = columns[i];
3008                                 contents = $.trim(cell.innerHTML);
3009         
3010                                 if ( col && col._bAttrSrc ) {
3011                                         var setter = _fnSetObjectDataFn( col.mData._ );
3012                                         setter( d, contents );
3013         
3014                                         attr( col.mData.sort, cell );
3015                                         attr( col.mData.type, cell );
3016                                         attr( col.mData.filter, cell );
3017                                 }
3018                                 else {
3019                                         // Depending on the `data` option for the columns the data can
3020                                         // be read to either an object or an array.
3021                                         if ( objectRead ) {
3022                                                 if ( ! col._setter ) {
3023                                                         // Cache the setter function
3024                                                         col._setter = _fnSetObjectDataFn( col.mData );
3025                                                 }
3026                                                 col._setter( d, contents );
3027                                         }
3028                                         else {
3029                                                 d[i] = contents;
3030                                         }
3031                                 }
3032                         }
3033         
3034                         i++;
3035                 };
3036         
3037                 if ( td ) {
3038                         // `tr` element was passed in
3039                         while ( td ) {
3040                                 name = td.nodeName.toUpperCase();
3041         
3042                                 if ( name == "TD" || name == "TH" ) {
3043                                         cellProcess( td );
3044                                         tds.push( td );
3045                                 }
3046         
3047                                 td = td.nextSibling;
3048                         }
3049                 }
3050                 else {
3051                         // Existing row object passed in
3052                         tds = row.anCells;
3053         
3054                         for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
3055                                 cellProcess( tds[j] );
3056                         }
3057                 }
3058         
3059                 // Read the ID from the DOM if present
3060                 var rowNode = row.firstChild ? row : row.nTr;
3061         
3062                 if ( rowNode ) {
3063                         var id = rowNode.getAttribute( 'id' );
3064         
3065                         if ( id ) {
3066                                 _fnSetObjectDataFn( settings.rowId )( d, id );
3067                         }
3068                 }
3069         
3070                 return {
3071                         data: d,
3072                         cells: tds
3073                 };
3074         }
3075         /**
3076          * Create a new TR element (and it's TD children) for a row
3077          *  @param {object} oSettings dataTables settings object
3078          *  @param {int} iRow Row to consider
3079          *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
3080          *    DataTables will create a row automatically
3081          *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
3082          *    if nTr is.
3083          *  @memberof DataTable#oApi
3084          */
3085         function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
3086         {
3087                 var
3088                         row = oSettings.aoData[iRow],
3089                         rowData = row._aData,
3090                         cells = [],
3091                         nTr, nTd, oCol,
3092                         i, iLen;
3093         
3094                 if ( row.nTr === null )
3095                 {
3096                         nTr = nTrIn || document.createElement('tr');
3097         
3098                         row.nTr = nTr;
3099                         row.anCells = cells;
3100         
3101                         /* Use a private property on the node to allow reserve mapping from the node
3102                          * to the aoData array for fast look up
3103                          */
3104                         nTr._DT_RowIndex = iRow;
3105         
3106                         /* Special parameters can be given by the data source to be used on the row */
3107                         _fnRowAttributes( oSettings, row );
3108         
3109                         /* Process each column */
3110                         for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
3111                         {
3112                                 oCol = oSettings.aoColumns[i];
3113         
3114                                 nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
3115                                 nTd._DT_CellIndex = {
3116                                         row: iRow,
3117                                         column: i
3118                                 };
3119                                 
3120                                 cells.push( nTd );
3121         
3122                                 // Need to create the HTML if new, or if a rendering function is defined
3123                                 if ( (!nTrIn || oCol.mRender || oCol.mData !== i) &&
3124                                          (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')
3125                                 ) {
3126                                         nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
3127                                 }
3128         
3129                                 /* Add user defined class */
3130                                 if ( oCol.sClass )
3131                                 {
3132                                         nTd.className += ' '+oCol.sClass;
3133                                 }
3134         
3135                                 // Visibility - add or remove as required
3136                                 if ( oCol.bVisible && ! nTrIn )
3137                                 {
3138                                         nTr.appendChild( nTd );
3139                                 }
3140                                 else if ( ! oCol.bVisible && nTrIn )
3141                                 {
3142                                         nTd.parentNode.removeChild( nTd );
3143                                 }
3144         
3145                                 if ( oCol.fnCreatedCell )
3146                                 {
3147                                         oCol.fnCreatedCell.call( oSettings.oInstance,
3148                                                 nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
3149                                         );
3150                                 }
3151                         }
3152         
3153                         _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
3154                 }
3155         
3156                 // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
3157                 // and deployed
3158                 row.nTr.setAttribute( 'role', 'row' );
3159         }
3160         
3161         
3162         /**
3163          * Add attributes to a row based on the special `DT_*` parameters in a data
3164          * source object.
3165          *  @param {object} settings DataTables settings object
3166          *  @param {object} DataTables row object for the row to be modified
3167          *  @memberof DataTable#oApi
3168          */
3169         function _fnRowAttributes( settings, row )
3170         {
3171                 var tr = row.nTr;
3172                 var data = row._aData;
3173         
3174                 if ( tr ) {
3175                         var id = settings.rowIdFn( data );
3176         
3177                         if ( id ) {
3178                                 tr.id = id;
3179                         }
3180         
3181                         if ( data.DT_RowClass ) {
3182                                 // Remove any classes added by DT_RowClass before
3183                                 var a = data.DT_RowClass.split(' ');
3184                                 row.__rowc = row.__rowc ?
3185                                         _unique( row.__rowc.concat( a ) ) :
3186                                         a;
3187         
3188                                 $(tr)
3189                                         .removeClass( row.__rowc.join(' ') )
3190                                         .addClass( data.DT_RowClass );
3191                         }
3192         
3193                         if ( data.DT_RowAttr ) {
3194                                 $(tr).attr( data.DT_RowAttr );
3195                         }
3196         
3197                         if ( data.DT_RowData ) {
3198                                 $(tr).data( data.DT_RowData );
3199                         }
3200                 }
3201         }
3202         
3203         
3204         /**
3205          * Create the HTML header for the table
3206          *  @param {object} oSettings dataTables settings object
3207          *  @memberof DataTable#oApi
3208          */
3209         function _fnBuildHead( oSettings )
3210         {
3211                 var i, ien, cell, row, column;
3212                 var thead = oSettings.nTHead;
3213                 var tfoot = oSettings.nTFoot;
3214                 var createHeader = $('th, td', thead).length === 0;
3215                 var classes = oSettings.oClasses;
3216                 var columns = oSettings.aoColumns;
3217         
3218                 if ( createHeader ) {
3219                         row = $('<tr/>').appendTo( thead );
3220                 }
3221         
3222                 for ( i=0, ien=columns.length ; i<ien ; i++ ) {
3223                         column = columns[i];
3224                         cell = $( column.nTh ).addClass( column.sClass );
3225         
3226                         if ( createHeader ) {
3227                                 cell.appendTo( row );
3228                         }
3229         
3230                         // 1.11 move into sorting
3231                         if ( oSettings.oFeatures.bSort ) {
3232                                 cell.addClass( column.sSortingClass );
3233         
3234                                 if ( column.bSortable !== false ) {
3235                                         cell
3236                                                 .attr( 'tabindex', oSettings.iTabIndex )
3237                                                 .attr( 'aria-controls', oSettings.sTableId );
3238         
3239                                         _fnSortAttachListener( oSettings, column.nTh, i );
3240                                 }
3241                         }
3242         
3243                         if ( column.sTitle != cell[0].innerHTML ) {
3244                                 cell.html( column.sTitle );
3245                         }
3246         
3247                         _fnRenderer( oSettings, 'header' )(
3248                                 oSettings, cell, column, classes
3249                         );
3250                 }
3251         
3252                 if ( createHeader ) {
3253                         _fnDetectHeader( oSettings.aoHeader, thead );
3254                 }
3255                 
3256                 /* ARIA role for the rows */
3257                 $(thead).find('>tr').attr('role', 'row');
3258         
3259                 /* Deal with the footer - add classes if required */
3260                 $(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
3261                 $(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
3262         
3263                 // Cache the footer cells. Note that we only take the cells from the first
3264                 // row in the footer. If there is more than one row the user wants to
3265                 // interact with, they need to use the table().foot() method. Note also this
3266                 // allows cells to be used for multiple columns using colspan
3267                 if ( tfoot !== null ) {
3268                         var cells = oSettings.aoFooter[0];
3269         
3270                         for ( i=0, ien=cells.length ; i<ien ; i++ ) {
3271                                 column = columns[i];
3272                                 column.nTf = cells[i].cell;
3273         
3274                                 if ( column.sClass ) {
3275                                         $(column.nTf).addClass( column.sClass );
3276                                 }
3277                         }
3278                 }
3279         }
3280         
3281         
3282         /**
3283          * Draw the header (or footer) element based on the column visibility states. The
3284          * methodology here is to use the layout array from _fnDetectHeader, modified for
3285          * the instantaneous column visibility, to construct the new layout. The grid is
3286          * traversed over cell at a time in a rows x columns grid fashion, although each
3287          * cell insert can cover multiple elements in the grid - which is tracks using the
3288          * aApplied array. Cell inserts in the grid will only occur where there isn't
3289          * already a cell in that position.
3290          *  @param {object} oSettings dataTables settings object
3291          *  @param array {objects} aoSource Layout array from _fnDetectHeader
3292          *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
3293          *  @memberof DataTable#oApi
3294          */
3295         function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
3296         {
3297                 var i, iLen, j, jLen, k, kLen, n, nLocalTr;
3298                 var aoLocal = [];
3299                 var aApplied = [];
3300                 var iColumns = oSettings.aoColumns.length;
3301                 var iRowspan, iColspan;
3302         
3303                 if ( ! aoSource )
3304                 {
3305                         return;
3306                 }
3307         
3308                 if (  bIncludeHidden === undefined )
3309                 {
3310                         bIncludeHidden = false;
3311                 }
3312         
3313                 /* Make a copy of the master layout array, but without the visible columns in it */
3314                 for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
3315                 {
3316                         aoLocal[i] = aoSource[i].slice();
3317                         aoLocal[i].nTr = aoSource[i].nTr;
3318         
3319                         /* Remove any columns which are currently hidden */
3320                         for ( j=iColumns-1 ; j>=0 ; j-- )
3321                         {
3322                                 if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
3323                                 {
3324                                         aoLocal[i].splice( j, 1 );
3325                                 }
3326                         }
3327         
3328                         /* Prep the applied array - it needs an element for each row */
3329                         aApplied.push( [] );
3330                 }
3331         
3332                 for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
3333                 {
3334                         nLocalTr = aoLocal[i].nTr;
3335         
3336                         /* All cells are going to be replaced, so empty out the row */
3337                         if ( nLocalTr )
3338                         {
3339                                 while( (n = nLocalTr.firstChild) )
3340                                 {
3341                                         nLocalTr.removeChild( n );
3342                                 }
3343                         }
3344         
3345                         for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
3346                         {
3347                                 iRowspan = 1;
3348                                 iColspan = 1;
3349         
3350                                 /* Check to see if there is already a cell (row/colspan) covering our target
3351                                  * insert point. If there is, then there is nothing to do.
3352                                  */
3353                                 if ( aApplied[i][j] === undefined )
3354                                 {
3355                                         nLocalTr.appendChild( aoLocal[i][j].cell );
3356                                         aApplied[i][j] = 1;
3357         
3358                                         /* Expand the cell to cover as many rows as needed */
3359                                         while ( aoLocal[i+iRowspan] !== undefined &&
3360                                                 aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
3361                                         {
3362                                                 aApplied[i+iRowspan][j] = 1;
3363                                                 iRowspan++;
3364                                         }
3365         
3366                                         /* Expand the cell to cover as many columns as needed */
3367                                         while ( aoLocal[i][j+iColspan] !== undefined &&
3368                                                 aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
3369                                         {
3370                                                 /* Must update the applied array over the rows for the columns */
3371                                                 for ( k=0 ; k<iRowspan ; k++ )
3372                                                 {
3373                                                         aApplied[i+k][j+iColspan] = 1;
3374                                                 }
3375                                                 iColspan++;
3376                                         }
3377         
3378                                         /* Do the actual expansion in the DOM */
3379                                         $(aoLocal[i][j].cell)
3380                                                 .attr('rowspan', iRowspan)
3381                                                 .attr('colspan', iColspan);
3382                                 }
3383                         }
3384                 }
3385         }
3386         
3387         
3388         /**
3389          * Insert the required TR nodes into the table for display
3390          *  @param {object} oSettings dataTables settings object
3391          *  @memberof DataTable#oApi
3392          */
3393         function _fnDraw( oSettings )
3394         {
3395                 /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
3396                 var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
3397                 if ( $.inArray( false, aPreDraw ) !== -1 )
3398                 {
3399                         _fnProcessingDisplay( oSettings, false );
3400                         return;
3401                 }
3402         
3403                 var i, iLen, n;
3404                 var anRows = [];
3405                 var iRowCount = 0;
3406                 var asStripeClasses = oSettings.asStripeClasses;
3407                 var iStripes = asStripeClasses.length;
3408                 var iOpenRows = oSettings.aoOpenRows.length;
3409                 var oLang = oSettings.oLanguage;
3410                 var iInitDisplayStart = oSettings.iInitDisplayStart;
3411                 var bServerSide = _fnDataSource( oSettings ) == 'ssp';
3412                 var aiDisplay = oSettings.aiDisplay;
3413         
3414                 oSettings.bDrawing = true;
3415         
3416                 /* Check and see if we have an initial draw position from state saving */
3417                 if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
3418                 {
3419                         oSettings._iDisplayStart = bServerSide ?
3420                                 iInitDisplayStart :
3421                                 iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
3422                                         0 :
3423                                         iInitDisplayStart;
3424         
3425                         oSettings.iInitDisplayStart = -1;
3426                 }
3427         
3428                 var iDisplayStart = oSettings._iDisplayStart;
3429                 var iDisplayEnd = oSettings.fnDisplayEnd();
3430         
3431                 /* Server-side processing draw intercept */
3432                 if ( oSettings.bDeferLoading )
3433                 {
3434                         oSettings.bDeferLoading = false;
3435                         oSettings.iDraw++;
3436                         _fnProcessingDisplay( oSettings, false );
3437                 }
3438                 else if ( !bServerSide )
3439                 {
3440                         oSettings.iDraw++;
3441                 }
3442                 else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
3443                 {
3444                         return;
3445                 }
3446         
3447                 if ( aiDisplay.length !== 0 )
3448                 {
3449                         var iStart = bServerSide ? 0 : iDisplayStart;
3450                         var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
3451         
3452                         for ( var j=iStart ; j<iEnd ; j++ )
3453                         {
3454                                 var iDataIndex = aiDisplay[j];
3455                                 var aoData = oSettings.aoData[ iDataIndex ];
3456                                 if ( aoData.nTr === null )
3457                                 {
3458                                         _fnCreateTr( oSettings, iDataIndex );
3459                                 }
3460         
3461                                 var nRow = aoData.nTr;
3462         
3463                                 /* Remove the old striping classes and then add the new one */
3464                                 if ( iStripes !== 0 )
3465                                 {
3466                                         var sStripe = asStripeClasses[ iRowCount % iStripes ];
3467                                         if ( aoData._sRowStripe != sStripe )
3468                                         {
3469                                                 $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
3470                                                 aoData._sRowStripe = sStripe;
3471                                         }
3472                                 }
3473         
3474                                 // Row callback functions - might want to manipulate the row
3475                                 // iRowCount and j are not currently documented. Are they at all
3476                                 // useful?
3477                                 _fnCallbackFire( oSettings, 'aoRowCallback', null,
3478                                         [nRow, aoData._aData, iRowCount, j] );
3479         
3480                                 anRows.push( nRow );
3481                                 iRowCount++;
3482                         }
3483                 }
3484                 else
3485                 {
3486                         /* Table is empty - create a row with an empty message in it */
3487                         var sZero = oLang.sZeroRecords;
3488                         if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
3489                         {
3490                                 sZero = oLang.sLoadingRecords;
3491                         }
3492                         else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
3493                         {
3494                                 sZero = oLang.sEmptyTable;
3495                         }
3496         
3497                         anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
3498                                 .append( $('<td />', {
3499                                         'valign':  'top',
3500                                         'colSpan': _fnVisbleColumns( oSettings ),
3501                                         'class':   oSettings.oClasses.sRowEmpty
3502                                 } ).html( sZero ) )[0];
3503                 }
3504         
3505                 /* Header and footer callbacks */
3506                 _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
3507                         _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3508         
3509                 _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
3510                         _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
3511         
3512                 var body = $(oSettings.nTBody);
3513         
3514                 body.children().detach();
3515                 body.append( $(anRows) );
3516         
3517                 /* Call all required callback functions for the end of a draw */
3518                 _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
3519         
3520                 /* Draw is complete, sorting and filtering must be as well */
3521                 oSettings.bSorted = false;
3522                 oSettings.bFiltered = false;
3523                 oSettings.bDrawing = false;
3524         }
3525         
3526         
3527         /**
3528          * Redraw the table - taking account of the various features which are enabled
3529          *  @param {object} oSettings dataTables settings object
3530          *  @param {boolean} [holdPosition] Keep the current paging position. By default
3531          *    the paging is reset to the first page
3532          *  @memberof DataTable#oApi
3533          */
3534         function _fnReDraw( settings, holdPosition )
3535         {
3536                 var
3537                         features = settings.oFeatures,
3538                         sort     = features.bSort,
3539                         filter   = features.bFilter;
3540         
3541                 if ( sort ) {
3542                         _fnSort( settings );
3543                 }
3544         
3545                 if ( filter ) {
3546                         _fnFilterComplete( settings, settings.oPreviousSearch );
3547                 }
3548                 else {
3549                         // No filtering, so we want to just use the display master
3550                         settings.aiDisplay = settings.aiDisplayMaster.slice();
3551                 }
3552         
3553                 if ( holdPosition !== true ) {
3554                         settings._iDisplayStart = 0;
3555                 }
3556         
3557                 // Let any modules know about the draw hold position state (used by
3558                 // scrolling internally)
3559                 settings._drawHold = holdPosition;
3560         
3561                 _fnDraw( settings );
3562         
3563                 settings._drawHold = false;
3564         }
3565         
3566         
3567         /**
3568          * Add the options to the page HTML for the table
3569          *  @param {object} oSettings dataTables settings object
3570          *  @memberof DataTable#oApi
3571          */
3572         function _fnAddOptionsHtml ( oSettings )
3573         {
3574                 var classes = oSettings.oClasses;
3575                 var table = $(oSettings.nTable);
3576                 var holding = $('<div/>').insertBefore( table ); // Holding element for speed
3577                 var features = oSettings.oFeatures;
3578         
3579                 // All DataTables are wrapped in a div
3580                 var insert = $('<div/>', {
3581                         id:      oSettings.sTableId+'_wrapper',
3582                         'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
3583                 } );
3584         
3585                 oSettings.nHolding = holding[0];
3586                 oSettings.nTableWrapper = insert[0];
3587                 oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
3588         
3589                 /* Loop over the user set positioning and place the elements as needed */
3590                 var aDom = oSettings.sDom.split('');
3591                 var featureNode, cOption, nNewNode, cNext, sAttr, j;
3592                 for ( var i=0 ; i<aDom.length ; i++ )
3593                 {
3594                         featureNode = null;
3595                         cOption = aDom[i];
3596         
3597                         if ( cOption == '<' )
3598                         {
3599                                 /* New container div */
3600                                 nNewNode = $('<div/>')[0];
3601         
3602                                 /* Check to see if we should append an id and/or a class name to the container */
3603                                 cNext = aDom[i+1];
3604                                 if ( cNext == "'" || cNext == '"' )
3605                                 {
3606                                         sAttr = "";
3607                                         j = 2;
3608                                         while ( aDom[i+j] != cNext )
3609                                         {
3610                                                 sAttr += aDom[i+j];
3611                                                 j++;
3612                                         }
3613         
3614                                         /* Replace jQuery UI constants @todo depreciated */
3615                                         if ( sAttr == "H" )
3616                                         {
3617                                                 sAttr = classes.sJUIHeader;
3618                                         }
3619                                         else if ( sAttr == "F" )
3620                                         {
3621                                                 sAttr = classes.sJUIFooter;
3622                                         }
3623         
3624                                         /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
3625                                          * breaks the string into parts and applies them as needed
3626                                          */
3627                                         if ( sAttr.indexOf('.') != -1 )
3628                                         {
3629                                                 var aSplit = sAttr.split('.');
3630                                                 nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
3631                                                 nNewNode.className = aSplit[1];
3632                                         }
3633                                         else if ( sAttr.charAt(0) == "#" )
3634                                         {
3635                                                 nNewNode.id = sAttr.substr(1, sAttr.length-1);
3636                                         }
3637                                         else
3638                                         {
3639                                                 nNewNode.className = sAttr;
3640                                         }
3641         
3642                                         i += j; /* Move along the position array */
3643                                 }
3644         
3645                                 insert.append( nNewNode );
3646                                 insert = $(nNewNode);
3647                         }
3648                         else if ( cOption == '>' )
3649                         {
3650                                 /* End container div */
3651                                 insert = insert.parent();
3652                         }
3653                         // @todo Move options into their own plugins?
3654                         else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
3655                         {
3656                                 /* Length */
3657                                 featureNode = _fnFeatureHtmlLength( oSettings );
3658                         }
3659                         else if ( cOption == 'f' && features.bFilter )
3660                         {
3661                                 /* Filter */
3662                                 featureNode = _fnFeatureHtmlFilter( oSettings );
3663                         }
3664                         else if ( cOption == 'r' && features.bProcessing )
3665                         {
3666                                 /* pRocessing */
3667                                 featureNode = _fnFeatureHtmlProcessing( oSettings );
3668                         }
3669                         else if ( cOption == 't' )
3670                         {
3671                                 /* Table */
3672                                 featureNode = _fnFeatureHtmlTable( oSettings );
3673                         }
3674                         else if ( cOption ==  'i' && features.bInfo )
3675                         {
3676                                 /* Info */
3677                                 featureNode = _fnFeatureHtmlInfo( oSettings );
3678                         }
3679                         else if ( cOption == 'p' && features.bPaginate )
3680                         {
3681                                 /* Pagination */
3682                                 featureNode = _fnFeatureHtmlPaginate( oSettings );
3683                         }
3684                         else if ( DataTable.ext.feature.length !== 0 )
3685                         {
3686                                 /* Plug-in features */
3687                                 var aoFeatures = DataTable.ext.feature;
3688                                 for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
3689                                 {
3690                                         if ( cOption == aoFeatures[k].cFeature )
3691                                         {
3692                                                 featureNode = aoFeatures[k].fnInit( oSettings );
3693                                                 break;
3694                                         }
3695                                 }
3696                         }
3697         
3698                         /* Add to the 2D features array */
3699                         if ( featureNode )
3700                         {
3701                                 var aanFeatures = oSettings.aanFeatures;
3702         
3703                                 if ( ! aanFeatures[cOption] )
3704                                 {
3705                                         aanFeatures[cOption] = [];
3706                                 }
3707         
3708                                 aanFeatures[cOption].push( featureNode );
3709                                 insert.append( featureNode );
3710                         }
3711                 }
3712         
3713                 /* Built our DOM structure - replace the holding div with what we want */
3714                 holding.replaceWith( insert );
3715                 oSettings.nHolding = null;
3716         }
3717         
3718         
3719         /**
3720          * Use the DOM source to create up an array of header cells. The idea here is to
3721          * create a layout grid (array) of rows x columns, which contains a reference
3722          * to the cell that that point in the grid (regardless of col/rowspan), such that
3723          * any column / row could be removed and the new grid constructed
3724          *  @param array {object} aLayout Array to store the calculated layout in
3725          *  @param {node} nThead The header/footer element for the table
3726          *  @memberof DataTable#oApi
3727          */
3728         function _fnDetectHeader ( aLayout, nThead )
3729         {
3730                 var nTrs = $(nThead).children('tr');
3731                 var nTr, nCell;
3732                 var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
3733                 var bUnique;
3734                 var fnShiftCol = function ( a, i, j ) {
3735                         var k = a[i];
3736                         while ( k[j] ) {
3737                                 j++;
3738                         }
3739                         return j;
3740                 };
3741         
3742                 aLayout.splice( 0, aLayout.length );
3743         
3744                 /* We know how many rows there are in the layout - so prep it */
3745                 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3746                 {
3747                         aLayout.push( [] );
3748                 }
3749         
3750                 /* Calculate a layout array */
3751                 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
3752                 {
3753                         nTr = nTrs[i];
3754                         iColumn = 0;
3755         
3756                         /* For every cell in the row... */
3757                         nCell = nTr.firstChild;
3758                         while ( nCell ) {
3759                                 if ( nCell.nodeName.toUpperCase() == "TD" ||
3760                                      nCell.nodeName.toUpperCase() == "TH" )
3761                                 {
3762                                         /* Get the col and rowspan attributes from the DOM and sanitise them */
3763                                         iColspan = nCell.getAttribute('colspan') * 1;
3764                                         iRowspan = nCell.getAttribute('rowspan') * 1;
3765                                         iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
3766                                         iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
3767         
3768                                         /* There might be colspan cells already in this row, so shift our target
3769                                          * accordingly
3770                                          */
3771                                         iColShifted = fnShiftCol( aLayout, i, iColumn );
3772         
3773                                         /* Cache calculation for unique columns */
3774                                         bUnique = iColspan === 1 ? true : false;
3775         
3776                                         /* If there is col / rowspan, copy the information into the layout grid */
3777                                         for ( l=0 ; l<iColspan ; l++ )
3778                                         {
3779                                                 for ( k=0 ; k<iRowspan ; k++ )
3780                                                 {
3781                                                         aLayout[i+k][iColShifted+l] = {
3782                                                                 "cell": nCell,
3783                                                                 "unique": bUnique
3784                                                         };
3785                                                         aLayout[i+k].nTr = nTr;
3786                                                 }
3787                                         }
3788                                 }
3789                                 nCell = nCell.nextSibling;
3790                         }
3791                 }
3792         }
3793         
3794         
3795         /**
3796          * Get an array of unique th elements, one for each column
3797          *  @param {object} oSettings dataTables settings object
3798          *  @param {node} nHeader automatically detect the layout from this node - optional
3799          *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
3800          *  @returns array {node} aReturn list of unique th's
3801          *  @memberof DataTable#oApi
3802          */
3803         function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
3804         {
3805                 var aReturn = [];
3806                 if ( !aLayout )
3807                 {
3808                         aLayout = oSettings.aoHeader;
3809                         if ( nHeader )
3810                         {
3811                                 aLayout = [];
3812                                 _fnDetectHeader( aLayout, nHeader );
3813                         }
3814                 }
3815         
3816                 for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
3817                 {
3818                         for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
3819                         {
3820                                 if ( aLayout[i][j].unique &&
3821                                          (!aReturn[j] || !oSettings.bSortCellsTop) )
3822                                 {
3823                                         aReturn[j] = aLayout[i][j].cell;
3824                                 }
3825                         }
3826                 }
3827         
3828                 return aReturn;
3829         }
3830         
3831         /**
3832          * Create an Ajax call based on the table's settings, taking into account that
3833          * parameters can have multiple forms, and backwards compatibility.
3834          *
3835          * @param {object} oSettings dataTables settings object
3836          * @param {array} data Data to send to the server, required by
3837          *     DataTables - may be augmented by developer callbacks
3838          * @param {function} fn Callback function to run when data is obtained
3839          */
3840         function _fnBuildAjax( oSettings, data, fn )
3841         {
3842                 // Compatibility with 1.9-, allow fnServerData and event to manipulate
3843                 _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
3844         
3845                 // Convert to object based for 1.10+ if using the old array scheme which can
3846                 // come from server-side processing or serverParams
3847                 if ( data && $.isArray(data) ) {
3848                         var tmp = {};
3849                         var rbracket = /(.*?)\[\]$/;
3850         
3851                         $.each( data, function (key, val) {
3852                                 var match = val.name.match(rbracket);
3853         
3854                                 if ( match ) {
3855                                         // Support for arrays
3856                                         var name = match[0];
3857         
3858                                         if ( ! tmp[ name ] ) {
3859                                                 tmp[ name ] = [];
3860                                         }
3861                                         tmp[ name ].push( val.value );
3862                                 }
3863                                 else {
3864                                         tmp[val.name] = val.value;
3865                                 }
3866                         } );
3867                         data = tmp;
3868                 }
3869         
3870                 var ajaxData;
3871                 var ajax = oSettings.ajax;
3872                 var instance = oSettings.oInstance;
3873                 var callback = function ( json ) {
3874                         _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );
3875                         fn( json );
3876                 };
3877         
3878                 if ( $.isPlainObject( ajax ) && ajax.data )
3879                 {
3880                         ajaxData = ajax.data;
3881         
3882                         var newData = $.isFunction( ajaxData ) ?
3883                                 ajaxData( data, oSettings ) :  // fn can manipulate data or return
3884                                 ajaxData;                      // an object object or array to merge
3885         
3886                         // If the function returned something, use that alone
3887                         data = $.isFunction( ajaxData ) && newData ?
3888                                 newData :
3889                                 $.extend( true, data, newData );
3890         
3891                         // Remove the data property as we've resolved it already and don't want
3892                         // jQuery to do it again (it is restored at the end of the function)
3893                         delete ajax.data;
3894                 }
3895         
3896                 var baseAjax = {
3897                         "data": data,
3898                         "success": function (json) {
3899                                 var error = json.error || json.sError;
3900                                 if ( error ) {
3901                                         _fnLog( oSettings, 0, error );
3902                                 }
3903         
3904                                 oSettings.json = json;
3905                                 callback( json );
3906                         },
3907                         "dataType": "json",
3908                         "cache": false,
3909                         "type": oSettings.sServerMethod,
3910                         "error": function (xhr, error, thrown) {
3911                                 var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );
3912         
3913                                 if ( $.inArray( true, ret ) === -1 ) {
3914                                         if ( error == "parsererror" ) {
3915                                                 _fnLog( oSettings, 0, 'Invalid JSON response', 1 );
3916                                         }
3917                                         else if ( xhr.readyState === 4 ) {
3918                                                 _fnLog( oSettings, 0, 'Ajax error', 7 );
3919                                         }
3920                                 }
3921         
3922                                 _fnProcessingDisplay( oSettings, false );
3923                         }
3924                 };
3925         
3926                 // Store the data submitted for the API
3927                 oSettings.oAjaxData = data;
3928         
3929                 // Allow plug-ins and external processes to modify the data
3930                 _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
3931         
3932                 if ( oSettings.fnServerData )
3933                 {
3934                         // DataTables 1.9- compatibility
3935                         oSettings.fnServerData.call( instance,
3936                                 oSettings.sAjaxSource,
3937                                 $.map( data, function (val, key) { // Need to convert back to 1.9 trad format
3938                                         return { name: key, value: val };
3939                                 } ),
3940                                 callback,
3941                                 oSettings
3942                         );
3943                 }
3944                 else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
3945                 {
3946                         // DataTables 1.9- compatibility
3947                         oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
3948                                 url: ajax || oSettings.sAjaxSource
3949                         } ) );
3950                 }
3951                 else if ( $.isFunction( ajax ) )
3952                 {
3953                         // Is a function - let the caller define what needs to be done
3954                         oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );
3955                 }
3956                 else
3957                 {
3958                         // Object to extend the base settings
3959                         oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
3960         
3961                         // Restore for next time around
3962                         ajax.data = ajaxData;
3963                 }
3964         }
3965         
3966         
3967         /**
3968          * Update the table using an Ajax call
3969          *  @param {object} settings dataTables settings object
3970          *  @returns {boolean} Block the table drawing or not
3971          *  @memberof DataTable#oApi
3972          */
3973         function _fnAjaxUpdate( settings )
3974         {
3975                 if ( settings.bAjaxDataGet ) {
3976                         settings.iDraw++;
3977                         _fnProcessingDisplay( settings, true );
3978         
3979                         _fnBuildAjax(
3980                                 settings,
3981                                 _fnAjaxParameters( settings ),
3982                                 function(json) {
3983                                         _fnAjaxUpdateDraw( settings, json );
3984                                 }
3985                         );
3986         
3987                         return false;
3988                 }
3989                 return true;
3990         }
3991         
3992         
3993         /**
3994          * Build up the parameters in an object needed for a server-side processing
3995          * request. Note that this is basically done twice, is different ways - a modern
3996          * method which is used by default in DataTables 1.10 which uses objects and
3997          * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
3998          * the sAjaxSource option is used in the initialisation, or the legacyAjax
3999          * option is set.
4000          *  @param {object} oSettings dataTables settings object
4001          *  @returns {bool} block the table drawing or not
4002          *  @memberof DataTable#oApi
4003          */
4004         function _fnAjaxParameters( settings )
4005         {
4006                 var
4007                         columns = settings.aoColumns,
4008                         columnCount = columns.length,
4009                         features = settings.oFeatures,
4010                         preSearch = settings.oPreviousSearch,
4011                         preColSearch = settings.aoPreSearchCols,
4012                         i, data = [], dataProp, column, columnSearch,
4013                         sort = _fnSortFlatten( settings ),
4014                         displayStart = settings._iDisplayStart,
4015                         displayLength = features.bPaginate !== false ?
4016                                 settings._iDisplayLength :
4017                                 -1;
4018         
4019                 var param = function ( name, value ) {
4020                         data.push( { 'name': name, 'value': value } );
4021                 };
4022         
4023                 // DataTables 1.9- compatible method
4024                 param( 'sEcho',          settings.iDraw );
4025                 param( 'iColumns',       columnCount );
4026                 param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
4027                 param( 'iDisplayStart',  displayStart );
4028                 param( 'iDisplayLength', displayLength );
4029         
4030                 // DataTables 1.10+ method
4031                 var d = {
4032                         draw:    settings.iDraw,
4033                         columns: [],
4034                         order:   [],
4035                         start:   displayStart,
4036                         length:  displayLength,
4037                         search:  {
4038                                 value: preSearch.sSearch,
4039                                 regex: preSearch.bRegex
4040                         }
4041                 };
4042         
4043                 for ( i=0 ; i<columnCount ; i++ ) {
4044                         column = columns[i];
4045                         columnSearch = preColSearch[i];
4046                         dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
4047         
4048                         d.columns.push( {
4049                                 data:       dataProp,
4050                                 name:       column.sName,
4051                                 searchable: column.bSearchable,
4052                                 orderable:  column.bSortable,
4053                                 search:     {
4054                                         value: columnSearch.sSearch,
4055                                         regex: columnSearch.bRegex
4056                                 }
4057                         } );
4058         
4059                         param( "mDataProp_"+i, dataProp );
4060         
4061                         if ( features.bFilter ) {
4062                                 param( 'sSearch_'+i,     columnSearch.sSearch );
4063                                 param( 'bRegex_'+i,      columnSearch.bRegex );
4064                                 param( 'bSearchable_'+i, column.bSearchable );
4065                         }
4066         
4067                         if ( features.bSort ) {
4068                                 param( 'bSortable_'+i, column.bSortable );
4069                         }
4070                 }
4071         
4072                 if ( features.bFilter ) {
4073                         param( 'sSearch', preSearch.sSearch );
4074                         param( 'bRegex', preSearch.bRegex );
4075                 }
4076         
4077                 if ( features.bSort ) {
4078                         $.each( sort, function ( i, val ) {
4079                                 d.order.push( { column: val.col, dir: val.dir } );
4080         
4081                                 param( 'iSortCol_'+i, val.col );
4082                                 param( 'sSortDir_'+i, val.dir );
4083                         } );
4084         
4085                         param( 'iSortingCols', sort.length );
4086                 }
4087         
4088                 // If the legacy.ajax parameter is null, then we automatically decide which
4089                 // form to use, based on sAjaxSource
4090                 var legacy = DataTable.ext.legacy.ajax;
4091                 if ( legacy === null ) {
4092                         return settings.sAjaxSource ? data : d;
4093                 }
4094         
4095                 // Otherwise, if legacy has been specified then we use that to decide on the
4096                 // form
4097                 return legacy ? data : d;
4098         }
4099         
4100         
4101         /**
4102          * Data the data from the server (nuking the old) and redraw the table
4103          *  @param {object} oSettings dataTables settings object
4104          *  @param {object} json json data return from the server.
4105          *  @param {string} json.sEcho Tracking flag for DataTables to match requests
4106          *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
4107          *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
4108          *  @param {array} json.aaData The data to display on this page
4109          *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
4110          *  @memberof DataTable#oApi
4111          */
4112         function _fnAjaxUpdateDraw ( settings, json )
4113         {
4114                 // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
4115                 // Support both
4116                 var compat = function ( old, modern ) {
4117                         return json[old] !== undefined ? json[old] : json[modern];
4118                 };
4119         
4120                 var data = _fnAjaxDataSrc( settings, json );
4121                 var draw            = compat( 'sEcho',                'draw' );
4122                 var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
4123                 var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
4124         
4125                 if ( draw ) {
4126                         // Protect against out of sequence returns
4127                         if ( draw*1 < settings.iDraw ) {
4128                                 return;
4129                         }
4130                         settings.iDraw = draw * 1;
4131                 }
4132         
4133                 _fnClearTable( settings );
4134                 settings._iRecordsTotal   = parseInt(recordsTotal, 10);
4135                 settings._iRecordsDisplay = parseInt(recordsFiltered, 10);
4136         
4137                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
4138                         _fnAddData( settings, data[i] );
4139                 }
4140                 settings.aiDisplay = settings.aiDisplayMaster.slice();
4141         
4142                 settings.bAjaxDataGet = false;
4143                 _fnDraw( settings );
4144         
4145                 if ( ! settings._bInitComplete ) {
4146                         _fnInitComplete( settings, json );
4147                 }
4148         
4149                 settings.bAjaxDataGet = true;
4150                 _fnProcessingDisplay( settings, false );
4151         }
4152         
4153         
4154         /**
4155          * Get the data from the JSON data source to use for drawing a table. Using
4156          * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
4157          * source object, or from a processing function.
4158          *  @param {object} oSettings dataTables settings object
4159          *  @param  {object} json Data source object / array from the server
4160          *  @return {array} Array of data to use
4161          */
4162         function _fnAjaxDataSrc ( oSettings, json )
4163         {
4164                 var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
4165                         oSettings.ajax.dataSrc :
4166                         oSettings.sAjaxDataProp; // Compatibility with 1.9-.
4167         
4168                 // Compatibility with 1.9-. In order to read from aaData, check if the
4169                 // default has been changed, if not, check for aaData
4170                 if ( dataSrc === 'data' ) {
4171                         return json.aaData || json[dataSrc];
4172                 }
4173         
4174                 return dataSrc !== "" ?
4175                         _fnGetObjectDataFn( dataSrc )( json ) :
4176                         json;
4177         }
4178         
4179         /**
4180          * Generate the node required for filtering text
4181          *  @returns {node} Filter control element
4182          *  @param {object} oSettings dataTables settings object
4183          *  @memberof DataTable#oApi
4184          */
4185         function _fnFeatureHtmlFilter ( settings )
4186         {
4187                 var classes = settings.oClasses;
4188                 var tableId = settings.sTableId;
4189                 var language = settings.oLanguage;
4190                 var previousSearch = settings.oPreviousSearch;
4191                 var features = settings.aanFeatures;
4192                 var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
4193         
4194                 var str = language.sSearch;
4195                 str = str.match(/_INPUT_/) ?
4196                         str.replace('_INPUT_', input) :
4197                         str+input;
4198         
4199                 var filter = $('<div/>', {
4200                                 'id': ! features.f ? tableId+'_filter' : null,
4201                                 'class': classes.sFilter
4202                         } )
4203                         .append( $('<label/>' ).append( str ) );
4204         
4205                 var searchFn = function() {
4206                         /* Update all other filter input elements for the new display */
4207                         var n = features.f;
4208                         var val = !this.value ? "" : this.value; // mental IE8 fix :-(
4209         
4210                         /* Now do the filter */
4211                         if ( val != previousSearch.sSearch ) {
4212                                 _fnFilterComplete( settings, {
4213                                         "sSearch": val,
4214                                         "bRegex": previousSearch.bRegex,
4215                                         "bSmart": previousSearch.bSmart ,
4216                                         "bCaseInsensitive": previousSearch.bCaseInsensitive
4217                                 } );
4218         
4219                                 // Need to redraw, without resorting
4220                                 settings._iDisplayStart = 0;
4221                                 _fnDraw( settings );
4222                         }
4223                 };
4224         
4225                 var searchDelay = settings.searchDelay !== null ?
4226                         settings.searchDelay :
4227                         _fnDataSource( settings ) === 'ssp' ?
4228                                 400 :
4229                                 0;
4230         
4231                 var jqFilter = $('input', filter)
4232                         .val( previousSearch.sSearch )
4233                         .attr( 'placeholder', language.sSearchPlaceholder )
4234                         .on(
4235                                 'keyup.DT search.DT input.DT paste.DT cut.DT',
4236                                 searchDelay ?
4237                                         _fnThrottle( searchFn, searchDelay ) :
4238                                         searchFn
4239                         )
4240                         .on( 'keypress.DT', function(e) {
4241                                 /* Prevent form submission */
4242                                 if ( e.keyCode == 13 ) {
4243                                         return false;
4244                                 }
4245                         } )
4246                         .attr('aria-controls', tableId);
4247         
4248                 // Update the input elements whenever the table is filtered
4249                 $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
4250                         if ( settings === s ) {
4251                                 // IE9 throws an 'unknown error' if document.activeElement is used
4252                                 // inside an iframe or frame...
4253                                 try {
4254                                         if ( jqFilter[0] !== document.activeElement ) {
4255                                                 jqFilter.val( previousSearch.sSearch );
4256                                         }
4257                                 }
4258                                 catch ( e ) {}
4259                         }
4260                 } );
4261         
4262                 return filter[0];
4263         }
4264         
4265         
4266         /**
4267          * Filter the table using both the global filter and column based filtering
4268          *  @param {object} oSettings dataTables settings object
4269          *  @param {object} oSearch search information
4270          *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
4271          *  @memberof DataTable#oApi
4272          */
4273         function _fnFilterComplete ( oSettings, oInput, iForce )
4274         {
4275                 var oPrevSearch = oSettings.oPreviousSearch;
4276                 var aoPrevSearch = oSettings.aoPreSearchCols;
4277                 var fnSaveFilter = function ( oFilter ) {
4278                         /* Save the filtering values */
4279                         oPrevSearch.sSearch = oFilter.sSearch;
4280                         oPrevSearch.bRegex = oFilter.bRegex;
4281                         oPrevSearch.bSmart = oFilter.bSmart;
4282                         oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
4283                 };
4284                 var fnRegex = function ( o ) {
4285                         // Backwards compatibility with the bEscapeRegex option
4286                         return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
4287                 };
4288         
4289                 // Resolve any column types that are unknown due to addition or invalidation
4290                 // @todo As per sort - can this be moved into an event handler?
4291                 _fnColumnTypes( oSettings );
4292         
4293                 /* In server-side processing all filtering is done by the server, so no point hanging around here */
4294                 if ( _fnDataSource( oSettings ) != 'ssp' )
4295                 {
4296                         /* Global filter */
4297                         _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
4298                         fnSaveFilter( oInput );
4299         
4300                         /* Now do the individual column filter */
4301                         for ( var i=0 ; i<aoPrevSearch.length ; i++ )
4302                         {
4303                                 _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
4304                                         aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
4305                         }
4306         
4307                         /* Custom filtering */
4308                         _fnFilterCustom( oSettings );
4309                 }
4310                 else
4311                 {
4312                         fnSaveFilter( oInput );
4313                 }
4314         
4315                 /* Tell the draw function we have been filtering */
4316                 oSettings.bFiltered = true;
4317                 _fnCallbackFire( oSettings, null, 'search', [oSettings] );
4318         }
4319         
4320         
4321         /**
4322          * Apply custom filtering functions
4323          *  @param {object} oSettings dataTables settings object
4324          *  @memberof DataTable#oApi
4325          */
4326         function _fnFilterCustom( settings )
4327         {
4328                 var filters = DataTable.ext.search;
4329                 var displayRows = settings.aiDisplay;
4330                 var row, rowIdx;
4331         
4332                 for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
4333                         var rows = [];
4334         
4335                         // Loop over each row and see if it should be included
4336                         for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
4337                                 rowIdx = displayRows[ j ];
4338                                 row = settings.aoData[ rowIdx ];
4339         
4340                                 if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
4341                                         rows.push( rowIdx );
4342                                 }
4343                         }
4344         
4345                         // So the array reference doesn't break set the results into the
4346                         // existing array
4347                         displayRows.length = 0;
4348                         $.merge( displayRows, rows );
4349                 }
4350         }
4351         
4352         
4353         /**
4354          * Filter the table on a per-column basis
4355          *  @param {object} oSettings dataTables settings object
4356          *  @param {string} sInput string to filter on
4357          *  @param {int} iColumn column to filter
4358          *  @param {bool} bRegex treat search string as a regular expression or not
4359          *  @param {bool} bSmart use smart filtering or not
4360          *  @param {bool} bCaseInsensitive Do case insenstive matching or not
4361          *  @memberof DataTable#oApi
4362          */
4363         function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
4364         {
4365                 if ( searchStr === '' ) {
4366                         return;
4367                 }
4368         
4369                 var data;
4370                 var out = [];
4371                 var display = settings.aiDisplay;
4372                 var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
4373         
4374                 for ( var i=0 ; i<display.length ; i++ ) {
4375                         data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
4376         
4377                         if ( rpSearch.test( data ) ) {
4378                                 out.push( display[i] );
4379                         }
4380                 }
4381         
4382                 settings.aiDisplay = out;
4383         }
4384         
4385         
4386         /**
4387          * Filter the data table based on user input and draw the table
4388          *  @param {object} settings dataTables settings object
4389          *  @param {string} input string to filter on
4390          *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
4391          *  @param {bool} regex treat as a regular expression or not
4392          *  @param {bool} smart perform smart filtering or not
4393          *  @param {bool} caseInsensitive Do case insenstive matching or not
4394          *  @memberof DataTable#oApi
4395          */
4396         function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
4397         {
4398                 var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
4399                 var prevSearch = settings.oPreviousSearch.sSearch;
4400                 var displayMaster = settings.aiDisplayMaster;
4401                 var display, invalidated, i;
4402                 var filtered = [];
4403         
4404                 // Need to take account of custom filtering functions - always filter
4405                 if ( DataTable.ext.search.length !== 0 ) {
4406                         force = true;
4407                 }
4408         
4409                 // Check if any of the rows were invalidated
4410                 invalidated = _fnFilterData( settings );
4411         
4412                 // If the input is blank - we just want the full data set
4413                 if ( input.length <= 0 ) {
4414                         settings.aiDisplay = displayMaster.slice();
4415                 }
4416                 else {
4417                         // New search - start from the master array
4418                         if ( invalidated ||
4419                                  force ||
4420                                  prevSearch.length > input.length ||
4421                                  input.indexOf(prevSearch) !== 0 ||
4422                                  settings.bSorted // On resort, the display master needs to be
4423                                                   // re-filtered since indexes will have changed
4424                         ) {
4425                                 settings.aiDisplay = displayMaster.slice();
4426                         }
4427         
4428                         // Search the display array
4429                         display = settings.aiDisplay;
4430         
4431                         for ( i=0 ; i<display.length ; i++ ) {
4432                                 if ( rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
4433                                         filtered.push( display[i] );
4434                                 }
4435                         }
4436         
4437                         settings.aiDisplay = filtered;
4438                 }
4439         }
4440         
4441         
4442         /**
4443          * Build a regular expression object suitable for searching a table
4444          *  @param {string} sSearch string to search for
4445          *  @param {bool} bRegex treat as a regular expression or not
4446          *  @param {bool} bSmart perform smart filtering or not
4447          *  @param {bool} bCaseInsensitive Do case insensitive matching or not
4448          *  @returns {RegExp} constructed object
4449          *  @memberof DataTable#oApi
4450          */
4451         function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
4452         {
4453                 search = regex ?
4454                         search :
4455                         _fnEscapeRegex( search );
4456                 
4457                 if ( smart ) {
4458                         /* For smart filtering we want to allow the search to work regardless of
4459                          * word order. We also want double quoted text to be preserved, so word
4460                          * order is important - a la google. So this is what we want to
4461                          * generate:
4462                          * 
4463                          * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
4464                          */
4465                         var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {
4466                                 if ( word.charAt(0) === '"' ) {
4467                                         var m = word.match( /^"(.*)"$/ );
4468                                         word = m ? m[1] : word;
4469                                 }
4470         
4471                                 return word.replace('"', '');
4472                         } );
4473         
4474                         search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
4475                 }
4476         
4477                 return new RegExp( search, caseInsensitive ? 'i' : '' );
4478         }
4479         
4480         
4481         /**
4482          * Escape a string such that it can be used in a regular expression
4483          *  @param {string} sVal string to escape
4484          *  @returns {string} escaped string
4485          *  @memberof DataTable#oApi
4486          */
4487         var _fnEscapeRegex = DataTable.util.escapeRegex;
4488         
4489         var __filter_div = $('<div>')[0];
4490         var __filter_div_textContent = __filter_div.textContent !== undefined;
4491         
4492         // Update the filtering data for each row if needed (by invalidation or first run)
4493         function _fnFilterData ( settings )
4494         {
4495                 var columns = settings.aoColumns;
4496                 var column;
4497                 var i, j, ien, jen, filterData, cellData, row;
4498                 var fomatters = DataTable.ext.type.search;
4499                 var wasInvalidated = false;
4500         
4501                 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4502                         row = settings.aoData[i];
4503         
4504                         if ( ! row._aFilterData ) {
4505                                 filterData = [];
4506         
4507                                 for ( j=0, jen=columns.length ; j<jen ; j++ ) {
4508                                         column = columns[j];
4509         
4510                                         if ( column.bSearchable ) {
4511                                                 cellData = _fnGetCellData( settings, i, j, 'filter' );
4512         
4513                                                 if ( fomatters[ column.sType ] ) {
4514                                                         cellData = fomatters[ column.sType ]( cellData );
4515                                                 }
4516         
4517                                                 // Search in DataTables 1.10 is string based. In 1.11 this
4518                                                 // should be altered to also allow strict type checking.
4519                                                 if ( cellData === null ) {
4520                                                         cellData = '';
4521                                                 }
4522         
4523                                                 if ( typeof cellData !== 'string' && cellData.toString ) {
4524                                                         cellData = cellData.toString();
4525                                                 }
4526                                         }
4527                                         else {
4528                                                 cellData = '';
4529                                         }
4530         
4531                                         // If it looks like there is an HTML entity in the string,
4532                                         // attempt to decode it so sorting works as expected. Note that
4533                                         // we could use a single line of jQuery to do this, but the DOM
4534                                         // method used here is much faster http://jsperf.com/html-decode
4535                                         if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
4536                                                 __filter_div.innerHTML = cellData;
4537                                                 cellData = __filter_div_textContent ?
4538                                                         __filter_div.textContent :
4539                                                         __filter_div.innerText;
4540                                         }
4541         
4542                                         if ( cellData.replace ) {
4543                                                 cellData = cellData.replace(/[\r\n]/g, '');
4544                                         }
4545         
4546                                         filterData.push( cellData );
4547                                 }
4548         
4549                                 row._aFilterData = filterData;
4550                                 row._sFilterRow = filterData.join('  ');
4551                                 wasInvalidated = true;
4552                         }
4553                 }
4554         
4555                 return wasInvalidated;
4556         }
4557         
4558         
4559         /**
4560          * Convert from the internal Hungarian notation to camelCase for external
4561          * interaction
4562          *  @param {object} obj Object to convert
4563          *  @returns {object} Inverted object
4564          *  @memberof DataTable#oApi
4565          */
4566         function _fnSearchToCamel ( obj )
4567         {
4568                 return {
4569                         search:          obj.sSearch,
4570                         smart:           obj.bSmart,
4571                         regex:           obj.bRegex,
4572                         caseInsensitive: obj.bCaseInsensitive
4573                 };
4574         }
4575         
4576         
4577         
4578         /**
4579          * Convert from camelCase notation to the internal Hungarian. We could use the
4580          * Hungarian convert function here, but this is cleaner
4581          *  @param {object} obj Object to convert
4582          *  @returns {object} Inverted object
4583          *  @memberof DataTable#oApi
4584          */
4585         function _fnSearchToHung ( obj )
4586         {
4587                 return {
4588                         sSearch:          obj.search,
4589                         bSmart:           obj.smart,
4590                         bRegex:           obj.regex,
4591                         bCaseInsensitive: obj.caseInsensitive
4592                 };
4593         }
4594         
4595         /**
4596          * Generate the node required for the info display
4597          *  @param {object} oSettings dataTables settings object
4598          *  @returns {node} Information element
4599          *  @memberof DataTable#oApi
4600          */
4601         function _fnFeatureHtmlInfo ( settings )
4602         {
4603                 var
4604                         tid = settings.sTableId,
4605                         nodes = settings.aanFeatures.i,
4606                         n = $('<div/>', {
4607                                 'class': settings.oClasses.sInfo,
4608                                 'id': ! nodes ? tid+'_info' : null
4609                         } );
4610         
4611                 if ( ! nodes ) {
4612                         // Update display on each draw
4613                         settings.aoDrawCallback.push( {
4614                                 "fn": _fnUpdateInfo,
4615                                 "sName": "information"
4616                         } );
4617         
4618                         n
4619                                 .attr( 'role', 'status' )
4620                                 .attr( 'aria-live', 'polite' );
4621         
4622                         // Table is described by our info div
4623                         $(settings.nTable).attr( 'aria-describedby', tid+'_info' );
4624                 }
4625         
4626                 return n[0];
4627         }
4628         
4629         
4630         /**
4631          * Update the information elements in the display
4632          *  @param {object} settings dataTables settings object
4633          *  @memberof DataTable#oApi
4634          */
4635         function _fnUpdateInfo ( settings )
4636         {
4637                 /* Show information about the table */
4638                 var nodes = settings.aanFeatures.i;
4639                 if ( nodes.length === 0 ) {
4640                         return;
4641                 }
4642         
4643                 var
4644                         lang  = settings.oLanguage,
4645                         start = settings._iDisplayStart+1,
4646                         end   = settings.fnDisplayEnd(),
4647                         max   = settings.fnRecordsTotal(),
4648                         total = settings.fnRecordsDisplay(),
4649                         out   = total ?
4650                                 lang.sInfo :
4651                                 lang.sInfoEmpty;
4652         
4653                 if ( total !== max ) {
4654                         /* Record set after filtering */
4655                         out += ' ' + lang.sInfoFiltered;
4656                 }
4657         
4658                 // Convert the macros
4659                 out += lang.sInfoPostFix;
4660                 out = _fnInfoMacros( settings, out );
4661         
4662                 var callback = lang.fnInfoCallback;
4663                 if ( callback !== null ) {
4664                         out = callback.call( settings.oInstance,
4665                                 settings, start, end, max, total, out
4666                         );
4667                 }
4668         
4669                 $(nodes).html( out );
4670         }
4671         
4672         
4673         function _fnInfoMacros ( settings, str )
4674         {
4675                 // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
4676                 // internally
4677                 var
4678                         formatter  = settings.fnFormatNumber,
4679                         start      = settings._iDisplayStart+1,
4680                         len        = settings._iDisplayLength,
4681                         vis        = settings.fnRecordsDisplay(),
4682                         all        = len === -1;
4683         
4684                 return str.
4685                         replace(/_START_/g, formatter.call( settings, start ) ).
4686                         replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
4687                         replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
4688                         replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
4689                         replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
4690                         replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
4691         }
4692         
4693         
4694         
4695         /**
4696          * Draw the table for the first time, adding all required features
4697          *  @param {object} settings dataTables settings object
4698          *  @memberof DataTable#oApi
4699          */
4700         function _fnInitialise ( settings )
4701         {
4702                 var i, iLen, iAjaxStart=settings.iInitDisplayStart;
4703                 var columns = settings.aoColumns, column;
4704                 var features = settings.oFeatures;
4705                 var deferLoading = settings.bDeferLoading; // value modified by the draw
4706         
4707                 /* Ensure that the table data is fully initialised */
4708                 if ( ! settings.bInitialised ) {
4709                         setTimeout( function(){ _fnInitialise( settings ); }, 200 );
4710                         return;
4711                 }
4712         
4713                 /* Show the display HTML options */
4714                 _fnAddOptionsHtml( settings );
4715         
4716                 /* Build and draw the header / footer for the table */
4717                 _fnBuildHead( settings );
4718                 _fnDrawHead( settings, settings.aoHeader );
4719                 _fnDrawHead( settings, settings.aoFooter );
4720         
4721                 /* Okay to show that something is going on now */
4722                 _fnProcessingDisplay( settings, true );
4723         
4724                 /* Calculate sizes for columns */
4725                 if ( features.bAutoWidth ) {
4726                         _fnCalculateColumnWidths( settings );
4727                 }
4728         
4729                 for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
4730                         column = columns[i];
4731         
4732                         if ( column.sWidth ) {
4733                                 column.nTh.style.width = _fnStringToCss( column.sWidth );
4734                         }
4735                 }
4736         
4737                 _fnCallbackFire( settings, null, 'preInit', [settings] );
4738         
4739                 // If there is default sorting required - let's do it. The sort function
4740                 // will do the drawing for us. Otherwise we draw the table regardless of the
4741                 // Ajax source - this allows the table to look initialised for Ajax sourcing
4742                 // data (show 'loading' message possibly)
4743                 _fnReDraw( settings );
4744         
4745                 // Server-side processing init complete is done by _fnAjaxUpdateDraw
4746                 var dataSrc = _fnDataSource( settings );
4747                 if ( dataSrc != 'ssp' || deferLoading ) {
4748                         // if there is an ajax source load the data
4749                         if ( dataSrc == 'ajax' ) {
4750                                 _fnBuildAjax( settings, [], function(json) {
4751                                         var aData = _fnAjaxDataSrc( settings, json );
4752         
4753                                         // Got the data - add it to the table
4754                                         for ( i=0 ; i<aData.length ; i++ ) {
4755                                                 _fnAddData( settings, aData[i] );
4756                                         }
4757         
4758                                         // Reset the init display for cookie saving. We've already done
4759                                         // a filter, and therefore cleared it before. So we need to make
4760                                         // it appear 'fresh'
4761                                         settings.iInitDisplayStart = iAjaxStart;
4762         
4763                                         _fnReDraw( settings );
4764         
4765                                         _fnProcessingDisplay( settings, false );
4766                                         _fnInitComplete( settings, json );
4767                                 }, settings );
4768                         }
4769                         else {
4770                                 _fnProcessingDisplay( settings, false );
4771                                 _fnInitComplete( settings );
4772                         }
4773                 }
4774         }
4775         
4776         
4777         /**
4778          * Draw the table for the first time, adding all required features
4779          *  @param {object} oSettings dataTables settings object
4780          *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
4781          *    with client-side processing (optional)
4782          *  @memberof DataTable#oApi
4783          */
4784         function _fnInitComplete ( settings, json )
4785         {
4786                 settings._bInitComplete = true;
4787         
4788                 // When data was added after the initialisation (data or Ajax) we need to
4789                 // calculate the column sizing
4790                 if ( json || settings.oInit.aaData ) {
4791                         _fnAdjustColumnSizing( settings );
4792                 }
4793         
4794                 _fnCallbackFire( settings, null, 'plugin-init', [settings, json] );
4795                 _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
4796         }
4797         
4798         
4799         function _fnLengthChange ( settings, val )
4800         {
4801                 var len = parseInt( val, 10 );
4802                 settings._iDisplayLength = len;
4803         
4804                 _fnLengthOverflow( settings );
4805         
4806                 // Fire length change event
4807                 _fnCallbackFire( settings, null, 'length', [settings, len] );
4808         }
4809         
4810         
4811         /**
4812          * Generate the node required for user display length changing
4813          *  @param {object} settings dataTables settings object
4814          *  @returns {node} Display length feature node
4815          *  @memberof DataTable#oApi
4816          */
4817         function _fnFeatureHtmlLength ( settings )
4818         {
4819                 var
4820                         classes  = settings.oClasses,
4821                         tableId  = settings.sTableId,
4822                         menu     = settings.aLengthMenu,
4823                         d2       = $.isArray( menu[0] ),
4824                         lengths  = d2 ? menu[0] : menu,
4825                         language = d2 ? menu[1] : menu;
4826         
4827                 var select = $('<select/>', {
4828                         'name':          tableId+'_length',
4829                         'aria-controls': tableId,
4830                         'class':         classes.sLengthSelect
4831                 } );
4832         
4833                 for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
4834                         select[0][ i ] = new Option( language[i], lengths[i] );
4835                 }
4836         
4837                 var div = $('<div><label/></div>').addClass( classes.sLength );
4838                 if ( ! settings.aanFeatures.l ) {
4839                         div[0].id = tableId+'_length';
4840                 }
4841         
4842                 div.children().append(
4843                         settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
4844                 );
4845         
4846                 // Can't use `select` variable as user might provide their own and the
4847                 // reference is broken by the use of outerHTML
4848                 $('select', div)
4849                         .val( settings._iDisplayLength )
4850                         .on( 'change.DT', function(e) {
4851                                 _fnLengthChange( settings, $(this).val() );
4852                                 _fnDraw( settings );
4853                         } );
4854         
4855                 // Update node value whenever anything changes the table's length
4856                 $(settings.nTable).on( 'length.dt.DT', function (e, s, len) {
4857                         if ( settings === s ) {
4858                                 $('select', div).val( len );
4859                         }
4860                 } );
4861         
4862                 return div[0];
4863         }
4864         
4865         
4866         
4867         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
4868          * Note that most of the paging logic is done in
4869          * DataTable.ext.pager
4870          */
4871         
4872         /**
4873          * Generate the node required for default pagination
4874          *  @param {object} oSettings dataTables settings object
4875          *  @returns {node} Pagination feature node
4876          *  @memberof DataTable#oApi
4877          */
4878         function _fnFeatureHtmlPaginate ( settings )
4879         {
4880                 var
4881                         type   = settings.sPaginationType,
4882                         plugin = DataTable.ext.pager[ type ],
4883                         modern = typeof plugin === 'function',
4884                         redraw = function( settings ) {
4885                                 _fnDraw( settings );
4886                         },
4887                         node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
4888                         features = settings.aanFeatures;
4889         
4890                 if ( ! modern ) {
4891                         plugin.fnInit( settings, node, redraw );
4892                 }
4893         
4894                 /* Add a draw callback for the pagination on first instance, to update the paging display */
4895                 if ( ! features.p )
4896                 {
4897                         node.id = settings.sTableId+'_paginate';
4898         
4899                         settings.aoDrawCallback.push( {
4900                                 "fn": function( settings ) {
4901                                         if ( modern ) {
4902                                                 var
4903                                                         start      = settings._iDisplayStart,
4904                                                         len        = settings._iDisplayLength,
4905                                                         visRecords = settings.fnRecordsDisplay(),
4906                                                         all        = len === -1,
4907                                                         page = all ? 0 : Math.ceil( start / len ),
4908                                                         pages = all ? 1 : Math.ceil( visRecords / len ),
4909                                                         buttons = plugin(page, pages),
4910                                                         i, ien;
4911         
4912                                                 for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
4913                                                         _fnRenderer( settings, 'pageButton' )(
4914                                                                 settings, features.p[i], i, buttons, page, pages
4915                                                         );
4916                                                 }
4917                                         }
4918                                         else {
4919                                                 plugin.fnUpdate( settings, redraw );
4920                                         }
4921                                 },
4922                                 "sName": "pagination"
4923                         } );
4924                 }
4925         
4926                 return node;
4927         }
4928         
4929         
4930         /**
4931          * Alter the display settings to change the page
4932          *  @param {object} settings DataTables settings object
4933          *  @param {string|int} action Paging action to take: "first", "previous",
4934          *    "next" or "last" or page number to jump to (integer)
4935          *  @param [bool] redraw Automatically draw the update or not
4936          *  @returns {bool} true page has changed, false - no change
4937          *  @memberof DataTable#oApi
4938          */
4939         function _fnPageChange ( settings, action, redraw )
4940         {
4941                 var
4942                         start     = settings._iDisplayStart,
4943                         len       = settings._iDisplayLength,
4944                         records   = settings.fnRecordsDisplay();
4945         
4946                 if ( records === 0 || len === -1 )
4947                 {
4948                         start = 0;
4949                 }
4950                 else if ( typeof action === "number" )
4951                 {
4952                         start = action * len;
4953         
4954                         if ( start > records )
4955                         {
4956                                 start = 0;
4957                         }
4958                 }
4959                 else if ( action == "first" )
4960                 {
4961                         start = 0;
4962                 }
4963                 else if ( action == "previous" )
4964                 {
4965                         start = len >= 0 ?
4966                                 start - len :
4967                                 0;
4968         
4969                         if ( start < 0 )
4970                         {
4971                           start = 0;
4972                         }
4973                 }
4974                 else if ( action == "next" )
4975                 {
4976                         if ( start + len < records )
4977                         {
4978                                 start += len;
4979                         }
4980                 }
4981                 else if ( action == "last" )
4982                 {
4983                         start = Math.floor( (records-1) / len) * len;
4984                 }
4985                 else
4986                 {
4987                         _fnLog( settings, 0, "Unknown paging action: "+action, 5 );
4988                 }
4989         
4990                 var changed = settings._iDisplayStart !== start;
4991                 settings._iDisplayStart = start;
4992         
4993                 if ( changed ) {
4994                         _fnCallbackFire( settings, null, 'page', [settings] );
4995         
4996                         if ( redraw ) {
4997                                 _fnDraw( settings );
4998                         }
4999                 }
5000         
5001                 return changed;
5002         }
5003         
5004         
5005         
5006         /**
5007          * Generate the node required for the processing node
5008          *  @param {object} settings dataTables settings object
5009          *  @returns {node} Processing element
5010          *  @memberof DataTable#oApi
5011          */
5012         function _fnFeatureHtmlProcessing ( settings )
5013         {
5014                 return $('<div/>', {
5015                                 'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
5016                                 'class': settings.oClasses.sProcessing
5017                         } )
5018                         .html( settings.oLanguage.sProcessing )
5019                         .insertBefore( settings.nTable )[0];
5020         }
5021         
5022         
5023         /**
5024          * Display or hide the processing indicator
5025          *  @param {object} settings dataTables settings object
5026          *  @param {bool} show Show the processing indicator (true) or not (false)
5027          *  @memberof DataTable#oApi
5028          */
5029         function _fnProcessingDisplay ( settings, show )
5030         {
5031                 if ( settings.oFeatures.bProcessing ) {
5032                         $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
5033                 }
5034         
5035                 _fnCallbackFire( settings, null, 'processing', [settings, show] );
5036         }
5037         
5038         /**
5039          * Add any control elements for the table - specifically scrolling
5040          *  @param {object} settings dataTables settings object
5041          *  @returns {node} Node to add to the DOM
5042          *  @memberof DataTable#oApi
5043          */
5044         function _fnFeatureHtmlTable ( settings )
5045         {
5046                 var table = $(settings.nTable);
5047         
5048                 // Add the ARIA grid role to the table
5049                 table.attr( 'role', 'grid' );
5050         
5051                 // Scrolling from here on in
5052                 var scroll = settings.oScroll;
5053         
5054                 if ( scroll.sX === '' && scroll.sY === '' ) {
5055                         return settings.nTable;
5056                 }
5057         
5058                 var scrollX = scroll.sX;
5059                 var scrollY = scroll.sY;
5060                 var classes = settings.oClasses;
5061                 var caption = table.children('caption');
5062                 var captionSide = caption.length ? caption[0]._captionSide : null;
5063                 var headerClone = $( table[0].cloneNode(false) );
5064                 var footerClone = $( table[0].cloneNode(false) );
5065                 var footer = table.children('tfoot');
5066                 var _div = '<div/>';
5067                 var size = function ( s ) {
5068                         return !s ? null : _fnStringToCss( s );
5069                 };
5070         
5071                 if ( ! footer.length ) {
5072                         footer = null;
5073                 }
5074         
5075                 /*
5076                  * The HTML structure that we want to generate in this function is:
5077                  *  div - scroller
5078                  *    div - scroll head
5079                  *      div - scroll head inner
5080                  *        table - scroll head table
5081                  *          thead - thead
5082                  *    div - scroll body
5083                  *      table - table (master table)
5084                  *        thead - thead clone for sizing
5085                  *        tbody - tbody
5086                  *    div - scroll foot
5087                  *      div - scroll foot inner
5088                  *        table - scroll foot table
5089                  *          tfoot - tfoot
5090                  */
5091                 var scroller = $( _div, { 'class': classes.sScrollWrapper } )
5092                         .append(
5093                                 $(_div, { 'class': classes.sScrollHead } )
5094                                         .css( {
5095                                                 overflow: 'hidden',
5096                                                 position: 'relative',
5097                                                 border: 0,
5098                                                 width: scrollX ? size(scrollX) : '100%'
5099                                         } )
5100                                         .append(
5101                                                 $(_div, { 'class': classes.sScrollHeadInner } )
5102                                                         .css( {
5103                                                                 'box-sizing': 'content-box',
5104                                                                 width: scroll.sXInner || '100%'
5105                                                         } )
5106                                                         .append(
5107                                                                 headerClone
5108                                                                         .removeAttr('id')
5109                                                                         .css( 'margin-left', 0 )
5110                                                                         .append( captionSide === 'top' ? caption : null )
5111                                                                         .append(
5112                                                                                 table.children('thead')
5113                                                                         )
5114                                                         )
5115                                         )
5116                         )
5117                         .append(
5118                                 $(_div, { 'class': classes.sScrollBody } )
5119                                         .css( {
5120                                                 position: 'relative',
5121                                                 overflow: 'auto',
5122                                                 width: size( scrollX )
5123                                         } )
5124                                         .append( table )
5125                         );
5126         
5127                 if ( footer ) {
5128                         scroller.append(
5129                                 $(_div, { 'class': classes.sScrollFoot } )
5130                                         .css( {
5131                                                 overflow: 'hidden',
5132                                                 border: 0,
5133                                                 width: scrollX ? size(scrollX) : '100%'
5134                                         } )
5135                                         .append(
5136                                                 $(_div, { 'class': classes.sScrollFootInner } )
5137                                                         .append(
5138                                                                 footerClone
5139                                                                         .removeAttr('id')
5140                                                                         .css( 'margin-left', 0 )
5141                                                                         .append( captionSide === 'bottom' ? caption : null )
5142                                                                         .append(
5143                                                                                 table.children('tfoot')
5144                                                                         )
5145                                                         )
5146                                         )
5147                         );
5148                 }
5149         
5150                 var children = scroller.children();
5151                 var scrollHead = children[0];
5152                 var scrollBody = children[1];
5153                 var scrollFoot = footer ? children[2] : null;
5154         
5155                 // When the body is scrolled, then we also want to scroll the headers
5156                 if ( scrollX ) {
5157                         $(scrollBody).on( 'scroll.DT', function (e) {
5158                                 var scrollLeft = this.scrollLeft;
5159         
5160                                 scrollHead.scrollLeft = scrollLeft;
5161         
5162                                 if ( footer ) {
5163                                         scrollFoot.scrollLeft = scrollLeft;
5164                                 }
5165                         } );
5166                 }
5167         
5168                 $(scrollBody).css(
5169                         scrollY && scroll.bCollapse ? 'max-height' : 'height', 
5170                         scrollY
5171                 );
5172         
5173                 settings.nScrollHead = scrollHead;
5174                 settings.nScrollBody = scrollBody;
5175                 settings.nScrollFoot = scrollFoot;
5176         
5177                 // On redraw - align columns
5178                 settings.aoDrawCallback.push( {
5179                         "fn": _fnScrollDraw,
5180                         "sName": "scrolling"
5181                 } );
5182         
5183                 return scroller[0];
5184         }
5185         
5186         
5187         
5188         /**
5189          * Update the header, footer and body tables for resizing - i.e. column
5190          * alignment.
5191          *
5192          * Welcome to the most horrible function DataTables. The process that this
5193          * function follows is basically:
5194          *   1. Re-create the table inside the scrolling div
5195          *   2. Take live measurements from the DOM
5196          *   3. Apply the measurements to align the columns
5197          *   4. Clean up
5198          *
5199          *  @param {object} settings dataTables settings object
5200          *  @memberof DataTable#oApi
5201          */
5202         function _fnScrollDraw ( settings )
5203         {
5204                 // Given that this is such a monster function, a lot of variables are use
5205                 // to try and keep the minimised size as small as possible
5206                 var
5207                         scroll         = settings.oScroll,
5208                         scrollX        = scroll.sX,
5209                         scrollXInner   = scroll.sXInner,
5210                         scrollY        = scroll.sY,
5211                         barWidth       = scroll.iBarWidth,
5212                         divHeader      = $(settings.nScrollHead),
5213                         divHeaderStyle = divHeader[0].style,
5214                         divHeaderInner = divHeader.children('div'),
5215                         divHeaderInnerStyle = divHeaderInner[0].style,
5216                         divHeaderTable = divHeaderInner.children('table'),
5217                         divBodyEl      = settings.nScrollBody,
5218                         divBody        = $(divBodyEl),
5219                         divBodyStyle   = divBodyEl.style,
5220                         divFooter      = $(settings.nScrollFoot),
5221                         divFooterInner = divFooter.children('div'),
5222                         divFooterTable = divFooterInner.children('table'),
5223                         header         = $(settings.nTHead),
5224                         table          = $(settings.nTable),
5225                         tableEl        = table[0],
5226                         tableStyle     = tableEl.style,
5227                         footer         = settings.nTFoot ? $(settings.nTFoot) : null,
5228                         browser        = settings.oBrowser,
5229                         ie67           = browser.bScrollOversize,
5230                         dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),
5231                         headerTrgEls, footerTrgEls,
5232                         headerSrcEls, footerSrcEls,
5233                         headerCopy, footerCopy,
5234                         headerWidths=[], footerWidths=[],
5235                         headerContent=[], footerContent=[],
5236                         idx, correction, sanityWidth,
5237                         zeroOut = function(nSizer) {
5238                                 var style = nSizer.style;
5239                                 style.paddingTop = "0";
5240                                 style.paddingBottom = "0";
5241                                 style.borderTopWidth = "0";
5242                                 style.borderBottomWidth = "0";
5243                                 style.height = 0;
5244                         };
5245         
5246                 // If the scrollbar visibility has changed from the last draw, we need to
5247                 // adjust the column sizes as the table width will have changed to account
5248                 // for the scrollbar
5249                 var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;
5250                 
5251                 if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {
5252                         settings.scrollBarVis = scrollBarVis;
5253                         _fnAdjustColumnSizing( settings );
5254                         return; // adjust column sizing will call this function again
5255                 }
5256                 else {
5257                         settings.scrollBarVis = scrollBarVis;
5258                 }
5259         
5260                 /*
5261                  * 1. Re-create the table inside the scrolling div
5262                  */
5263         
5264                 // Remove the old minimised thead and tfoot elements in the inner table
5265                 table.children('thead, tfoot').remove();
5266         
5267                 if ( footer ) {
5268                         footerCopy = footer.clone().prependTo( table );
5269                         footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
5270                         footerSrcEls = footerCopy.find('tr');
5271                 }
5272         
5273                 // Clone the current header and footer elements and then place it into the inner table
5274                 headerCopy = header.clone().prependTo( table );
5275                 headerTrgEls = header.find('tr'); // original header is in its own table
5276                 headerSrcEls = headerCopy.find('tr');
5277                 headerCopy.find('th, td').removeAttr('tabindex');
5278         
5279         
5280                 /*
5281                  * 2. Take live measurements from the DOM - do not alter the DOM itself!
5282                  */
5283         
5284                 // Remove old sizing and apply the calculated column widths
5285                 // Get the unique column headers in the newly created (cloned) header. We want to apply the
5286                 // calculated sizes to this header
5287                 if ( ! scrollX )
5288                 {
5289                         divBodyStyle.width = '100%';
5290                         divHeader[0].style.width = '100%';
5291                 }
5292         
5293                 $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
5294                         idx = _fnVisibleToColumnIndex( settings, i );
5295                         el.style.width = settings.aoColumns[idx].sWidth;
5296                 } );
5297         
5298                 if ( footer ) {
5299                         _fnApplyToChildren( function(n) {
5300                                 n.style.width = "";
5301                         }, footerSrcEls );
5302                 }
5303         
5304                 // Size the table as a whole
5305                 sanityWidth = table.outerWidth();
5306                 if ( scrollX === "" ) {
5307                         // No x scrolling
5308                         tableStyle.width = "100%";
5309         
5310                         // IE7 will make the width of the table when 100% include the scrollbar
5311                         // - which is shouldn't. When there is a scrollbar we need to take this
5312                         // into account.
5313                         if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
5314                                 divBody.css('overflow-y') == "scroll")
5315                         ) {
5316                                 tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
5317                         }
5318         
5319                         // Recalculate the sanity width
5320                         sanityWidth = table.outerWidth();
5321                 }
5322                 else if ( scrollXInner !== "" ) {
5323                         // legacy x scroll inner has been given - use it
5324                         tableStyle.width = _fnStringToCss(scrollXInner);
5325         
5326                         // Recalculate the sanity width
5327                         sanityWidth = table.outerWidth();
5328                 }
5329         
5330                 // Hidden header should have zero height, so remove padding and borders. Then
5331                 // set the width based on the real headers
5332         
5333                 // Apply all styles in one pass
5334                 _fnApplyToChildren( zeroOut, headerSrcEls );
5335         
5336                 // Read all widths in next pass
5337                 _fnApplyToChildren( function(nSizer) {
5338                         headerContent.push( nSizer.innerHTML );
5339                         headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5340                 }, headerSrcEls );
5341         
5342                 // Apply all widths in final pass
5343                 _fnApplyToChildren( function(nToSize, i) {
5344                         // Only apply widths to the DataTables detected header cells - this
5345                         // prevents complex headers from having contradictory sizes applied
5346                         if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) {
5347                                 nToSize.style.width = headerWidths[i];
5348                         }
5349                 }, headerTrgEls );
5350         
5351                 $(headerSrcEls).height(0);
5352         
5353                 /* Same again with the footer if we have one */
5354                 if ( footer )
5355                 {
5356                         _fnApplyToChildren( zeroOut, footerSrcEls );
5357         
5358                         _fnApplyToChildren( function(nSizer) {
5359                                 footerContent.push( nSizer.innerHTML );
5360                                 footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
5361                         }, footerSrcEls );
5362         
5363                         _fnApplyToChildren( function(nToSize, i) {
5364                                 nToSize.style.width = footerWidths[i];
5365                         }, footerTrgEls );
5366         
5367                         $(footerSrcEls).height(0);
5368                 }
5369         
5370         
5371                 /*
5372                  * 3. Apply the measurements
5373                  */
5374         
5375                 // "Hide" the header and footer that we used for the sizing. We need to keep
5376                 // the content of the cell so that the width applied to the header and body
5377                 // both match, but we want to hide it completely. We want to also fix their
5378                 // width to what they currently are
5379                 _fnApplyToChildren( function(nSizer, i) {
5380                         nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
5381                         nSizer.style.width = headerWidths[i];
5382                 }, headerSrcEls );
5383         
5384                 if ( footer )
5385                 {
5386                         _fnApplyToChildren( function(nSizer, i) {
5387                                 nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+footerContent[i]+'</div>';
5388                                 nSizer.style.width = footerWidths[i];
5389                         }, footerSrcEls );
5390                 }
5391         
5392                 // Sanity check that the table is of a sensible width. If not then we are going to get
5393                 // misalignment - try to prevent this by not allowing the table to shrink below its min width
5394                 if ( table.outerWidth() < sanityWidth )
5395                 {
5396                         // The min width depends upon if we have a vertical scrollbar visible or not */
5397                         correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
5398                                 divBody.css('overflow-y') == "scroll")) ?
5399                                         sanityWidth+barWidth :
5400                                         sanityWidth;
5401         
5402                         // IE6/7 are a law unto themselves...
5403                         if ( ie67 && (divBodyEl.scrollHeight >
5404                                 divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
5405                         ) {
5406                                 tableStyle.width = _fnStringToCss( correction-barWidth );
5407                         }
5408         
5409                         // And give the user a warning that we've stopped the table getting too small
5410                         if ( scrollX === "" || scrollXInner !== "" ) {
5411                                 _fnLog( settings, 1, 'Possible column misalignment', 6 );
5412                         }
5413                 }
5414                 else
5415                 {
5416                         correction = '100%';
5417                 }
5418         
5419                 // Apply to the container elements
5420                 divBodyStyle.width = _fnStringToCss( correction );
5421                 divHeaderStyle.width = _fnStringToCss( correction );
5422         
5423                 if ( footer ) {
5424                         settings.nScrollFoot.style.width = _fnStringToCss( correction );
5425                 }
5426         
5427         
5428                 /*
5429                  * 4. Clean up
5430                  */
5431                 if ( ! scrollY ) {
5432                         /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
5433                          * the scrollbar height from the visible display, rather than adding it on. We need to
5434                          * set the height in order to sort this. Don't want to do it in any other browsers.
5435                          */
5436                         if ( ie67 ) {
5437                                 divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
5438                         }
5439                 }
5440         
5441                 /* Finally set the width's of the header and footer tables */
5442                 var iOuterWidth = table.outerWidth();
5443                 divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
5444                 divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
5445         
5446                 // Figure out if there are scrollbar present - if so then we need a the header and footer to
5447                 // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
5448                 var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
5449                 var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
5450                 divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
5451         
5452                 if ( footer ) {
5453                         divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
5454                         divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
5455                         divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
5456                 }
5457         
5458                 // Correct DOM ordering for colgroup - comes before the thead
5459                 table.children('colgroup').insertBefore( table.children('thead') );
5460         
5461                 /* Adjust the position of the header in case we loose the y-scrollbar */
5462                 divBody.scroll();
5463         
5464                 // If sorting or filtering has occurred, jump the scrolling back to the top
5465                 // only if we aren't holding the position
5466                 if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
5467                         divBodyEl.scrollTop = 0;
5468                 }
5469         }
5470         
5471         
5472         
5473         /**
5474          * Apply a given function to the display child nodes of an element array (typically
5475          * TD children of TR rows
5476          *  @param {function} fn Method to apply to the objects
5477          *  @param array {nodes} an1 List of elements to look through for display children
5478          *  @param array {nodes} an2 Another list (identical structure to the first) - optional
5479          *  @memberof DataTable#oApi
5480          */
5481         function _fnApplyToChildren( fn, an1, an2 )
5482         {
5483                 var index=0, i=0, iLen=an1.length;
5484                 var nNode1, nNode2;
5485         
5486                 while ( i < iLen ) {
5487                         nNode1 = an1[i].firstChild;
5488                         nNode2 = an2 ? an2[i].firstChild : null;
5489         
5490                         while ( nNode1 ) {
5491                                 if ( nNode1.nodeType === 1 ) {
5492                                         if ( an2 ) {
5493                                                 fn( nNode1, nNode2, index );
5494                                         }
5495                                         else {
5496                                                 fn( nNode1, index );
5497                                         }
5498         
5499                                         index++;
5500                                 }
5501         
5502                                 nNode1 = nNode1.nextSibling;
5503                                 nNode2 = an2 ? nNode2.nextSibling : null;
5504                         }
5505         
5506                         i++;
5507                 }
5508         }
5509         
5510         
5511         
5512         var __re_html_remove = /<.*?>/g;
5513         
5514         
5515         /**
5516          * Calculate the width of columns for the table
5517          *  @param {object} oSettings dataTables settings object
5518          *  @memberof DataTable#oApi
5519          */
5520         function _fnCalculateColumnWidths ( oSettings )
5521         {
5522                 var
5523                         table = oSettings.nTable,
5524                         columns = oSettings.aoColumns,
5525                         scroll = oSettings.oScroll,
5526                         scrollY = scroll.sY,
5527                         scrollX = scroll.sX,
5528                         scrollXInner = scroll.sXInner,
5529                         columnCount = columns.length,
5530                         visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
5531                         headerCells = $('th', oSettings.nTHead),
5532                         tableWidthAttr = table.getAttribute('width'), // from DOM element
5533                         tableContainer = table.parentNode,
5534                         userInputs = false,
5535                         i, column, columnIdx, width, outerWidth,
5536                         browser = oSettings.oBrowser,
5537                         ie67 = browser.bScrollOversize;
5538         
5539                 var styleWidth = table.style.width;
5540                 if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {
5541                         tableWidthAttr = styleWidth;
5542                 }
5543         
5544                 /* Convert any user input sizes into pixel sizes */
5545                 for ( i=0 ; i<visibleColumns.length ; i++ ) {
5546                         column = columns[ visibleColumns[i] ];
5547         
5548                         if ( column.sWidth !== null ) {
5549                                 column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
5550         
5551                                 userInputs = true;
5552                         }
5553                 }
5554         
5555                 /* If the number of columns in the DOM equals the number that we have to
5556                  * process in DataTables, then we can use the offsets that are created by
5557                  * the web- browser. No custom sizes can be set in order for this to happen,
5558                  * nor scrolling used
5559                  */
5560                 if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&
5561                      columnCount == _fnVisbleColumns( oSettings ) &&
5562                      columnCount == headerCells.length
5563                 ) {
5564                         for ( i=0 ; i<columnCount ; i++ ) {
5565                                 var colIdx = _fnVisibleToColumnIndex( oSettings, i );
5566         
5567                                 if ( colIdx !== null ) {
5568                                         columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );
5569                                 }
5570                         }
5571                 }
5572                 else
5573                 {
5574                         // Otherwise construct a single row, worst case, table with the widest
5575                         // node in the data, assign any user defined widths, then insert it into
5576                         // the DOM and allow the browser to do all the hard work of calculating
5577                         // table widths
5578                         var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
5579                                 .css( 'visibility', 'hidden' )
5580                                 .removeAttr( 'id' );
5581         
5582                         // Clean up the table body
5583                         tmpTable.find('tbody tr').remove();
5584                         var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );
5585         
5586                         // Clone the table header and footer - we can't use the header / footer
5587                         // from the cloned table, since if scrolling is active, the table's
5588                         // real header and footer are contained in different table tags
5589                         tmpTable.find('thead, tfoot').remove();
5590                         tmpTable
5591                                 .append( $(oSettings.nTHead).clone() )
5592                                 .append( $(oSettings.nTFoot).clone() );
5593         
5594                         // Remove any assigned widths from the footer (from scrolling)
5595                         tmpTable.find('tfoot th, tfoot td').css('width', '');
5596         
5597                         // Apply custom sizing to the cloned header
5598                         headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
5599         
5600                         for ( i=0 ; i<visibleColumns.length ; i++ ) {
5601                                 column = columns[ visibleColumns[i] ];
5602         
5603                                 headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
5604                                         _fnStringToCss( column.sWidthOrig ) :
5605                                         '';
5606         
5607                                 // For scrollX we need to force the column width otherwise the
5608                                 // browser will collapse it. If this width is smaller than the
5609                                 // width the column requires, then it will have no effect
5610                                 if ( column.sWidthOrig && scrollX ) {
5611                                         $( headerCells[i] ).append( $('<div/>').css( {
5612                                                 width: column.sWidthOrig,
5613                                                 margin: 0,
5614                                                 padding: 0,
5615                                                 border: 0,
5616                                                 height: 1
5617                                         } ) );
5618                                 }
5619                         }
5620         
5621                         // Find the widest cell for each column and put it into the table
5622                         if ( oSettings.aoData.length ) {
5623                                 for ( i=0 ; i<visibleColumns.length ; i++ ) {
5624                                         columnIdx = visibleColumns[i];
5625                                         column = columns[ columnIdx ];
5626         
5627                                         $( _fnGetWidestNode( oSettings, columnIdx ) )
5628                                                 .clone( false )
5629                                                 .append( column.sContentPadding )
5630                                                 .appendTo( tr );
5631                                 }
5632                         }
5633         
5634                         // Tidy the temporary table - remove name attributes so there aren't
5635                         // duplicated in the dom (radio elements for example)
5636                         $('[name]', tmpTable).removeAttr('name');
5637         
5638                         // Table has been built, attach to the document so we can work with it.
5639                         // A holding element is used, positioned at the top of the container
5640                         // with minimal height, so it has no effect on if the container scrolls
5641                         // or not. Otherwise it might trigger scrolling when it actually isn't
5642                         // needed
5643                         var holder = $('<div/>').css( scrollX || scrollY ?
5644                                         {
5645                                                 position: 'absolute',
5646                                                 top: 0,
5647                                                 left: 0,
5648                                                 height: 1,
5649                                                 right: 0,
5650                                                 overflow: 'hidden'
5651                                         } :
5652                                         {}
5653                                 )
5654                                 .append( tmpTable )
5655                                 .appendTo( tableContainer );
5656         
5657                         // When scrolling (X or Y) we want to set the width of the table as 
5658                         // appropriate. However, when not scrolling leave the table width as it
5659                         // is. This results in slightly different, but I think correct behaviour
5660                         if ( scrollX && scrollXInner ) {
5661                                 tmpTable.width( scrollXInner );
5662                         }
5663                         else if ( scrollX ) {
5664                                 tmpTable.css( 'width', 'auto' );
5665                                 tmpTable.removeAttr('width');
5666         
5667                                 // If there is no width attribute or style, then allow the table to
5668                                 // collapse
5669                                 if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {
5670                                         tmpTable.width( tableContainer.clientWidth );
5671                                 }
5672                         }
5673                         else if ( scrollY ) {
5674                                 tmpTable.width( tableContainer.clientWidth );
5675                         }
5676                         else if ( tableWidthAttr ) {
5677                                 tmpTable.width( tableWidthAttr );
5678                         }
5679         
5680                         // Get the width of each column in the constructed table - we need to
5681                         // know the inner width (so it can be assigned to the other table's
5682                         // cells) and the outer width so we can calculate the full width of the
5683                         // table. This is safe since DataTables requires a unique cell for each
5684                         // column, but if ever a header can span multiple columns, this will
5685                         // need to be modified.
5686                         var total = 0;
5687                         for ( i=0 ; i<visibleColumns.length ; i++ ) {
5688                                 var cell = $(headerCells[i]);
5689                                 var border = cell.outerWidth() - cell.width();
5690         
5691                                 // Use getBounding... where possible (not IE8-) because it can give
5692                                 // sub-pixel accuracy, which we then want to round up!
5693                                 var bounding = browser.bBounding ?
5694                                         Math.ceil( headerCells[i].getBoundingClientRect().width ) :
5695                                         cell.outerWidth();
5696         
5697                                 // Total is tracked to remove any sub-pixel errors as the outerWidth
5698                                 // of the table might not equal the total given here (IE!).
5699                                 total += bounding;
5700         
5701                                 // Width for each column to use
5702                                 columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );
5703                         }
5704         
5705                         table.style.width = _fnStringToCss( total );
5706         
5707                         // Finished with the table - ditch it
5708                         holder.remove();
5709                 }
5710         
5711                 // If there is a width attr, we want to attach an event listener which
5712                 // allows the table sizing to automatically adjust when the window is
5713                 // resized. Use the width attr rather than CSS, since we can't know if the
5714                 // CSS is a relative value or absolute - DOM read is always px.
5715                 if ( tableWidthAttr ) {
5716                         table.style.width = _fnStringToCss( tableWidthAttr );
5717                 }
5718         
5719                 if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
5720                         var bindResize = function () {
5721                                 $(window).on('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
5722                                         _fnAdjustColumnSizing( oSettings );
5723                                 } ) );
5724                         };
5725         
5726                         // IE6/7 will crash if we bind a resize event handler on page load.
5727                         // To be removed in 1.11 which drops IE6/7 support
5728                         if ( ie67 ) {
5729                                 setTimeout( bindResize, 1000 );
5730                         }
5731                         else {
5732                                 bindResize();
5733                         }
5734         
5735                         oSettings._reszEvt = true;
5736                 }
5737         }
5738         
5739         
5740         /**
5741          * Throttle the calls to a function. Arguments and context are maintained for
5742          * the throttled function
5743          *  @param {function} fn Function to be called
5744          *  @param {int} [freq=200] call frequency in mS
5745          *  @returns {function} wrapped function
5746          *  @memberof DataTable#oApi
5747          */
5748         var _fnThrottle = DataTable.util.throttle;
5749         
5750         
5751         /**
5752          * Convert a CSS unit width to pixels (e.g. 2em)
5753          *  @param {string} width width to be converted
5754          *  @param {node} parent parent to get the with for (required for relative widths) - optional
5755          *  @returns {int} width in pixels
5756          *  @memberof DataTable#oApi
5757          */
5758         function _fnConvertToWidth ( width, parent )
5759         {
5760                 if ( ! width ) {
5761                         return 0;
5762                 }
5763         
5764                 var n = $('<div/>')
5765                         .css( 'width', _fnStringToCss( width ) )
5766                         .appendTo( parent || document.body );
5767         
5768                 var val = n[0].offsetWidth;
5769                 n.remove();
5770         
5771                 return val;
5772         }
5773         
5774         
5775         /**
5776          * Get the widest node
5777          *  @param {object} settings dataTables settings object
5778          *  @param {int} colIdx column of interest
5779          *  @returns {node} widest table node
5780          *  @memberof DataTable#oApi
5781          */
5782         function _fnGetWidestNode( settings, colIdx )
5783         {
5784                 var idx = _fnGetMaxLenString( settings, colIdx );
5785                 if ( idx < 0 ) {
5786                         return null;
5787                 }
5788         
5789                 var data = settings.aoData[ idx ];
5790                 return ! data.nTr ? // Might not have been created when deferred rendering
5791                         $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
5792                         data.anCells[ colIdx ];
5793         }
5794         
5795         
5796         /**
5797          * Get the maximum strlen for each data column
5798          *  @param {object} settings dataTables settings object
5799          *  @param {int} colIdx column of interest
5800          *  @returns {string} max string length for each column
5801          *  @memberof DataTable#oApi
5802          */
5803         function _fnGetMaxLenString( settings, colIdx )
5804         {
5805                 var s, max=-1, maxIdx = -1;
5806         
5807                 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
5808                         s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
5809                         s = s.replace( __re_html_remove, '' );
5810                         s = s.replace( /&nbsp;/g, ' ' );
5811         
5812                         if ( s.length > max ) {
5813                                 max = s.length;
5814                                 maxIdx = i;
5815                         }
5816                 }
5817         
5818                 return maxIdx;
5819         }
5820         
5821         
5822         /**
5823          * Append a CSS unit (only if required) to a string
5824          *  @param {string} value to css-ify
5825          *  @returns {string} value with css unit
5826          *  @memberof DataTable#oApi
5827          */
5828         function _fnStringToCss( s )
5829         {
5830                 if ( s === null ) {
5831                         return '0px';
5832                 }
5833         
5834                 if ( typeof s == 'number' ) {
5835                         return s < 0 ?
5836                                 '0px' :
5837                                 s+'px';
5838                 }
5839         
5840                 // Check it has a unit character already
5841                 return s.match(/\d$/) ?
5842                         s+'px' :
5843                         s;
5844         }
5845         
5846         
5847         
5848         function _fnSortFlatten ( settings )
5849         {
5850                 var
5851                         i, iLen, k, kLen,
5852                         aSort = [],
5853                         aiOrig = [],
5854                         aoColumns = settings.aoColumns,
5855                         aDataSort, iCol, sType, srcCol,
5856                         fixed = settings.aaSortingFixed,
5857                         fixedObj = $.isPlainObject( fixed ),
5858                         nestedSort = [],
5859                         add = function ( a ) {
5860                                 if ( a.length && ! $.isArray( a[0] ) ) {
5861                                         // 1D array
5862                                         nestedSort.push( a );
5863                                 }
5864                                 else {
5865                                         // 2D array
5866                                         $.merge( nestedSort, a );
5867                                 }
5868                         };
5869         
5870                 // Build the sort array, with pre-fix and post-fix options if they have been
5871                 // specified
5872                 if ( $.isArray( fixed ) ) {
5873                         add( fixed );
5874                 }
5875         
5876                 if ( fixedObj && fixed.pre ) {
5877                         add( fixed.pre );
5878                 }
5879         
5880                 add( settings.aaSorting );
5881         
5882                 if (fixedObj && fixed.post ) {
5883                         add( fixed.post );
5884                 }
5885         
5886                 for ( i=0 ; i<nestedSort.length ; i++ )
5887                 {
5888                         srcCol = nestedSort[i][0];
5889                         aDataSort = aoColumns[ srcCol ].aDataSort;
5890         
5891                         for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
5892                         {
5893                                 iCol = aDataSort[k];
5894                                 sType = aoColumns[ iCol ].sType || 'string';
5895         
5896                                 if ( nestedSort[i]._idx === undefined ) {
5897                                         nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );
5898                                 }
5899         
5900                                 aSort.push( {
5901                                         src:       srcCol,
5902                                         col:       iCol,
5903                                         dir:       nestedSort[i][1],
5904                                         index:     nestedSort[i]._idx,
5905                                         type:      sType,
5906                                         formatter: DataTable.ext.type.order[ sType+"-pre" ]
5907                                 } );
5908                         }
5909                 }
5910         
5911                 return aSort;
5912         }
5913         
5914         /**
5915          * Change the order of the table
5916          *  @param {object} oSettings dataTables settings object
5917          *  @memberof DataTable#oApi
5918          *  @todo This really needs split up!
5919          */
5920         function _fnSort ( oSettings )
5921         {
5922                 var
5923                         i, ien, iLen, j, jLen, k, kLen,
5924                         sDataType, nTh,
5925                         aiOrig = [],
5926                         oExtSort = DataTable.ext.type.order,
5927                         aoData = oSettings.aoData,
5928                         aoColumns = oSettings.aoColumns,
5929                         aDataSort, data, iCol, sType, oSort,
5930                         formatters = 0,
5931                         sortCol,
5932                         displayMaster = oSettings.aiDisplayMaster,
5933                         aSort;
5934         
5935                 // Resolve any column types that are unknown due to addition or invalidation
5936                 // @todo Can this be moved into a 'data-ready' handler which is called when
5937                 //   data is going to be used in the table?
5938                 _fnColumnTypes( oSettings );
5939         
5940                 aSort = _fnSortFlatten( oSettings );
5941         
5942                 for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
5943                         sortCol = aSort[i];
5944         
5945                         // Track if we can use the fast sort algorithm
5946                         if ( sortCol.formatter ) {
5947                                 formatters++;
5948                         }
5949         
5950                         // Load the data needed for the sort, for each cell
5951                         _fnSortData( oSettings, sortCol.col );
5952                 }
5953         
5954                 /* No sorting required if server-side or no sorting array */
5955                 if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
5956                 {
5957                         // Create a value - key array of the current row positions such that we can use their
5958                         // current position during the sort, if values match, in order to perform stable sorting
5959                         for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
5960                                 aiOrig[ displayMaster[i] ] = i;
5961                         }
5962         
5963                         /* Do the sort - here we want multi-column sorting based on a given data source (column)
5964                          * and sorting function (from oSort) in a certain direction. It's reasonably complex to
5965                          * follow on it's own, but this is what we want (example two column sorting):
5966                          *  fnLocalSorting = function(a,b){
5967                          *    var iTest;
5968                          *    iTest = oSort['string-asc']('data11', 'data12');
5969                          *      if (iTest !== 0)
5970                          *        return iTest;
5971                          *    iTest = oSort['numeric-desc']('data21', 'data22');
5972                          *    if (iTest !== 0)
5973                          *      return iTest;
5974                          *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
5975                          *  }
5976                          * Basically we have a test for each sorting column, if the data in that column is equal,
5977                          * test the next column. If all columns match, then we use a numeric sort on the row
5978                          * positions in the original data array to provide a stable sort.
5979                          *
5980                          * Note - I know it seems excessive to have two sorting methods, but the first is around
5981                          * 15% faster, so the second is only maintained for backwards compatibility with sorting
5982                          * methods which do not have a pre-sort formatting function.
5983                          */
5984                         if ( formatters === aSort.length ) {
5985                                 // All sort types have formatting functions
5986                                 displayMaster.sort( function ( a, b ) {
5987                                         var
5988                                                 x, y, k, test, sort,
5989                                                 len=aSort.length,
5990                                                 dataA = aoData[a]._aSortData,
5991                                                 dataB = aoData[b]._aSortData;
5992         
5993                                         for ( k=0 ; k<len ; k++ ) {
5994                                                 sort = aSort[k];
5995         
5996                                                 x = dataA[ sort.col ];
5997                                                 y = dataB[ sort.col ];
5998         
5999                                                 test = x<y ? -1 : x>y ? 1 : 0;
6000                                                 if ( test !== 0 ) {
6001                                                         return sort.dir === 'asc' ? test : -test;
6002                                                 }
6003                                         }
6004         
6005                                         x = aiOrig[a];
6006                                         y = aiOrig[b];
6007                                         return x<y ? -1 : x>y ? 1 : 0;
6008                                 } );
6009                         }
6010                         else {
6011                                 // Depreciated - remove in 1.11 (providing a plug-in option)
6012                                 // Not all sort types have formatting methods, so we have to call their sorting
6013                                 // methods.
6014                                 displayMaster.sort( function ( a, b ) {
6015                                         var
6016                                                 x, y, k, l, test, sort, fn,
6017                                                 len=aSort.length,
6018                                                 dataA = aoData[a]._aSortData,
6019                                                 dataB = aoData[b]._aSortData;
6020         
6021                                         for ( k=0 ; k<len ; k++ ) {
6022                                                 sort = aSort[k];
6023         
6024                                                 x = dataA[ sort.col ];
6025                                                 y = dataB[ sort.col ];
6026         
6027                                                 fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
6028                                                 test = fn( x, y );
6029                                                 if ( test !== 0 ) {
6030                                                         return test;
6031                                                 }
6032                                         }
6033         
6034                                         x = aiOrig[a];
6035                                         y = aiOrig[b];
6036                                         return x<y ? -1 : x>y ? 1 : 0;
6037                                 } );
6038                         }
6039                 }
6040         
6041                 /* Tell the draw function that we have sorted the data */
6042                 oSettings.bSorted = true;
6043         }
6044         
6045         
6046         function _fnSortAria ( settings )
6047         {
6048                 var label;
6049                 var nextSort;
6050                 var columns = settings.aoColumns;
6051                 var aSort = _fnSortFlatten( settings );
6052                 var oAria = settings.oLanguage.oAria;
6053         
6054                 // ARIA attributes - need to loop all columns, to update all (removing old
6055                 // attributes as needed)
6056                 for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
6057                 {
6058                         var col = columns[i];
6059                         var asSorting = col.asSorting;
6060                         var sTitle = col.sTitle.replace( /<.*?>/g, "" );
6061                         var th = col.nTh;
6062         
6063                         // IE7 is throwing an error when setting these properties with jQuery's
6064                         // attr() and removeAttr() methods...
6065                         th.removeAttribute('aria-sort');
6066         
6067                         /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
6068                         if ( col.bSortable ) {
6069                                 if ( aSort.length > 0 && aSort[0].col == i ) {
6070                                         th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
6071                                         nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
6072                                 }
6073                                 else {
6074                                         nextSort = asSorting[0];
6075                                 }
6076         
6077                                 label = sTitle + ( nextSort === "asc" ?
6078                                         oAria.sSortAscending :
6079                                         oAria.sSortDescending
6080                                 );
6081                         }
6082                         else {
6083                                 label = sTitle;
6084                         }
6085         
6086                         th.setAttribute('aria-label', label);
6087                 }
6088         }
6089         
6090         
6091         /**
6092          * Function to run on user sort request
6093          *  @param {object} settings dataTables settings object
6094          *  @param {node} attachTo node to attach the handler to
6095          *  @param {int} colIdx column sorting index
6096          *  @param {boolean} [append=false] Append the requested sort to the existing
6097          *    sort if true (i.e. multi-column sort)
6098          *  @param {function} [callback] callback function
6099          *  @memberof DataTable#oApi
6100          */
6101         function _fnSortListener ( settings, colIdx, append, callback )
6102         {
6103                 var col = settings.aoColumns[ colIdx ];
6104                 var sorting = settings.aaSorting;
6105                 var asSorting = col.asSorting;
6106                 var nextSortIdx;
6107                 var next = function ( a, overflow ) {
6108                         var idx = a._idx;
6109                         if ( idx === undefined ) {
6110                                 idx = $.inArray( a[1], asSorting );
6111                         }
6112         
6113                         return idx+1 < asSorting.length ?
6114                                 idx+1 :
6115                                 overflow ?
6116                                         null :
6117                                         0;
6118                 };
6119         
6120                 // Convert to 2D array if needed
6121                 if ( typeof sorting[0] === 'number' ) {
6122                         sorting = settings.aaSorting = [ sorting ];
6123                 }
6124         
6125                 // If appending the sort then we are multi-column sorting
6126                 if ( append && settings.oFeatures.bSortMulti ) {
6127                         // Are we already doing some kind of sort on this column?
6128                         var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
6129         
6130                         if ( sortIdx !== -1 ) {
6131                                 // Yes, modify the sort
6132                                 nextSortIdx = next( sorting[sortIdx], true );
6133         
6134                                 if ( nextSortIdx === null && sorting.length === 1 ) {
6135                                         nextSortIdx = 0; // can't remove sorting completely
6136                                 }
6137         
6138                                 if ( nextSortIdx === null ) {
6139                                         sorting.splice( sortIdx, 1 );
6140                                 }
6141                                 else {
6142                                         sorting[sortIdx][1] = asSorting[ nextSortIdx ];
6143                                         sorting[sortIdx]._idx = nextSortIdx;
6144                                 }
6145                         }
6146                         else {
6147                                 // No sort on this column yet
6148                                 sorting.push( [ colIdx, asSorting[0], 0 ] );
6149                                 sorting[sorting.length-1]._idx = 0;
6150                         }
6151                 }
6152                 else if ( sorting.length && sorting[0][0] == colIdx ) {
6153                         // Single column - already sorting on this column, modify the sort
6154                         nextSortIdx = next( sorting[0] );
6155         
6156                         sorting.length = 1;
6157                         sorting[0][1] = asSorting[ nextSortIdx ];
6158                         sorting[0]._idx = nextSortIdx;
6159                 }
6160                 else {
6161                         // Single column - sort only on this column
6162                         sorting.length = 0;
6163                         sorting.push( [ colIdx, asSorting[0] ] );
6164                         sorting[0]._idx = 0;
6165                 }
6166         
6167                 // Run the sort by calling a full redraw
6168                 _fnReDraw( settings );
6169         
6170                 // callback used for async user interaction
6171                 if ( typeof callback == 'function' ) {
6172                         callback( settings );
6173                 }
6174         }
6175         
6176         
6177         /**
6178          * Attach a sort handler (click) to a node
6179          *  @param {object} settings dataTables settings object
6180          *  @param {node} attachTo node to attach the handler to
6181          *  @param {int} colIdx column sorting index
6182          *  @param {function} [callback] callback function
6183          *  @memberof DataTable#oApi
6184          */
6185         function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
6186         {
6187                 var col = settings.aoColumns[ colIdx ];
6188         
6189                 _fnBindAction( attachTo, {}, function (e) {
6190                         /* If the column is not sortable - don't to anything */
6191                         if ( col.bSortable === false ) {
6192                                 return;
6193                         }
6194         
6195                         // If processing is enabled use a timeout to allow the processing
6196                         // display to be shown - otherwise to it synchronously
6197                         if ( settings.oFeatures.bProcessing ) {
6198                                 _fnProcessingDisplay( settings, true );
6199         
6200                                 setTimeout( function() {
6201                                         _fnSortListener( settings, colIdx, e.shiftKey, callback );
6202         
6203                                         // In server-side processing, the draw callback will remove the
6204                                         // processing display
6205                                         if ( _fnDataSource( settings ) !== 'ssp' ) {
6206                                                 _fnProcessingDisplay( settings, false );
6207                                         }
6208                                 }, 0 );
6209                         }
6210                         else {
6211                                 _fnSortListener( settings, colIdx, e.shiftKey, callback );
6212                         }
6213                 } );
6214         }
6215         
6216         
6217         /**
6218          * Set the sorting classes on table's body, Note: it is safe to call this function
6219          * when bSort and bSortClasses are false
6220          *  @param {object} oSettings dataTables settings object
6221          *  @memberof DataTable#oApi
6222          */
6223         function _fnSortingClasses( settings )
6224         {
6225                 var oldSort = settings.aLastSort;
6226                 var sortClass = settings.oClasses.sSortColumn;
6227                 var sort = _fnSortFlatten( settings );
6228                 var features = settings.oFeatures;
6229                 var i, ien, colIdx;
6230         
6231                 if ( features.bSort && features.bSortClasses ) {
6232                         // Remove old sorting classes
6233                         for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
6234                                 colIdx = oldSort[i].src;
6235         
6236                                 // Remove column sorting
6237                                 $( _pluck( settings.aoData, 'anCells', colIdx ) )
6238                                         .removeClass( sortClass + (i<2 ? i+1 : 3) );
6239                         }
6240         
6241                         // Add new column sorting
6242                         for ( i=0, ien=sort.length ; i<ien ; i++ ) {
6243                                 colIdx = sort[i].src;
6244         
6245                                 $( _pluck( settings.aoData, 'anCells', colIdx ) )
6246                                         .addClass( sortClass + (i<2 ? i+1 : 3) );
6247                         }
6248                 }
6249         
6250                 settings.aLastSort = sort;
6251         }
6252         
6253         
6254         // Get the data to sort a column, be it from cache, fresh (populating the
6255         // cache), or from a sort formatter
6256         function _fnSortData( settings, idx )
6257         {
6258                 // Custom sorting function - provided by the sort data type
6259                 var column = settings.aoColumns[ idx ];
6260                 var customSort = DataTable.ext.order[ column.sSortDataType ];
6261                 var customData;
6262         
6263                 if ( customSort ) {
6264                         customData = customSort.call( settings.oInstance, settings, idx,
6265                                 _fnColumnIndexToVisible( settings, idx )
6266                         );
6267                 }
6268         
6269                 // Use / populate cache
6270                 var row, cellData;
6271                 var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
6272         
6273                 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
6274                         row = settings.aoData[i];
6275         
6276                         if ( ! row._aSortData ) {
6277                                 row._aSortData = [];
6278                         }
6279         
6280                         if ( ! row._aSortData[idx] || customSort ) {
6281                                 cellData = customSort ?
6282                                         customData[i] : // If there was a custom sort function, use data from there
6283                                         _fnGetCellData( settings, i, idx, 'sort' );
6284         
6285                                 row._aSortData[ idx ] = formatter ?
6286                                         formatter( cellData ) :
6287                                         cellData;
6288                         }
6289                 }
6290         }
6291         
6292         
6293         
6294         /**
6295          * Save the state of a table
6296          *  @param {object} oSettings dataTables settings object
6297          *  @memberof DataTable#oApi
6298          */
6299         function _fnSaveState ( settings )
6300         {
6301                 if ( !settings.oFeatures.bStateSave || settings.bDestroying )
6302                 {
6303                         return;
6304                 }
6305         
6306                 /* Store the interesting variables */
6307                 var state = {
6308                         time:    +new Date(),
6309                         start:   settings._iDisplayStart,
6310                         length:  settings._iDisplayLength,
6311                         order:   $.extend( true, [], settings.aaSorting ),
6312                         search:  _fnSearchToCamel( settings.oPreviousSearch ),
6313                         columns: $.map( settings.aoColumns, function ( col, i ) {
6314                                 return {
6315                                         visible: col.bVisible,
6316                                         search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
6317                                 };
6318                         } )
6319                 };
6320         
6321                 _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
6322         
6323                 settings.oSavedState = state;
6324                 settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
6325         }
6326         
6327         
6328         /**
6329          * Attempt to load a saved table state
6330          *  @param {object} oSettings dataTables settings object
6331          *  @param {object} oInit DataTables init object so we can override settings
6332          *  @param {function} callback Callback to execute when the state has been loaded
6333          *  @memberof DataTable#oApi
6334          */
6335         function _fnLoadState ( settings, oInit, callback )
6336         {
6337                 var i, ien;
6338                 var columns = settings.aoColumns;
6339                 var loaded = function ( s ) {
6340                         if ( ! s || ! s.time ) {
6341                                 callback();
6342                                 return;
6343                         }
6344         
6345                         // Allow custom and plug-in manipulation functions to alter the saved data set and
6346                         // cancelling of loading by returning false
6347                         var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, s] );
6348                         if ( $.inArray( false, abStateLoad ) !== -1 ) {
6349                                 callback();
6350                                 return;
6351                         }
6352         
6353                         // Reject old data
6354                         var duration = settings.iStateDuration;
6355                         if ( duration > 0 && s.time < +new Date() - (duration*1000) ) {
6356                                 callback();
6357                                 return;
6358                         }
6359         
6360                         // Number of columns have changed - all bets are off, no restore of settings
6361                         if ( s.columns && columns.length !== s.columns.length ) {
6362                                 callback();
6363                                 return;
6364                         }
6365         
6366                         // Store the saved state so it might be accessed at any time
6367                         settings.oLoadedState = $.extend( true, {}, s );
6368         
6369                         // Restore key features - todo - for 1.11 this needs to be done by
6370                         // subscribed events
6371                         if ( s.start !== undefined ) {
6372                                 settings._iDisplayStart    = s.start;
6373                                 settings.iInitDisplayStart = s.start;
6374                         }
6375                         if ( s.length !== undefined ) {
6376                                 settings._iDisplayLength   = s.length;
6377                         }
6378         
6379                         // Order
6380                         if ( s.order !== undefined ) {
6381                                 settings.aaSorting = [];
6382                                 $.each( s.order, function ( i, col ) {
6383                                         settings.aaSorting.push( col[0] >= columns.length ?
6384                                                 [ 0, col[1] ] :
6385                                                 col
6386                                         );
6387                                 } );
6388                         }
6389         
6390                         // Search
6391                         if ( s.search !== undefined ) {
6392                                 $.extend( settings.oPreviousSearch, _fnSearchToHung( s.search ) );
6393                         }
6394         
6395                         // Columns
6396                         //
6397                         if ( s.columns ) {
6398                                 for ( i=0, ien=s.columns.length ; i<ien ; i++ ) {
6399                                         var col = s.columns[i];
6400         
6401                                         // Visibility
6402                                         if ( col.visible !== undefined ) {
6403                                                 columns[i].bVisible = col.visible;
6404                                         }
6405         
6406                                         // Search
6407                                         if ( col.search !== undefined ) {
6408                                                 $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
6409                                         }
6410                                 }
6411                         }
6412         
6413                         _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, s] );
6414                         callback();
6415                 }
6416         
6417                 if ( ! settings.oFeatures.bStateSave ) {
6418                         callback();
6419                         return;
6420                 }
6421         
6422                 var state = settings.fnStateLoadCallback.call( settings.oInstance, settings, loaded );
6423         
6424                 if ( state !== undefined ) {
6425                         loaded( state );
6426                 }
6427                 // otherwise, wait for the loaded callback to be executed
6428         }
6429         
6430         
6431         /**
6432          * Return the settings object for a particular table
6433          *  @param {node} table table we are using as a dataTable
6434          *  @returns {object} Settings object - or null if not found
6435          *  @memberof DataTable#oApi
6436          */
6437         function _fnSettingsFromNode ( table )
6438         {
6439                 var settings = DataTable.settings;
6440                 var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
6441         
6442                 return idx !== -1 ?
6443                         settings[ idx ] :
6444                         null;
6445         }
6446         
6447         
6448         /**
6449          * Log an error message
6450          *  @param {object} settings dataTables settings object
6451          *  @param {int} level log error messages, or display them to the user
6452          *  @param {string} msg error message
6453          *  @param {int} tn Technical note id to get more information about the error.
6454          *  @memberof DataTable#oApi
6455          */
6456         function _fnLog( settings, level, msg, tn )
6457         {
6458                 msg = 'DataTables warning: '+
6459                         (settings ? 'table id='+settings.sTableId+' - ' : '')+msg;
6460         
6461                 if ( tn ) {
6462                         msg += '. For more information about this error, please see '+
6463                         'http://datatables.net/tn/'+tn;
6464                 }
6465         
6466                 if ( ! level  ) {
6467                         // Backwards compatibility pre 1.10
6468                         var ext = DataTable.ext;
6469                         var type = ext.sErrMode || ext.errMode;
6470         
6471                         if ( settings ) {
6472                                 _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );
6473                         }
6474         
6475                         if ( type == 'alert' ) {
6476                                 alert( msg );
6477                         }
6478                         else if ( type == 'throw' ) {
6479                                 throw new Error(msg);
6480                         }
6481                         else if ( typeof type == 'function' ) {
6482                                 type( settings, tn, msg );
6483                         }
6484                 }
6485                 else if ( window.console && console.log ) {
6486                         console.log( msg );
6487                 }
6488         }
6489         
6490         
6491         /**
6492          * See if a property is defined on one object, if so assign it to the other object
6493          *  @param {object} ret target object
6494          *  @param {object} src source object
6495          *  @param {string} name property
6496          *  @param {string} [mappedName] name to map too - optional, name used if not given
6497          *  @memberof DataTable#oApi
6498          */
6499         function _fnMap( ret, src, name, mappedName )
6500         {
6501                 if ( $.isArray( name ) ) {
6502                         $.each( name, function (i, val) {
6503                                 if ( $.isArray( val ) ) {
6504                                         _fnMap( ret, src, val[0], val[1] );
6505                                 }
6506                                 else {
6507                                         _fnMap( ret, src, val );
6508                                 }
6509                         } );
6510         
6511                         return;
6512                 }
6513         
6514                 if ( mappedName === undefined ) {
6515                         mappedName = name;
6516                 }
6517         
6518                 if ( src[name] !== undefined ) {
6519                         ret[mappedName] = src[name];
6520                 }
6521         }
6522         
6523         
6524         /**
6525          * Extend objects - very similar to jQuery.extend, but deep copy objects, and
6526          * shallow copy arrays. The reason we need to do this, is that we don't want to
6527          * deep copy array init values (such as aaSorting) since the dev wouldn't be
6528          * able to override them, but we do want to deep copy arrays.
6529          *  @param {object} out Object to extend
6530          *  @param {object} extender Object from which the properties will be applied to
6531          *      out
6532          *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
6533          *      independent copy with the exception of the `data` or `aaData` parameters
6534          *      if they are present. This is so you can pass in a collection to
6535          *      DataTables and have that used as your data source without breaking the
6536          *      references
6537          *  @returns {object} out Reference, just for convenience - out === the return.
6538          *  @memberof DataTable#oApi
6539          *  @todo This doesn't take account of arrays inside the deep copied objects.
6540          */
6541         function _fnExtend( out, extender, breakRefs )
6542         {
6543                 var val;
6544         
6545                 for ( var prop in extender ) {
6546                         if ( extender.hasOwnProperty(prop) ) {
6547                                 val = extender[prop];
6548         
6549                                 if ( $.isPlainObject( val ) ) {
6550                                         if ( ! $.isPlainObject( out[prop] ) ) {
6551                                                 out[prop] = {};
6552                                         }
6553                                         $.extend( true, out[prop], val );
6554                                 }
6555                                 else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
6556                                         out[prop] = val.slice();
6557                                 }
6558                                 else {
6559                                         out[prop] = val;
6560                                 }
6561                         }
6562                 }
6563         
6564                 return out;
6565         }
6566         
6567         
6568         /**
6569          * Bind an event handers to allow a click or return key to activate the callback.
6570          * This is good for accessibility since a return on the keyboard will have the
6571          * same effect as a click, if the element has focus.
6572          *  @param {element} n Element to bind the action to
6573          *  @param {object} oData Data object to pass to the triggered function
6574          *  @param {function} fn Callback function for when the event is triggered
6575          *  @memberof DataTable#oApi
6576          */
6577         function _fnBindAction( n, oData, fn )
6578         {
6579                 $(n)
6580                         .on( 'click.DT', oData, function (e) {
6581                                         n.blur(); // Remove focus outline for mouse users
6582                                         fn(e);
6583                                 } )
6584                         .on( 'keypress.DT', oData, function (e){
6585                                         if ( e.which === 13 ) {
6586                                                 e.preventDefault();
6587                                                 fn(e);
6588                                         }
6589                                 } )
6590                         .on( 'selectstart.DT', function () {
6591                                         /* Take the brutal approach to cancelling text selection */
6592                                         return false;
6593                                 } );
6594         }
6595         
6596         
6597         /**
6598          * Register a callback function. Easily allows a callback function to be added to
6599          * an array store of callback functions that can then all be called together.
6600          *  @param {object} oSettings dataTables settings object
6601          *  @param {string} sStore Name of the array storage for the callbacks in oSettings
6602          *  @param {function} fn Function to be called back
6603          *  @param {string} sName Identifying name for the callback (i.e. a label)
6604          *  @memberof DataTable#oApi
6605          */
6606         function _fnCallbackReg( oSettings, sStore, fn, sName )
6607         {
6608                 if ( fn )
6609                 {
6610                         oSettings[sStore].push( {
6611                                 "fn": fn,
6612                                 "sName": sName
6613                         } );
6614                 }
6615         }
6616         
6617         
6618         /**
6619          * Fire callback functions and trigger events. Note that the loop over the
6620          * callback array store is done backwards! Further note that you do not want to
6621          * fire off triggers in time sensitive applications (for example cell creation)
6622          * as its slow.
6623          *  @param {object} settings dataTables settings object
6624          *  @param {string} callbackArr Name of the array storage for the callbacks in
6625          *      oSettings
6626          *  @param {string} eventName Name of the jQuery custom event to trigger. If
6627          *      null no trigger is fired
6628          *  @param {array} args Array of arguments to pass to the callback function /
6629          *      trigger
6630          *  @memberof DataTable#oApi
6631          */
6632         function _fnCallbackFire( settings, callbackArr, eventName, args )
6633         {
6634                 var ret = [];
6635         
6636                 if ( callbackArr ) {
6637                         ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
6638                                 return val.fn.apply( settings.oInstance, args );
6639                         } );
6640                 }
6641         
6642                 if ( eventName !== null ) {
6643                         var e = $.Event( eventName+'.dt' );
6644         
6645                         $(settings.nTable).trigger( e, args );
6646         
6647                         ret.push( e.result );
6648                 }
6649         
6650                 return ret;
6651         }
6652         
6653         
6654         function _fnLengthOverflow ( settings )
6655         {
6656                 var
6657                         start = settings._iDisplayStart,
6658                         end = settings.fnDisplayEnd(),
6659                         len = settings._iDisplayLength;
6660         
6661                 /* If we have space to show extra rows (backing up from the end point - then do so */
6662                 if ( start >= end )
6663                 {
6664                         start = end - len;
6665                 }
6666         
6667                 // Keep the start record on the current page
6668                 start -= (start % len);
6669         
6670                 if ( len === -1 || start < 0 )
6671                 {
6672                         start = 0;
6673                 }
6674         
6675                 settings._iDisplayStart = start;
6676         }
6677         
6678         
6679         function _fnRenderer( settings, type )
6680         {
6681                 var renderer = settings.renderer;
6682                 var host = DataTable.ext.renderer[type];
6683         
6684                 if ( $.isPlainObject( renderer ) && renderer[type] ) {
6685                         // Specific renderer for this type. If available use it, otherwise use
6686                         // the default.
6687                         return host[renderer[type]] || host._;
6688                 }
6689                 else if ( typeof renderer === 'string' ) {
6690                         // Common renderer - if there is one available for this type use it,
6691                         // otherwise use the default
6692                         return host[renderer] || host._;
6693                 }
6694         
6695                 // Use the default
6696                 return host._;
6697         }
6698         
6699         
6700         /**
6701          * Detect the data source being used for the table. Used to simplify the code
6702          * a little (ajax) and to make it compress a little smaller.
6703          *
6704          *  @param {object} settings dataTables settings object
6705          *  @returns {string} Data source
6706          *  @memberof DataTable#oApi
6707          */
6708         function _fnDataSource ( settings )
6709         {
6710                 if ( settings.oFeatures.bServerSide ) {
6711                         return 'ssp';
6712                 }
6713                 else if ( settings.ajax || settings.sAjaxSource ) {
6714                         return 'ajax';
6715                 }
6716                 return 'dom';
6717         }
6718         
6719
6720         
6721         
6722         /**
6723          * Computed structure of the DataTables API, defined by the options passed to
6724          * `DataTable.Api.register()` when building the API.
6725          *
6726          * The structure is built in order to speed creation and extension of the Api
6727          * objects since the extensions are effectively pre-parsed.
6728          *
6729          * The array is an array of objects with the following structure, where this
6730          * base array represents the Api prototype base:
6731          *
6732          *     [
6733          *       {
6734          *         name:      'data'                -- string   - Property name
6735          *         val:       function () {},       -- function - Api method (or undefined if just an object
6736          *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6737          *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6738          *       },
6739          *       {
6740          *         name:     'row'
6741          *         val:       {},
6742          *         methodExt: [ ... ],
6743          *         propExt:   [
6744          *           {
6745          *             name:      'data'
6746          *             val:       function () {},
6747          *             methodExt: [ ... ],
6748          *             propExt:   [ ... ]
6749          *           },
6750          *           ...
6751          *         ]
6752          *       }
6753          *     ]
6754          *
6755          * @type {Array}
6756          * @ignore
6757          */
6758         var __apiStruct = [];
6759         
6760         
6761         /**
6762          * `Array.prototype` reference.
6763          *
6764          * @type object
6765          * @ignore
6766          */
6767         var __arrayProto = Array.prototype;
6768         
6769         
6770         /**
6771          * Abstraction for `context` parameter of the `Api` constructor to allow it to
6772          * take several different forms for ease of use.
6773          *
6774          * Each of the input parameter types will be converted to a DataTables settings
6775          * object where possible.
6776          *
6777          * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6778          *   of:
6779          *
6780          *   * `string` - jQuery selector. Any DataTables' matching the given selector
6781          *     with be found and used.
6782          *   * `node` - `TABLE` node which has already been formed into a DataTable.
6783          *   * `jQuery` - A jQuery object of `TABLE` nodes.
6784          *   * `object` - DataTables settings object
6785          *   * `DataTables.Api` - API instance
6786          * @return {array|null} Matching DataTables settings objects. `null` or
6787          *   `undefined` is returned if no matching DataTable is found.
6788          * @ignore
6789          */
6790         var _toSettings = function ( mixed )
6791         {
6792                 var idx, jq;
6793                 var settings = DataTable.settings;
6794                 var tables = $.map( settings, function (el, i) {
6795                         return el.nTable;
6796                 } );
6797         
6798                 if ( ! mixed ) {
6799                         return [];
6800                 }
6801                 else if ( mixed.nTable && mixed.oApi ) {
6802                         // DataTables settings object
6803                         return [ mixed ];
6804                 }
6805                 else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6806                         // Table node
6807                         idx = $.inArray( mixed, tables );
6808                         return idx !== -1 ? [ settings[idx] ] : null;
6809                 }
6810                 else if ( mixed && typeof mixed.settings === 'function' ) {
6811                         return mixed.settings().toArray();
6812                 }
6813                 else if ( typeof mixed === 'string' ) {
6814                         // jQuery selector
6815                         jq = $(mixed);
6816                 }
6817                 else if ( mixed instanceof $ ) {
6818                         // jQuery object (also DataTables instance)
6819                         jq = mixed;
6820                 }
6821         
6822                 if ( jq ) {
6823                         return jq.map( function(i) {
6824                                 idx = $.inArray( this, tables );
6825                                 return idx !== -1 ? settings[idx] : null;
6826                         } ).toArray();
6827                 }
6828         };
6829         
6830         
6831         /**
6832          * DataTables API class - used to control and interface with  one or more
6833          * DataTables enhanced tables.
6834          *
6835          * The API class is heavily based on jQuery, presenting a chainable interface
6836          * that you can use to interact with tables. Each instance of the API class has
6837          * a "context" - i.e. the tables that it will operate on. This could be a single
6838          * table, all tables on a page or a sub-set thereof.
6839          *
6840          * Additionally the API is designed to allow you to easily work with the data in
6841          * the tables, retrieving and manipulating it as required. This is done by
6842          * presenting the API class as an array like interface. The contents of the
6843          * array depend upon the actions requested by each method (for example
6844          * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6845          * return an array of objects or arrays depending upon your table's
6846          * configuration). The API object has a number of array like methods (`push`,
6847          * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6848          * `unique` etc) to assist your working with the data held in a table.
6849          *
6850          * Most methods (those which return an Api instance) are chainable, which means
6851          * the return from a method call also has all of the methods available that the
6852          * top level object had. For example, these two calls are equivalent:
6853          *
6854          *     // Not chained
6855          *     api.row.add( {...} );
6856          *     api.draw();
6857          *
6858          *     // Chained
6859          *     api.row.add( {...} ).draw();
6860          *
6861          * @class DataTable.Api
6862          * @param {array|object|string|jQuery} context DataTable identifier. This is
6863          *   used to define which DataTables enhanced tables this API will operate on.
6864          *   Can be one of:
6865          *
6866          *   * `string` - jQuery selector. Any DataTables' matching the given selector
6867          *     with be found and used.
6868          *   * `node` - `TABLE` node which has already been formed into a DataTable.
6869          *   * `jQuery` - A jQuery object of `TABLE` nodes.
6870          *   * `object` - DataTables settings object
6871          * @param {array} [data] Data to initialise the Api instance with.
6872          *
6873          * @example
6874          *   // Direct initialisation during DataTables construction
6875          *   var api = $('#example').DataTable();
6876          *
6877          * @example
6878          *   // Initialisation using a DataTables jQuery object
6879          *   var api = $('#example').dataTable().api();
6880          *
6881          * @example
6882          *   // Initialisation as a constructor
6883          *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6884          */
6885         _Api = function ( context, data )
6886         {
6887                 if ( ! (this instanceof _Api) ) {
6888                         return new _Api( context, data );
6889                 }
6890         
6891                 var settings = [];
6892                 var ctxSettings = function ( o ) {
6893                         var a = _toSettings( o );
6894                         if ( a ) {
6895                                 settings = settings.concat( a );
6896                         }
6897                 };
6898         
6899                 if ( $.isArray( context ) ) {
6900                         for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6901                                 ctxSettings( context[i] );
6902                         }
6903                 }
6904                 else {
6905                         ctxSettings( context );
6906                 }
6907         
6908                 // Remove duplicates
6909                 this.context = _unique( settings );
6910         
6911                 // Initial data
6912                 if ( data ) {
6913                         $.merge( this, data );
6914                 }
6915         
6916                 // selector
6917                 this.selector = {
6918                         rows: null,
6919                         cols: null,
6920                         opts: null
6921                 };
6922         
6923                 _Api.extend( this, this, __apiStruct );
6924         };
6925         
6926         DataTable.Api = _Api;
6927         
6928         // Don't destroy the existing prototype, just extend it. Required for jQuery 2's
6929         // isPlainObject.
6930         $.extend( _Api.prototype, {
6931                 any: function ()
6932                 {
6933                         return this.count() !== 0;
6934                 },
6935         
6936         
6937                 concat:  __arrayProto.concat,
6938         
6939         
6940                 context: [], // array of table settings objects
6941         
6942         
6943                 count: function ()
6944                 {
6945                         return this.flatten().length;
6946                 },
6947         
6948         
6949                 each: function ( fn )
6950                 {
6951                         for ( var i=0, ien=this.length ; i<ien; i++ ) {
6952                                 fn.call( this, this[i], i, this );
6953                         }
6954         
6955                         return this;
6956                 },
6957         
6958         
6959                 eq: function ( idx )
6960                 {
6961                         var ctx = this.context;
6962         
6963                         return ctx.length > idx ?
6964                                 new _Api( ctx[idx], this[idx] ) :
6965                                 null;
6966                 },
6967         
6968         
6969                 filter: function ( fn )
6970                 {
6971                         var a = [];
6972         
6973                         if ( __arrayProto.filter ) {
6974                                 a = __arrayProto.filter.call( this, fn, this );
6975                         }
6976                         else {
6977                                 // Compatibility for browsers without EMCA-252-5 (JS 1.6)
6978                                 for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6979                                         if ( fn.call( this, this[i], i, this ) ) {
6980                                                 a.push( this[i] );
6981                                         }
6982                                 }
6983                         }
6984         
6985                         return new _Api( this.context, a );
6986                 },
6987         
6988         
6989                 flatten: function ()
6990                 {
6991                         var a = [];
6992                         return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
6993                 },
6994         
6995         
6996                 join:    __arrayProto.join,
6997         
6998         
6999                 indexOf: __arrayProto.indexOf || function (obj, start)
7000                 {
7001                         for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
7002                                 if ( this[i] === obj ) {
7003                                         return i;
7004                                 }
7005                         }
7006                         return -1;
7007                 },
7008         
7009                 iterator: function ( flatten, type, fn, alwaysNew ) {
7010                         var
7011                                 a = [], ret,
7012                                 i, ien, j, jen,
7013                                 context = this.context,
7014                                 rows, items, item,
7015                                 selector = this.selector;
7016         
7017                         // Argument shifting
7018                         if ( typeof flatten === 'string' ) {
7019                                 alwaysNew = fn;
7020                                 fn = type;
7021                                 type = flatten;
7022                                 flatten = false;
7023                         }
7024         
7025                         for ( i=0, ien=context.length ; i<ien ; i++ ) {
7026                                 var apiInst = new _Api( context[i] );
7027         
7028                                 if ( type === 'table' ) {
7029                                         ret = fn.call( apiInst, context[i], i );
7030         
7031                                         if ( ret !== undefined ) {
7032                                                 a.push( ret );
7033                                         }
7034                                 }
7035                                 else if ( type === 'columns' || type === 'rows' ) {
7036                                         // this has same length as context - one entry for each table
7037                                         ret = fn.call( apiInst, context[i], this[i], i );
7038         
7039                                         if ( ret !== undefined ) {
7040                                                 a.push( ret );
7041                                         }
7042                                 }
7043                                 else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
7044                                         // columns and rows share the same structure.
7045                                         // 'this' is an array of column indexes for each context
7046                                         items = this[i];
7047         
7048                                         if ( type === 'column-rows' ) {
7049                                                 rows = _selector_row_indexes( context[i], selector.opts );
7050                                         }
7051         
7052                                         for ( j=0, jen=items.length ; j<jen ; j++ ) {
7053                                                 item = items[j];
7054         
7055                                                 if ( type === 'cell' ) {
7056                                                         ret = fn.call( apiInst, context[i], item.row, item.column, i, j );
7057                                                 }
7058                                                 else {
7059                                                         ret = fn.call( apiInst, context[i], item, i, j, rows );
7060                                                 }
7061         
7062                                                 if ( ret !== undefined ) {
7063                                                         a.push( ret );
7064                                                 }
7065                                         }
7066                                 }
7067                         }
7068         
7069                         if ( a.length || alwaysNew ) {
7070                                 var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
7071                                 var apiSelector = api.selector;
7072                                 apiSelector.rows = selector.rows;
7073                                 apiSelector.cols = selector.cols;
7074                                 apiSelector.opts = selector.opts;
7075                                 return api;
7076                         }
7077                         return this;
7078                 },
7079         
7080         
7081                 lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
7082                 {
7083                         // Bit cheeky...
7084                         return this.indexOf.apply( this.toArray.reverse(), arguments );
7085                 },
7086         
7087         
7088                 length:  0,
7089         
7090         
7091                 map: function ( fn )
7092                 {
7093                         var a = [];
7094         
7095                         if ( __arrayProto.map ) {
7096                                 a = __arrayProto.map.call( this, fn, this );
7097                         }
7098                         else {
7099                                 // Compatibility for browsers without EMCA-252-5 (JS 1.6)
7100                                 for ( var i=0, ien=this.length ; i<ien ; i++ ) {
7101                                         a.push( fn.call( this, this[i], i ) );
7102                                 }
7103                         }
7104         
7105                         return new _Api( this.context, a );
7106                 },
7107         
7108         
7109                 pluck: function ( prop )
7110                 {
7111                         return this.map( function ( el ) {
7112                                 return el[ prop ];
7113                         } );
7114                 },
7115         
7116                 pop:     __arrayProto.pop,
7117         
7118         
7119                 push:    __arrayProto.push,
7120         
7121         
7122                 // Does not return an API instance
7123                 reduce: __arrayProto.reduce || function ( fn, init )
7124                 {
7125                         return _fnReduce( this, fn, init, 0, this.length, 1 );
7126                 },
7127         
7128         
7129                 reduceRight: __arrayProto.reduceRight || function ( fn, init )
7130                 {
7131                         return _fnReduce( this, fn, init, this.length-1, -1, -1 );
7132                 },
7133         
7134         
7135                 reverse: __arrayProto.reverse,
7136         
7137         
7138                 // Object with rows, columns and opts
7139                 selector: null,
7140         
7141         
7142                 shift:   __arrayProto.shift,
7143         
7144         
7145                 slice: function () {
7146                         return new _Api( this.context, this );
7147                 },
7148         
7149         
7150                 sort:    __arrayProto.sort, // ? name - order?
7151         
7152         
7153                 splice:  __arrayProto.splice,
7154         
7155         
7156                 toArray: function ()
7157                 {
7158                         return __arrayProto.slice.call( this );
7159                 },
7160         
7161         
7162                 to$: function ()
7163                 {
7164                         return $( this );
7165                 },
7166         
7167         
7168                 toJQuery: function ()
7169                 {
7170                         return $( this );
7171                 },
7172         
7173         
7174                 unique: function ()
7175                 {
7176                         return new _Api( this.context, _unique(this) );
7177                 },
7178         
7179         
7180                 unshift: __arrayProto.unshift
7181         } );
7182         
7183         
7184         _Api.extend = function ( scope, obj, ext )
7185         {
7186                 // Only extend API instances and static properties of the API
7187                 if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
7188                         return;
7189                 }
7190         
7191                 var
7192                         i, ien,
7193                         j, jen,
7194                         struct, inner,
7195                         methodScoping = function ( scope, fn, struc ) {
7196                                 return function () {
7197                                         var ret = fn.apply( scope, arguments );
7198         
7199                                         // Method extension
7200                                         _Api.extend( ret, ret, struc.methodExt );
7201                                         return ret;
7202                                 };
7203                         };
7204         
7205                 for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7206                         struct = ext[i];
7207         
7208                         // Value
7209                         obj[ struct.name ] = typeof struct.val === 'function' ?
7210                                 methodScoping( scope, struct.val, struct ) :
7211                                 $.isPlainObject( struct.val ) ?
7212                                         {} :
7213                                         struct.val;
7214         
7215                         obj[ struct.name ].__dt_wrapper = true;
7216         
7217                         // Property extension
7218                         _Api.extend( scope, obj[ struct.name ], struct.propExt );
7219                 }
7220         };
7221         
7222         
7223         // @todo - Is there need for an augment function?
7224         // _Api.augment = function ( inst, name )
7225         // {
7226         //      // Find src object in the structure from the name
7227         //      var parts = name.split('.');
7228         
7229         //      _Api.extend( inst, obj );
7230         // };
7231         
7232         
7233         //     [
7234         //       {
7235         //         name:      'data'                -- string   - Property name
7236         //         val:       function () {},       -- function - Api method (or undefined if just an object
7237         //         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
7238         //         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
7239         //       },
7240         //       {
7241         //         name:     'row'
7242         //         val:       {},
7243         //         methodExt: [ ... ],
7244         //         propExt:   [
7245         //           {
7246         //             name:      'data'
7247         //             val:       function () {},
7248         //             methodExt: [ ... ],
7249         //             propExt:   [ ... ]
7250         //           },
7251         //           ...
7252         //         ]
7253         //       }
7254         //     ]
7255         
7256         _Api.register = _api_register = function ( name, val )
7257         {
7258                 if ( $.isArray( name ) ) {
7259                         for ( var j=0, jen=name.length ; j<jen ; j++ ) {
7260                                 _Api.register( name[j], val );
7261                         }
7262                         return;
7263                 }
7264         
7265                 var
7266                         i, ien,
7267                         heir = name.split('.'),
7268                         struct = __apiStruct,
7269                         key, method;
7270         
7271                 var find = function ( src, name ) {
7272                         for ( var i=0, ien=src.length ; i<ien ; i++ ) {
7273                                 if ( src[i].name === name ) {
7274                                         return src[i];
7275                                 }
7276                         }
7277                         return null;
7278                 };
7279         
7280                 for ( i=0, ien=heir.length ; i<ien ; i++ ) {
7281                         method = heir[i].indexOf('()') !== -1;
7282                         key = method ?
7283                                 heir[i].replace('()', '') :
7284                                 heir[i];
7285         
7286                         var src = find( struct, key );
7287                         if ( ! src ) {
7288                                 src = {
7289                                         name:      key,
7290                                         val:       {},
7291                                         methodExt: [],
7292                                         propExt:   []
7293                                 };
7294                                 struct.push( src );
7295                         }
7296         
7297                         if ( i === ien-1 ) {
7298                                 src.val = val;
7299                         }
7300                         else {
7301                                 struct = method ?
7302                                         src.methodExt :
7303                                         src.propExt;
7304                         }
7305                 }
7306         };
7307         
7308         
7309         _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7310                 _Api.register( pluralName, val );
7311         
7312                 _Api.register( singularName, function () {
7313                         var ret = val.apply( this, arguments );
7314         
7315                         if ( ret === this ) {
7316                                 // Returned item is the API instance that was passed in, return it
7317                                 return this;
7318                         }
7319                         else if ( ret instanceof _Api ) {
7320                                 // New API instance returned, want the value from the first item
7321                                 // in the returned array for the singular result.
7322                                 return ret.length ?
7323                                         $.isArray( ret[0] ) ?
7324                                                 new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7325                                                 ret[0] :
7326                                         undefined;
7327                         }
7328         
7329                         // Non-API return - just fire it back
7330                         return ret;
7331                 } );
7332         };
7333         
7334         
7335         /**
7336          * Selector for HTML tables. Apply the given selector to the give array of
7337          * DataTables settings objects.
7338          *
7339          * @param {string|integer} [selector] jQuery selector string or integer
7340          * @param  {array} Array of DataTables settings objects to be filtered
7341          * @return {array}
7342          * @ignore
7343          */
7344         var __table_selector = function ( selector, a )
7345         {
7346                 // Integer is used to pick out a table by index
7347                 if ( typeof selector === 'number' ) {
7348                         return [ a[ selector ] ];
7349                 }
7350         
7351                 // Perform a jQuery selector on the table nodes
7352                 var nodes = $.map( a, function (el, i) {
7353                         return el.nTable;
7354                 } );
7355         
7356                 return $(nodes)
7357                         .filter( selector )
7358                         .map( function (i) {
7359                                 // Need to translate back from the table node to the settings
7360                                 var idx = $.inArray( this, nodes );
7361                                 return a[ idx ];
7362                         } )
7363                         .toArray();
7364         };
7365         
7366         
7367         
7368         /**
7369          * Context selector for the API's context (i.e. the tables the API instance
7370          * refers to.
7371          *
7372          * @name    DataTable.Api#tables
7373          * @param {string|integer} [selector] Selector to pick which tables the iterator
7374          *   should operate on. If not given, all tables in the current context are
7375          *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7376          *   select multiple tables or as an integer to select a single table.
7377          * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7378          */
7379         _api_register( 'tables()', function ( selector ) {
7380                 // A new instance is created if there was a selector specified
7381                 return selector ?
7382                         new _Api( __table_selector( selector, this.context ) ) :
7383                         this;
7384         } );
7385         
7386         
7387         _api_register( 'table()', function ( selector ) {
7388                 var tables = this.tables( selector );
7389                 var ctx = tables.context;
7390         
7391                 // Truncate to the first matched table
7392                 return ctx.length ?
7393                         new _Api( ctx[0] ) :
7394                         tables;
7395         } );
7396         
7397         
7398         _api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7399                 return this.iterator( 'table', function ( ctx ) {
7400                         return ctx.nTable;
7401                 }, 1 );
7402         } );
7403         
7404         
7405         _api_registerPlural( 'tables().body()', 'table().body()' , function () {
7406                 return this.iterator( 'table', function ( ctx ) {
7407                         return ctx.nTBody;
7408                 }, 1 );
7409         } );
7410         
7411         
7412         _api_registerPlural( 'tables().header()', 'table().header()' , function () {
7413                 return this.iterator( 'table', function ( ctx ) {
7414                         return ctx.nTHead;
7415                 }, 1 );
7416         } );
7417         
7418         
7419         _api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7420                 return this.iterator( 'table', function ( ctx ) {
7421                         return ctx.nTFoot;
7422                 }, 1 );
7423         } );
7424         
7425         
7426         _api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7427                 return this.iterator( 'table', function ( ctx ) {
7428                         return ctx.nTableWrapper;
7429                 }, 1 );
7430         } );
7431         
7432         
7433         
7434         /**
7435          * Redraw the tables in the current context.
7436          */
7437         _api_register( 'draw()', function ( paging ) {
7438                 return this.iterator( 'table', function ( settings ) {
7439                         if ( paging === 'page' ) {
7440                                 _fnDraw( settings );
7441                         }
7442                         else {
7443                                 if ( typeof paging === 'string' ) {
7444                                         paging = paging === 'full-hold' ?
7445                                                 false :
7446                                                 true;
7447                                 }
7448         
7449                                 _fnReDraw( settings, paging===false );
7450                         }
7451                 } );
7452         } );
7453         
7454         
7455         
7456         /**
7457          * Get the current page index.
7458          *
7459          * @return {integer} Current page index (zero based)
7460          *//**
7461          * Set the current page.
7462          *
7463          * Note that if you attempt to show a page which does not exist, DataTables will
7464          * not throw an error, but rather reset the paging.
7465          *
7466          * @param {integer|string} action The paging action to take. This can be one of:
7467          *  * `integer` - The page index to jump to
7468          *  * `string` - An action to take:
7469          *    * `first` - Jump to first page.
7470          *    * `next` - Jump to the next page
7471          *    * `previous` - Jump to previous page
7472          *    * `last` - Jump to the last page.
7473          * @returns {DataTables.Api} this
7474          */
7475         _api_register( 'page()', function ( action ) {
7476                 if ( action === undefined ) {
7477                         return this.page.info().page; // not an expensive call
7478                 }
7479         
7480                 // else, have an action to take on all tables
7481                 return this.iterator( 'table', function ( settings ) {
7482                         _fnPageChange( settings, action );
7483                 } );
7484         } );
7485         
7486         
7487         /**
7488          * Paging information for the first table in the current context.
7489          *
7490          * If you require paging information for another table, use the `table()` method
7491          * with a suitable selector.
7492          *
7493          * @return {object} Object with the following properties set:
7494          *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7495          *  * `pages` - Total number of pages
7496          *  * `start` - Display index for the first record shown on the current page
7497          *  * `end` - Display index for the last record shown on the current page
7498          *  * `length` - Display length (number of records). Note that generally `start
7499          *    + length = end`, but this is not always true, for example if there are
7500          *    only 2 records to show on the final page, with a length of 10.
7501          *  * `recordsTotal` - Full data set length
7502          *  * `recordsDisplay` - Data set length once the current filtering criterion
7503          *    are applied.
7504          */
7505         _api_register( 'page.info()', function ( action ) {
7506                 if ( this.context.length === 0 ) {
7507                         return undefined;
7508                 }
7509         
7510                 var
7511                         settings   = this.context[0],
7512                         start      = settings._iDisplayStart,
7513                         len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,
7514                         visRecords = settings.fnRecordsDisplay(),
7515                         all        = len === -1;
7516         
7517                 return {
7518                         "page":           all ? 0 : Math.floor( start / len ),
7519                         "pages":          all ? 1 : Math.ceil( visRecords / len ),
7520                         "start":          start,
7521                         "end":            settings.fnDisplayEnd(),
7522                         "length":         len,
7523                         "recordsTotal":   settings.fnRecordsTotal(),
7524                         "recordsDisplay": visRecords,
7525                         "serverSide":     _fnDataSource( settings ) === 'ssp'
7526                 };
7527         } );
7528         
7529         
7530         /**
7531          * Get the current page length.
7532          *
7533          * @return {integer} Current page length. Note `-1` indicates that all records
7534          *   are to be shown.
7535          *//**
7536          * Set the current page length.
7537          *
7538          * @param {integer} Page length to set. Use `-1` to show all records.
7539          * @returns {DataTables.Api} this
7540          */
7541         _api_register( 'page.len()', function ( len ) {
7542                 // Note that we can't call this function 'length()' because `length`
7543                 // is a Javascript property of functions which defines how many arguments
7544                 // the function expects.
7545                 if ( len === undefined ) {
7546                         return this.context.length !== 0 ?
7547                                 this.context[0]._iDisplayLength :
7548                                 undefined;
7549                 }
7550         
7551                 // else, set the page length
7552                 return this.iterator( 'table', function ( settings ) {
7553                         _fnLengthChange( settings, len );
7554                 } );
7555         } );
7556         
7557         
7558         
7559         var __reload = function ( settings, holdPosition, callback ) {
7560                 // Use the draw event to trigger a callback
7561                 if ( callback ) {
7562                         var api = new _Api( settings );
7563         
7564                         api.one( 'draw', function () {
7565                                 callback( api.ajax.json() );
7566                         } );
7567                 }
7568         
7569                 if ( _fnDataSource( settings ) == 'ssp' ) {
7570                         _fnReDraw( settings, holdPosition );
7571                 }
7572                 else {
7573                         _fnProcessingDisplay( settings, true );
7574         
7575                         // Cancel an existing request
7576                         var xhr = settings.jqXHR;
7577                         if ( xhr && xhr.readyState !== 4 ) {
7578                                 xhr.abort();
7579                         }
7580         
7581                         // Trigger xhr
7582                         _fnBuildAjax( settings, [], function( json ) {
7583                                 _fnClearTable( settings );
7584         
7585                                 var data = _fnAjaxDataSrc( settings, json );
7586                                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7587                                         _fnAddData( settings, data[i] );
7588                                 }
7589         
7590                                 _fnReDraw( settings, holdPosition );
7591                                 _fnProcessingDisplay( settings, false );
7592                         } );
7593                 }
7594         };
7595         
7596         
7597         /**
7598          * Get the JSON response from the last Ajax request that DataTables made to the
7599          * server. Note that this returns the JSON from the first table in the current
7600          * context.
7601          *
7602          * @return {object} JSON received from the server.
7603          */
7604         _api_register( 'ajax.json()', function () {
7605                 var ctx = this.context;
7606         
7607                 if ( ctx.length > 0 ) {
7608                         return ctx[0].json;
7609                 }
7610         
7611                 // else return undefined;
7612         } );
7613         
7614         
7615         /**
7616          * Get the data submitted in the last Ajax request
7617          */
7618         _api_register( 'ajax.params()', function () {
7619                 var ctx = this.context;
7620         
7621                 if ( ctx.length > 0 ) {
7622                         return ctx[0].oAjaxData;
7623                 }
7624         
7625                 // else return undefined;
7626         } );
7627         
7628         
7629         /**
7630          * Reload tables from the Ajax data source. Note that this function will
7631          * automatically re-draw the table when the remote data has been loaded.
7632          *
7633          * @param {boolean} [reset=true] Reset (default) or hold the current paging
7634          *   position. A full re-sort and re-filter is performed when this method is
7635          *   called, which is why the pagination reset is the default action.
7636          * @returns {DataTables.Api} this
7637          */
7638         _api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7639                 return this.iterator( 'table', function (settings) {
7640                         __reload( settings, resetPaging===false, callback );
7641                 } );
7642         } );
7643         
7644         
7645         /**
7646          * Get the current Ajax URL. Note that this returns the URL from the first
7647          * table in the current context.
7648          *
7649          * @return {string} Current Ajax source URL
7650          *//**
7651          * Set the Ajax URL. Note that this will set the URL for all tables in the
7652          * current context.
7653          *
7654          * @param {string} url URL to set.
7655          * @returns {DataTables.Api} this
7656          */
7657         _api_register( 'ajax.url()', function ( url ) {
7658                 var ctx = this.context;
7659         
7660                 if ( url === undefined ) {
7661                         // get
7662                         if ( ctx.length === 0 ) {
7663                                 return undefined;
7664                         }
7665                         ctx = ctx[0];
7666         
7667                         return ctx.ajax ?
7668                                 $.isPlainObject( ctx.ajax ) ?
7669                                         ctx.ajax.url :
7670                                         ctx.ajax :
7671                                 ctx.sAjaxSource;
7672                 }
7673         
7674                 // set
7675                 return this.iterator( 'table', function ( settings ) {
7676                         if ( $.isPlainObject( settings.ajax ) ) {
7677                                 settings.ajax.url = url;
7678                         }
7679                         else {
7680                                 settings.ajax = url;
7681                         }
7682                         // No need to consider sAjaxSource here since DataTables gives priority
7683                         // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7684                         // value of `sAjaxSource` redundant.
7685                 } );
7686         } );
7687         
7688         
7689         /**
7690          * Load data from the newly set Ajax URL. Note that this method is only
7691          * available when `ajax.url()` is used to set a URL. Additionally, this method
7692          * has the same effect as calling `ajax.reload()` but is provided for
7693          * convenience when setting a new URL. Like `ajax.reload()` it will
7694          * automatically redraw the table once the remote data has been loaded.
7695          *
7696          * @returns {DataTables.Api} this
7697          */
7698         _api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7699                 // Same as a reload, but makes sense to present it for easy access after a
7700                 // url change
7701                 return this.iterator( 'table', function ( ctx ) {
7702                         __reload( ctx, resetPaging===false, callback );
7703                 } );
7704         } );
7705         
7706         
7707         
7708         
7709         var _selector_run = function ( type, selector, selectFn, settings, opts )
7710         {
7711                 var
7712                         out = [], res,
7713                         a, i, ien, j, jen,
7714                         selectorType = typeof selector;
7715         
7716                 // Can't just check for isArray here, as an API or jQuery instance might be
7717                 // given with their array like look
7718                 if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {
7719                         selector = [ selector ];
7720                 }
7721         
7722                 for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7723                         // Only split on simple strings - complex expressions will be jQuery selectors
7724                         a = selector[i] && selector[i].split && ! selector[i].match(/[\[\(:]/) ?
7725                                 selector[i].split(',') :
7726                                 [ selector[i] ];
7727         
7728                         for ( j=0, jen=a.length ; j<jen ; j++ ) {
7729                                 res = selectFn( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
7730         
7731                                 if ( res && res.length ) {
7732                                         out = out.concat( res );
7733                                 }
7734                         }
7735                 }
7736         
7737                 // selector extensions
7738                 var ext = _ext.selector[ type ];
7739                 if ( ext.length ) {
7740                         for ( i=0, ien=ext.length ; i<ien ; i++ ) {
7741                                 out = ext[i]( settings, opts, out );
7742                         }
7743                 }
7744         
7745                 return _unique( out );
7746         };
7747         
7748         
7749         var _selector_opts = function ( opts )
7750         {
7751                 if ( ! opts ) {
7752                         opts = {};
7753                 }
7754         
7755                 // Backwards compatibility for 1.9- which used the terminology filter rather
7756                 // than search
7757                 if ( opts.filter && opts.search === undefined ) {
7758                         opts.search = opts.filter;
7759                 }
7760         
7761                 return $.extend( {
7762                         search: 'none',
7763                         order: 'current',
7764                         page: 'all'
7765                 }, opts );
7766         };
7767         
7768         
7769         var _selector_first = function ( inst )
7770         {
7771                 // Reduce the API instance to the first item found
7772                 for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7773                         if ( inst[i].length > 0 ) {
7774                                 // Assign the first element to the first item in the instance
7775                                 // and truncate the instance and context
7776                                 inst[0] = inst[i];
7777                                 inst[0].length = 1;
7778                                 inst.length = 1;
7779                                 inst.context = [ inst.context[i] ];
7780         
7781                                 return inst;
7782                         }
7783                 }
7784         
7785                 // Not found - return an empty instance
7786                 inst.length = 0;
7787                 return inst;
7788         };
7789         
7790         
7791         var _selector_row_indexes = function ( settings, opts )
7792         {
7793                 var
7794                         i, ien, tmp, a=[],
7795                         displayFiltered = settings.aiDisplay,
7796                         displayMaster = settings.aiDisplayMaster;
7797         
7798                 var
7799                         search = opts.search,  // none, applied, removed
7800                         order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7801                         page   = opts.page;    // all, current
7802         
7803                 if ( _fnDataSource( settings ) == 'ssp' ) {
7804                         // In server-side processing mode, most options are irrelevant since
7805                         // rows not shown don't exist and the index order is the applied order
7806                         // Removed is a special case - for consistency just return an empty
7807                         // array
7808                         return search === 'removed' ?
7809                                 [] :
7810                                 _range( 0, displayMaster.length );
7811                 }
7812                 else if ( page == 'current' ) {
7813                         // Current page implies that order=current and fitler=applied, since it is
7814                         // fairly senseless otherwise, regardless of what order and search actually
7815                         // are
7816                         for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7817                                 a.push( displayFiltered[i] );
7818                         }
7819                 }
7820                 else if ( order == 'current' || order == 'applied' ) {
7821                         a = search == 'none' ?
7822                                 displayMaster.slice() :                      // no search
7823                                 search == 'applied' ?
7824                                         displayFiltered.slice() :                // applied search
7825                                         $.map( displayMaster, function (el, i) { // removed search
7826                                                 return $.inArray( el, displayFiltered ) === -1 ? el : null;
7827                                         } );
7828                 }
7829                 else if ( order == 'index' || order == 'original' ) {
7830                         for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7831                                 if ( search == 'none' ) {
7832                                         a.push( i );
7833                                 }
7834                                 else { // applied | removed
7835                                         tmp = $.inArray( i, displayFiltered );
7836         
7837                                         if ((tmp === -1 && search == 'removed') ||
7838                                                 (tmp >= 0   && search == 'applied') )
7839                                         {
7840                                                 a.push( i );
7841                                         }
7842                                 }
7843                         }
7844                 }
7845         
7846                 return a;
7847         };
7848         
7849         
7850         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7851          * Rows
7852          *
7853          * {}          - no selector - use all available rows
7854          * {integer}   - row aoData index
7855          * {node}      - TR node
7856          * {string}    - jQuery selector to apply to the TR elements
7857          * {array}     - jQuery array of nodes, or simply an array of TR nodes
7858          *
7859          */
7860         
7861         
7862         var __row_selector = function ( settings, selector, opts )
7863         {
7864                 var rows;
7865                 var run = function ( sel ) {
7866                         var selInt = _intVal( sel );
7867                         var i, ien;
7868         
7869                         // Short cut - selector is a number and no options provided (default is
7870                         // all records, so no need to check if the index is in there, since it
7871                         // must be - dev error if the index doesn't exist).
7872                         if ( selInt !== null && ! opts ) {
7873                                 return [ selInt ];
7874                         }
7875         
7876                         if ( ! rows ) {
7877                                 rows = _selector_row_indexes( settings, opts );
7878                         }
7879         
7880                         if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7881                                 // Selector - integer
7882                                 return [ selInt ];
7883                         }
7884                         else if ( sel === null || sel === undefined || sel === '' ) {
7885                                 // Selector - none
7886                                 return rows;
7887                         }
7888         
7889                         // Selector - function
7890                         if ( typeof sel === 'function' ) {
7891                                 return $.map( rows, function (idx) {
7892                                         var row = settings.aoData[ idx ];
7893                                         return sel( idx, row._aData, row.nTr ) ? idx : null;
7894                                 } );
7895                         }
7896         
7897                         // Get nodes in the order from the `rows` array with null values removed
7898                         var nodes = _removeEmpty(
7899                                 _pluck_order( settings.aoData, rows, 'nTr' )
7900                         );
7901         
7902                         // Selector - node
7903                         if ( sel.nodeName ) {
7904                                 if ( sel._DT_RowIndex !== undefined ) {
7905                                         return [ sel._DT_RowIndex ]; // Property added by DT for fast lookup
7906                                 }
7907                                 else if ( sel._DT_CellIndex ) {
7908                                         return [ sel._DT_CellIndex.row ];
7909                                 }
7910                                 else {
7911                                         var host = $(sel).closest('*[data-dt-row]');
7912                                         return host.length ?
7913                                                 [ host.data('dt-row') ] :
7914                                                 [];
7915                                 }
7916                         }
7917         
7918                         // ID selector. Want to always be able to select rows by id, regardless
7919                         // of if the tr element has been created or not, so can't rely upon
7920                         // jQuery here - hence a custom implementation. This does not match
7921                         // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,
7922                         // but to select it using a CSS selector engine (like Sizzle or
7923                         // querySelect) it would need to need to be escaped for some characters.
7924                         // DataTables simplifies this for row selectors since you can select
7925                         // only a row. A # indicates an id any anything that follows is the id -
7926                         // unescaped.
7927                         if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {
7928                                 // get row index from id
7929                                 var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];
7930                                 if ( rowObj !== undefined ) {
7931                                         return [ rowObj.idx ];
7932                                 }
7933         
7934                                 // need to fall through to jQuery in case there is DOM id that
7935                                 // matches
7936                         }
7937         
7938                         // Selector - jQuery selector string, array of nodes or jQuery object/
7939                         // As jQuery's .filter() allows jQuery objects to be passed in filter,
7940                         // it also allows arrays, so this will cope with all three options
7941                         return $(nodes)
7942                                 .filter( sel )
7943                                 .map( function () {
7944                                         return this._DT_RowIndex;
7945                                 } )
7946                                 .toArray();
7947                 };
7948         
7949                 return _selector_run( 'row', selector, run, settings, opts );
7950         };
7951         
7952         
7953         _api_register( 'rows()', function ( selector, opts ) {
7954                 // argument shifting
7955                 if ( selector === undefined ) {
7956                         selector = '';
7957                 }
7958                 else if ( $.isPlainObject( selector ) ) {
7959                         opts = selector;
7960                         selector = '';
7961                 }
7962         
7963                 opts = _selector_opts( opts );
7964         
7965                 var inst = this.iterator( 'table', function ( settings ) {
7966                         return __row_selector( settings, selector, opts );
7967                 }, 1 );
7968         
7969                 // Want argument shifting here and in __row_selector?
7970                 inst.selector.rows = selector;
7971                 inst.selector.opts = opts;
7972         
7973                 return inst;
7974         } );
7975         
7976         _api_register( 'rows().nodes()', function () {
7977                 return this.iterator( 'row', function ( settings, row ) {
7978                         return settings.aoData[ row ].nTr || undefined;
7979                 }, 1 );
7980         } );
7981         
7982         _api_register( 'rows().data()', function () {
7983                 return this.iterator( true, 'rows', function ( settings, rows ) {
7984                         return _pluck_order( settings.aoData, rows, '_aData' );
7985                 }, 1 );
7986         } );
7987         
7988         _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
7989                 return this.iterator( 'row', function ( settings, row ) {
7990                         var r = settings.aoData[ row ];
7991                         return type === 'search' ? r._aFilterData : r._aSortData;
7992                 }, 1 );
7993         } );
7994         
7995         _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
7996                 return this.iterator( 'row', function ( settings, row ) {
7997                         _fnInvalidate( settings, row, src );
7998                 } );
7999         } );
8000         
8001         _api_registerPlural( 'rows().indexes()', 'row().index()', function () {
8002                 return this.iterator( 'row', function ( settings, row ) {
8003                         return row;
8004                 }, 1 );
8005         } );
8006         
8007         _api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {
8008                 var a = [];
8009                 var context = this.context;
8010         
8011                 // `iterator` will drop undefined values, but in this case we want them
8012                 for ( var i=0, ien=context.length ; i<ien ; i++ ) {
8013                         for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {
8014                                 var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );
8015                                 a.push( (hash === true ? '#' : '' )+ id );
8016                         }
8017                 }
8018         
8019                 return new _Api( context, a );
8020         } );
8021         
8022         _api_registerPlural( 'rows().remove()', 'row().remove()', function () {
8023                 var that = this;
8024         
8025                 this.iterator( 'row', function ( settings, row, thatIdx ) {
8026                         var data = settings.aoData;
8027                         var rowData = data[ row ];
8028                         var i, ien, j, jen;
8029                         var loopRow, loopCells;
8030         
8031                         data.splice( row, 1 );
8032         
8033                         // Update the cached indexes
8034                         for ( i=0, ien=data.length ; i<ien ; i++ ) {
8035                                 loopRow = data[i];
8036                                 loopCells = loopRow.anCells;
8037         
8038                                 // Rows
8039                                 if ( loopRow.nTr !== null ) {
8040                                         loopRow.nTr._DT_RowIndex = i;
8041                                 }
8042         
8043                                 // Cells
8044                                 if ( loopCells !== null ) {
8045                                         for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {
8046                                                 loopCells[j]._DT_CellIndex.row = i;
8047                                         }
8048                                 }
8049                         }
8050         
8051                         // Delete from the display arrays
8052                         _fnDeleteIndex( settings.aiDisplayMaster, row );
8053                         _fnDeleteIndex( settings.aiDisplay, row );
8054                         _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
8055         
8056                         // Check for an 'overflow' they case for displaying the table
8057                         _fnLengthOverflow( settings );
8058         
8059                         // Remove the row's ID reference if there is one
8060                         var id = settings.rowIdFn( rowData._aData );
8061                         if ( id !== undefined ) {
8062                                 delete settings.aIds[ id ];
8063                         }
8064                 } );
8065         
8066                 this.iterator( 'table', function ( settings ) {
8067                         for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
8068                                 settings.aoData[i].idx = i;
8069                         }
8070                 } );
8071         
8072                 return this;
8073         } );
8074         
8075         
8076         _api_register( 'rows.add()', function ( rows ) {
8077                 var newRows = this.iterator( 'table', function ( settings ) {
8078                                 var row, i, ien;
8079                                 var out = [];
8080         
8081                                 for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8082                                         row = rows[i];
8083         
8084                                         if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8085                                                 out.push( _fnAddTr( settings, row )[0] );
8086                                         }
8087                                         else {
8088                                                 out.push( _fnAddData( settings, row ) );
8089                                         }
8090                                 }
8091         
8092                                 return out;
8093                         }, 1 );
8094         
8095                 // Return an Api.rows() extended instance, so rows().nodes() etc can be used
8096                 var modRows = this.rows( -1 );
8097                 modRows.pop();
8098                 $.merge( modRows, newRows );
8099         
8100                 return modRows;
8101         } );
8102         
8103         
8104         
8105         
8106         
8107         /**
8108          *
8109          */
8110         _api_register( 'row()', function ( selector, opts ) {
8111                 return _selector_first( this.rows( selector, opts ) );
8112         } );
8113         
8114         
8115         _api_register( 'row().data()', function ( data ) {
8116                 var ctx = this.context;
8117         
8118                 if ( data === undefined ) {
8119                         // Get
8120                         return ctx.length && this.length ?
8121                                 ctx[0].aoData[ this[0] ]._aData :
8122                                 undefined;
8123                 }
8124         
8125                 // Set
8126                 ctx[0].aoData[ this[0] ]._aData = data;
8127         
8128                 // Automatically invalidate
8129                 _fnInvalidate( ctx[0], this[0], 'data' );
8130         
8131                 return this;
8132         } );
8133         
8134         
8135         _api_register( 'row().node()', function () {
8136                 var ctx = this.context;
8137         
8138                 return ctx.length && this.length ?
8139                         ctx[0].aoData[ this[0] ].nTr || null :
8140                         null;
8141         } );
8142         
8143         
8144         _api_register( 'row.add()', function ( row ) {
8145                 // Allow a jQuery object to be passed in - only a single row is added from
8146                 // it though - the first element in the set
8147                 if ( row instanceof $ && row.length ) {
8148                         row = row[0];
8149                 }
8150         
8151                 var rows = this.iterator( 'table', function ( settings ) {
8152                         if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
8153                                 return _fnAddTr( settings, row )[0];
8154                         }
8155                         return _fnAddData( settings, row );
8156                 } );
8157         
8158                 // Return an Api.rows() extended instance, with the newly added row selected
8159                 return this.row( rows[0] );
8160         } );
8161         
8162         
8163         
8164         var __details_add = function ( ctx, row, data, klass )
8165         {
8166                 // Convert to array of TR elements
8167                 var rows = [];
8168                 var addRow = function ( r, k ) {
8169                         // Recursion to allow for arrays of jQuery objects
8170                         if ( $.isArray( r ) || r instanceof $ ) {
8171                                 for ( var i=0, ien=r.length ; i<ien ; i++ ) {
8172                                         addRow( r[i], k );
8173                                 }
8174                                 return;
8175                         }
8176         
8177                         // If we get a TR element, then just add it directly - up to the dev
8178                         // to add the correct number of columns etc
8179                         if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
8180                                 rows.push( r );
8181                         }
8182                         else {
8183                                 // Otherwise create a row with a wrapper
8184                                 var created = $('<tr><td/></tr>').addClass( k );
8185                                 $('td', created)
8186                                         .addClass( k )
8187                                         .html( r )
8188                                         [0].colSpan = _fnVisbleColumns( ctx );
8189         
8190                                 rows.push( created[0] );
8191                         }
8192                 };
8193         
8194                 addRow( data, klass );
8195         
8196                 if ( row._details ) {
8197                         row._details.detach();
8198                 }
8199         
8200                 row._details = $(rows);
8201         
8202                 // If the children were already shown, that state should be retained
8203                 if ( row._detailsShow ) {
8204                         row._details.insertAfter( row.nTr );
8205                 }
8206         };
8207         
8208         
8209         var __details_remove = function ( api, idx )
8210         {
8211                 var ctx = api.context;
8212         
8213                 if ( ctx.length ) {
8214                         var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];
8215         
8216                         if ( row && row._details ) {
8217                                 row._details.remove();
8218         
8219                                 row._detailsShow = undefined;
8220                                 row._details = undefined;
8221                         }
8222                 }
8223         };
8224         
8225         
8226         var __details_display = function ( api, show ) {
8227                 var ctx = api.context;
8228         
8229                 if ( ctx.length && api.length ) {
8230                         var row = ctx[0].aoData[ api[0] ];
8231         
8232                         if ( row._details ) {
8233                                 row._detailsShow = show;
8234         
8235                                 if ( show ) {
8236                                         row._details.insertAfter( row.nTr );
8237                                 }
8238                                 else {
8239                                         row._details.detach();
8240                                 }
8241         
8242                                 __details_events( ctx[0] );
8243                         }
8244                 }
8245         };
8246         
8247         
8248         var __details_events = function ( settings )
8249         {
8250                 var api = new _Api( settings );
8251                 var namespace = '.dt.DT_details';
8252                 var drawEvent = 'draw'+namespace;
8253                 var colvisEvent = 'column-visibility'+namespace;
8254                 var destroyEvent = 'destroy'+namespace;
8255                 var data = settings.aoData;
8256         
8257                 api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
8258         
8259                 if ( _pluck( data, '_details' ).length > 0 ) {
8260                         // On each draw, insert the required elements into the document
8261                         api.on( drawEvent, function ( e, ctx ) {
8262                                 if ( settings !== ctx ) {
8263                                         return;
8264                                 }
8265         
8266                                 api.rows( {page:'current'} ).eq(0).each( function (idx) {
8267                                         // Internal data grab
8268                                         var row = data[ idx ];
8269         
8270                                         if ( row._detailsShow ) {
8271                                                 row._details.insertAfter( row.nTr );
8272                                         }
8273                                 } );
8274                         } );
8275         
8276                         // Column visibility change - update the colspan
8277                         api.on( colvisEvent, function ( e, ctx, idx, vis ) {
8278                                 if ( settings !== ctx ) {
8279                                         return;
8280                                 }
8281         
8282                                 // Update the colspan for the details rows (note, only if it already has
8283                                 // a colspan)
8284                                 var row, visible = _fnVisbleColumns( ctx );
8285         
8286                                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8287                                         row = data[i];
8288         
8289                                         if ( row._details ) {
8290                                                 row._details.children('td[colspan]').attr('colspan', visible );
8291                                         }
8292                                 }
8293                         } );
8294         
8295                         // Table destroyed - nuke any child rows
8296                         api.on( destroyEvent, function ( e, ctx ) {
8297                                 if ( settings !== ctx ) {
8298                                         return;
8299                                 }
8300         
8301                                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {
8302                                         if ( data[i]._details ) {
8303                                                 __details_remove( api, i );
8304                                         }
8305                                 }
8306                         } );
8307                 }
8308         };
8309         
8310         // Strings for the method names to help minification
8311         var _emp = '';
8312         var _child_obj = _emp+'row().child';
8313         var _child_mth = _child_obj+'()';
8314         
8315         // data can be:
8316         //  tr
8317         //  string
8318         //  jQuery or array of any of the above
8319         _api_register( _child_mth, function ( data, klass ) {
8320                 var ctx = this.context;
8321         
8322                 if ( data === undefined ) {
8323                         // get
8324                         return ctx.length && this.length ?
8325                                 ctx[0].aoData[ this[0] ]._details :
8326                                 undefined;
8327                 }
8328                 else if ( data === true ) {
8329                         // show
8330                         this.child.show();
8331                 }
8332                 else if ( data === false ) {
8333                         // remove
8334                         __details_remove( this );
8335                 }
8336                 else if ( ctx.length && this.length ) {
8337                         // set
8338                         __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
8339                 }
8340         
8341                 return this;
8342         } );
8343         
8344         
8345         _api_register( [
8346                 _child_obj+'.show()',
8347                 _child_mth+'.show()' // only when `child()` was called with parameters (without
8348         ], function ( show ) {   // it returns an object and this method is not executed)
8349                 __details_display( this, true );
8350                 return this;
8351         } );
8352         
8353         
8354         _api_register( [
8355                 _child_obj+'.hide()',
8356                 _child_mth+'.hide()' // only when `child()` was called with parameters (without
8357         ], function () {         // it returns an object and this method is not executed)
8358                 __details_display( this, false );
8359                 return this;
8360         } );
8361         
8362         
8363         _api_register( [
8364                 _child_obj+'.remove()',
8365                 _child_mth+'.remove()' // only when `child()` was called with parameters (without
8366         ], function () {           // it returns an object and this method is not executed)
8367                 __details_remove( this );
8368                 return this;
8369         } );
8370         
8371         
8372         _api_register( _child_obj+'.isShown()', function () {
8373                 var ctx = this.context;
8374         
8375                 if ( ctx.length && this.length ) {
8376                         // _detailsShown as false or undefined will fall through to return false
8377                         return ctx[0].aoData[ this[0] ]._detailsShow || false;
8378                 }
8379                 return false;
8380         } );
8381         
8382         
8383         
8384         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
8385          * Columns
8386          *
8387          * {integer}           - column index (>=0 count from left, <0 count from right)
8388          * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
8389          * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
8390          * "{string}:name"     - column name
8391          * "{string}"          - jQuery selector on column header nodes
8392          *
8393          */
8394         
8395         // can be an array of these items, comma separated list, or an array of comma
8396         // separated lists
8397         
8398         var __re_column_selector = /^([^:]+):(name|visIdx|visible)$/;
8399         
8400         
8401         // r1 and r2 are redundant - but it means that the parameters match for the
8402         // iterator callback in columns().data()
8403         var __columnData = function ( settings, column, r1, r2, rows ) {
8404                 var a = [];
8405                 for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8406                         a.push( _fnGetCellData( settings, rows[row], column ) );
8407                 }
8408                 return a;
8409         };
8410         
8411         
8412         var __column_selector = function ( settings, selector, opts )
8413         {
8414                 var
8415                         columns = settings.aoColumns,
8416                         names = _pluck( columns, 'sName' ),
8417                         nodes = _pluck( columns, 'nTh' );
8418         
8419                 var run = function ( s ) {
8420                         var selInt = _intVal( s );
8421         
8422                         // Selector - all
8423                         if ( s === '' ) {
8424                                 return _range( columns.length );
8425                         }
8426         
8427                         // Selector - index
8428                         if ( selInt !== null ) {
8429                                 return [ selInt >= 0 ?
8430                                         selInt : // Count from left
8431                                         columns.length + selInt // Count from right (+ because its a negative value)
8432                                 ];
8433                         }
8434         
8435                         // Selector = function
8436                         if ( typeof s === 'function' ) {
8437                                 var rows = _selector_row_indexes( settings, opts );
8438         
8439                                 return $.map( columns, function (col, idx) {
8440                                         return s(
8441                                                         idx,
8442                                                         __columnData( settings, idx, 0, 0, rows ),
8443                                                         nodes[ idx ]
8444                                                 ) ? idx : null;
8445                                 } );
8446                         }
8447         
8448                         // jQuery or string selector
8449                         var match = typeof s === 'string' ?
8450                                 s.match( __re_column_selector ) :
8451                                 '';
8452         
8453                         if ( match ) {
8454                                 switch( match[2] ) {
8455                                         case 'visIdx':
8456                                         case 'visible':
8457                                                 var idx = parseInt( match[1], 10 );
8458                                                 // Visible index given, convert to column index
8459                                                 if ( idx < 0 ) {
8460                                                         // Counting from the right
8461                                                         var visColumns = $.map( columns, function (col,i) {
8462                                                                 return col.bVisible ? i : null;
8463                                                         } );
8464                                                         return [ visColumns[ visColumns.length + idx ] ];
8465                                                 }
8466                                                 // Counting from the left
8467                                                 return [ _fnVisibleToColumnIndex( settings, idx ) ];
8468         
8469                                         case 'name':
8470                                                 // match by name. `names` is column index complete and in order
8471                                                 return $.map( names, function (name, i) {
8472                                                         return name === match[1] ? i : null;
8473                                                 } );
8474         
8475                                         default:
8476                                                 return [];
8477                                 }
8478                         }
8479         
8480                         // Cell in the table body
8481                         if ( s.nodeName && s._DT_CellIndex ) {
8482                                 return [ s._DT_CellIndex.column ];
8483                         }
8484         
8485                         // jQuery selector on the TH elements for the columns
8486                         var jqResult = $( nodes )
8487                                 .filter( s )
8488                                 .map( function () {
8489                                         return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8490                                 } )
8491                                 .toArray();
8492         
8493                         if ( jqResult.length || ! s.nodeName ) {
8494                                 return jqResult;
8495                         }
8496         
8497                         // Otherwise a node which might have a `dt-column` data attribute, or be
8498                         // a child or such an element
8499                         var host = $(s).closest('*[data-dt-column]');
8500                         return host.length ?
8501                                 [ host.data('dt-column') ] :
8502                                 [];
8503                 };
8504         
8505                 return _selector_run( 'column', selector, run, settings, opts );
8506         };
8507         
8508         
8509         var __setColumnVis = function ( settings, column, vis ) {
8510                 var
8511                         cols = settings.aoColumns,
8512                         col  = cols[ column ],
8513                         data = settings.aoData,
8514                         row, cells, i, ien, tr;
8515         
8516                 // Get
8517                 if ( vis === undefined ) {
8518                         return col.bVisible;
8519                 }
8520         
8521                 // Set
8522                 // No change
8523                 if ( col.bVisible === vis ) {
8524                         return;
8525                 }
8526         
8527                 if ( vis ) {
8528                         // Insert column
8529                         // Need to decide if we should use appendChild or insertBefore
8530                         var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8531         
8532                         for ( i=0, ien=data.length ; i<ien ; i++ ) {
8533                                 tr = data[i].nTr;
8534                                 cells = data[i].anCells;
8535         
8536                                 if ( tr ) {
8537                                         // insertBefore can act like appendChild if 2nd arg is null
8538                                         tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8539                                 }
8540                         }
8541                 }
8542                 else {
8543                         // Remove column
8544                         $( _pluck( settings.aoData, 'anCells', column ) ).detach();
8545                 }
8546         
8547                 // Common actions
8548                 col.bVisible = vis;
8549                 _fnDrawHead( settings, settings.aoHeader );
8550                 _fnDrawHead( settings, settings.aoFooter );
8551         
8552                 _fnSaveState( settings );
8553         };
8554         
8555         
8556         _api_register( 'columns()', function ( selector, opts ) {
8557                 // argument shifting
8558                 if ( selector === undefined ) {
8559                         selector = '';
8560                 }
8561                 else if ( $.isPlainObject( selector ) ) {
8562                         opts = selector;
8563                         selector = '';
8564                 }
8565         
8566                 opts = _selector_opts( opts );
8567         
8568                 var inst = this.iterator( 'table', function ( settings ) {
8569                         return __column_selector( settings, selector, opts );
8570                 }, 1 );
8571         
8572                 // Want argument shifting here and in _row_selector?
8573                 inst.selector.cols = selector;
8574                 inst.selector.opts = opts;
8575         
8576                 return inst;
8577         } );
8578         
8579         _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8580                 return this.iterator( 'column', function ( settings, column ) {
8581                         return settings.aoColumns[column].nTh;
8582                 }, 1 );
8583         } );
8584         
8585         _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8586                 return this.iterator( 'column', function ( settings, column ) {
8587                         return settings.aoColumns[column].nTf;
8588                 }, 1 );
8589         } );
8590         
8591         _api_registerPlural( 'columns().data()', 'column().data()', function () {
8592                 return this.iterator( 'column-rows', __columnData, 1 );
8593         } );
8594         
8595         _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {
8596                 return this.iterator( 'column', function ( settings, column ) {
8597                         return settings.aoColumns[column].mData;
8598                 }, 1 );
8599         } );
8600         
8601         _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8602                 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8603                         return _pluck_order( settings.aoData, rows,
8604                                 type === 'search' ? '_aFilterData' : '_aSortData', column
8605                         );
8606                 }, 1 );
8607         } );
8608         
8609         _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8610                 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8611                         return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8612                 }, 1 );
8613         } );
8614         
8615         _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8616                 var ret = this.iterator( 'column', function ( settings, column ) {
8617                         if ( vis === undefined ) {
8618                                 return settings.aoColumns[ column ].bVisible;
8619                         } // else
8620                         __setColumnVis( settings, column, vis );
8621                 } );
8622         
8623                 // Group the column visibility changes
8624                 if ( vis !== undefined ) {
8625                         // Second loop once the first is done for events
8626                         this.iterator( 'column', function ( settings, column ) {
8627                                 _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, calc] );
8628                         } );
8629         
8630                         if ( calc === undefined || calc ) {
8631                                 this.columns.adjust();
8632                         }
8633                 }
8634         
8635                 return ret;
8636         } );
8637         
8638         _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8639                 return this.iterator( 'column', function ( settings, column ) {
8640                         return type === 'visible' ?
8641                                 _fnColumnIndexToVisible( settings, column ) :
8642                                 column;
8643                 }, 1 );
8644         } );
8645         
8646         _api_register( 'columns.adjust()', function () {
8647                 return this.iterator( 'table', function ( settings ) {
8648                         _fnAdjustColumnSizing( settings );
8649                 }, 1 );
8650         } );
8651         
8652         _api_register( 'column.index()', function ( type, idx ) {
8653                 if ( this.context.length !== 0 ) {
8654                         var ctx = this.context[0];
8655         
8656                         if ( type === 'fromVisible' || type === 'toData' ) {
8657                                 return _fnVisibleToColumnIndex( ctx, idx );
8658                         }
8659                         else if ( type === 'fromData' || type === 'toVisible' ) {
8660                                 return _fnColumnIndexToVisible( ctx, idx );
8661                         }
8662                 }
8663         } );
8664         
8665         _api_register( 'column()', function ( selector, opts ) {
8666                 return _selector_first( this.columns( selector, opts ) );
8667         } );
8668         
8669         
8670         
8671         var __cell_selector = function ( settings, selector, opts )
8672         {
8673                 var data = settings.aoData;
8674                 var rows = _selector_row_indexes( settings, opts );
8675                 var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );
8676                 var allCells = $( [].concat.apply([], cells) );
8677                 var row;
8678                 var columns = settings.aoColumns.length;
8679                 var a, i, ien, j, o, host;
8680         
8681                 var run = function ( s ) {
8682                         var fnSelector = typeof s === 'function';
8683         
8684                         if ( s === null || s === undefined || fnSelector ) {
8685                                 // All cells and function selectors
8686                                 a = [];
8687         
8688                                 for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8689                                         row = rows[i];
8690         
8691                                         for ( j=0 ; j<columns ; j++ ) {
8692                                                 o = {
8693                                                         row: row,
8694                                                         column: j
8695                                                 };
8696         
8697                                                 if ( fnSelector ) {
8698                                                         // Selector - function
8699                                                         host = data[ row ];
8700         
8701                                                         if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {
8702                                                                 a.push( o );
8703                                                         }
8704                                                 }
8705                                                 else {
8706                                                         // Selector - all
8707                                                         a.push( o );
8708                                                 }
8709                                         }
8710                                 }
8711         
8712                                 return a;
8713                         }
8714                         
8715                         // Selector - index
8716                         if ( $.isPlainObject( s ) ) {
8717                                 return [s];
8718                         }
8719         
8720                         // Selector - jQuery filtered cells
8721                         var jqResult = allCells
8722                                 .filter( s )
8723                                 .map( function (i, el) {
8724                                         return { // use a new object, in case someone changes the values
8725                                                 row:    el._DT_CellIndex.row,
8726                                                 column: el._DT_CellIndex.column
8727                                         };
8728                                 } )
8729                                 .toArray();
8730         
8731                         if ( jqResult.length || ! s.nodeName ) {
8732                                 return jqResult;
8733                         }
8734         
8735                         // Otherwise the selector is a node, and there is one last option - the
8736                         // element might be a child of an element which has dt-row and dt-column
8737                         // data attributes
8738                         host = $(s).closest('*[data-dt-row]');
8739                         return host.length ?
8740                                 [ {
8741                                         row: host.data('dt-row'),
8742                                         column: host.data('dt-column')
8743                                 } ] :
8744                                 [];
8745                 };
8746         
8747                 return _selector_run( 'cell', selector, run, settings, opts );
8748         };
8749         
8750         
8751         
8752         
8753         _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8754                 // Argument shifting
8755                 if ( $.isPlainObject( rowSelector ) ) {
8756                         // Indexes
8757                         if ( rowSelector.row === undefined ) {
8758                                 // Selector options in first parameter
8759                                 opts = rowSelector;
8760                                 rowSelector = null;
8761                         }
8762                         else {
8763                                 // Cell index objects in first parameter
8764                                 opts = columnSelector;
8765                                 columnSelector = null;
8766                         }
8767                 }
8768                 if ( $.isPlainObject( columnSelector ) ) {
8769                         opts = columnSelector;
8770                         columnSelector = null;
8771                 }
8772         
8773                 // Cell selector
8774                 if ( columnSelector === null || columnSelector === undefined ) {
8775                         return this.iterator( 'table', function ( settings ) {
8776                                 return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8777                         } );
8778                 }
8779         
8780                 // Row + column selector
8781                 var columns = this.columns( columnSelector, opts );
8782                 var rows = this.rows( rowSelector, opts );
8783                 var a, i, ien, j, jen;
8784         
8785                 var cells = this.iterator( 'table', function ( settings, idx ) {
8786                         a = [];
8787         
8788                         for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
8789                                 for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
8790                                         a.push( {
8791                                                 row:    rows[idx][i],
8792                                                 column: columns[idx][j]
8793                                         } );
8794                                 }
8795                         }
8796         
8797                         return a;
8798                 }, 1 );
8799         
8800                 $.extend( cells.selector, {
8801                         cols: columnSelector,
8802                         rows: rowSelector,
8803                         opts: opts
8804                 } );
8805         
8806                 return cells;
8807         } );
8808         
8809         
8810         _api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8811                 return this.iterator( 'cell', function ( settings, row, column ) {
8812                         var data = settings.aoData[ row ];
8813         
8814                         return data && data.anCells ?
8815                                 data.anCells[ column ] :
8816                                 undefined;
8817                 }, 1 );
8818         } );
8819         
8820         
8821         _api_register( 'cells().data()', function () {
8822                 return this.iterator( 'cell', function ( settings, row, column ) {
8823                         return _fnGetCellData( settings, row, column );
8824                 }, 1 );
8825         } );
8826         
8827         
8828         _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8829                 type = type === 'search' ? '_aFilterData' : '_aSortData';
8830         
8831                 return this.iterator( 'cell', function ( settings, row, column ) {
8832                         return settings.aoData[ row ][ type ][ column ];
8833                 }, 1 );
8834         } );
8835         
8836         
8837         _api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {
8838                 return this.iterator( 'cell', function ( settings, row, column ) {
8839                         return _fnGetCellData( settings, row, column, type );
8840                 }, 1 );
8841         } );
8842         
8843         
8844         _api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8845                 return this.iterator( 'cell', function ( settings, row, column ) {
8846                         return {
8847                                 row: row,
8848                                 column: column,
8849                                 columnVisible: _fnColumnIndexToVisible( settings, column )
8850                         };
8851                 }, 1 );
8852         } );
8853         
8854         
8855         _api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {
8856                 return this.iterator( 'cell', function ( settings, row, column ) {
8857                         _fnInvalidate( settings, row, src, column );
8858                 } );
8859         } );
8860         
8861         
8862         
8863         _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8864                 return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8865         } );
8866         
8867         
8868         _api_register( 'cell().data()', function ( data ) {
8869                 var ctx = this.context;
8870                 var cell = this[0];
8871         
8872                 if ( data === undefined ) {
8873                         // Get
8874                         return ctx.length && cell.length ?
8875                                 _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8876                                 undefined;
8877                 }
8878         
8879                 // Set
8880                 _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8881                 _fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );
8882         
8883                 return this;
8884         } );
8885         
8886         
8887         
8888         /**
8889          * Get current ordering (sorting) that has been applied to the table.
8890          *
8891          * @returns {array} 2D array containing the sorting information for the first
8892          *   table in the current context. Each element in the parent array represents
8893          *   a column being sorted upon (i.e. multi-sorting with two columns would have
8894          *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8895          *   the column index that the sorting condition applies to, the second is the
8896          *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8897          *   index of the sorting order from the `column.sorting` initialisation array.
8898          *//**
8899          * Set the ordering for the table.
8900          *
8901          * @param {integer} order Column index to sort upon.
8902          * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8903          * @returns {DataTables.Api} this
8904          *//**
8905          * Set the ordering for the table.
8906          *
8907          * @param {array} order 1D array of sorting information to be applied.
8908          * @param {array} [...] Optional additional sorting conditions
8909          * @returns {DataTables.Api} this
8910          *//**
8911          * Set the ordering for the table.
8912          *
8913          * @param {array} order 2D array of sorting information to be applied.
8914          * @returns {DataTables.Api} this
8915          */
8916         _api_register( 'order()', function ( order, dir ) {
8917                 var ctx = this.context;
8918         
8919                 if ( order === undefined ) {
8920                         // get
8921                         return ctx.length !== 0 ?
8922                                 ctx[0].aaSorting :
8923                                 undefined;
8924                 }
8925         
8926                 // set
8927                 if ( typeof order === 'number' ) {
8928                         // Simple column / direction passed in
8929                         order = [ [ order, dir ] ];
8930                 }
8931                 else if ( order.length && ! $.isArray( order[0] ) ) {
8932                         // Arguments passed in (list of 1D arrays)
8933                         order = Array.prototype.slice.call( arguments );
8934                 }
8935                 // otherwise a 2D array was passed in
8936         
8937                 return this.iterator( 'table', function ( settings ) {
8938                         settings.aaSorting = order.slice();
8939                 } );
8940         } );
8941         
8942         
8943         /**
8944          * Attach a sort listener to an element for a given column
8945          *
8946          * @param {node|jQuery|string} node Identifier for the element(s) to attach the
8947          *   listener to. This can take the form of a single DOM node, a jQuery
8948          *   collection of nodes or a jQuery selector which will identify the node(s).
8949          * @param {integer} column the column that a click on this node will sort on
8950          * @param {function} [callback] callback function when sort is run
8951          * @returns {DataTables.Api} this
8952          */
8953         _api_register( 'order.listener()', function ( node, column, callback ) {
8954                 return this.iterator( 'table', function ( settings ) {
8955                         _fnSortAttachListener( settings, node, column, callback );
8956                 } );
8957         } );
8958         
8959         
8960         _api_register( 'order.fixed()', function ( set ) {
8961                 if ( ! set ) {
8962                         var ctx = this.context;
8963                         var fixed = ctx.length ?
8964                                 ctx[0].aaSortingFixed :
8965                                 undefined;
8966         
8967                         return $.isArray( fixed ) ?
8968                                 { pre: fixed } :
8969                                 fixed;
8970                 }
8971         
8972                 return this.iterator( 'table', function ( settings ) {
8973                         settings.aaSortingFixed = $.extend( true, {}, set );
8974                 } );
8975         } );
8976         
8977         
8978         // Order by the selected column(s)
8979         _api_register( [
8980                 'columns().order()',
8981                 'column().order()'
8982         ], function ( dir ) {
8983                 var that = this;
8984         
8985                 return this.iterator( 'table', function ( settings, i ) {
8986                         var sort = [];
8987         
8988                         $.each( that[i], function (j, col) {
8989                                 sort.push( [ col, dir ] );
8990                         } );
8991         
8992                         settings.aaSorting = sort;
8993                 } );
8994         } );
8995         
8996         
8997         
8998         _api_register( 'search()', function ( input, regex, smart, caseInsen ) {
8999                 var ctx = this.context;
9000         
9001                 if ( input === undefined ) {
9002                         // get
9003                         return ctx.length !== 0 ?
9004                                 ctx[0].oPreviousSearch.sSearch :
9005                                 undefined;
9006                 }
9007         
9008                 // set
9009                 return this.iterator( 'table', function ( settings ) {
9010                         if ( ! settings.oFeatures.bFilter ) {
9011                                 return;
9012                         }
9013         
9014                         _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
9015                                 "sSearch": input+"",
9016                                 "bRegex":  regex === null ? false : regex,
9017                                 "bSmart":  smart === null ? true  : smart,
9018                                 "bCaseInsensitive": caseInsen === null ? true : caseInsen
9019                         } ), 1 );
9020                 } );
9021         } );
9022         
9023         
9024         _api_registerPlural(
9025                 'columns().search()',
9026                 'column().search()',
9027                 function ( input, regex, smart, caseInsen ) {
9028                         return this.iterator( 'column', function ( settings, column ) {
9029                                 var preSearch = settings.aoPreSearchCols;
9030         
9031                                 if ( input === undefined ) {
9032                                         // get
9033                                         return preSearch[ column ].sSearch;
9034                                 }
9035         
9036                                 // set
9037                                 if ( ! settings.oFeatures.bFilter ) {
9038                                         return;
9039                                 }
9040         
9041                                 $.extend( preSearch[ column ], {
9042                                         "sSearch": input+"",
9043                                         "bRegex":  regex === null ? false : regex,
9044                                         "bSmart":  smart === null ? true  : smart,
9045                                         "bCaseInsensitive": caseInsen === null ? true : caseInsen
9046                                 } );
9047         
9048                                 _fnFilterComplete( settings, settings.oPreviousSearch, 1 );
9049                         } );
9050                 }
9051         );
9052         
9053         /*
9054          * State API methods
9055          */
9056         
9057         _api_register( 'state()', function () {
9058                 return this.context.length ?
9059                         this.context[0].oSavedState :
9060                         null;
9061         } );
9062         
9063         
9064         _api_register( 'state.clear()', function () {
9065                 return this.iterator( 'table', function ( settings ) {
9066                         // Save an empty object
9067                         settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
9068                 } );
9069         } );
9070         
9071         
9072         _api_register( 'state.loaded()', function () {
9073                 return this.context.length ?
9074                         this.context[0].oLoadedState :
9075                         null;
9076         } );
9077         
9078         
9079         _api_register( 'state.save()', function () {
9080                 return this.iterator( 'table', function ( settings ) {
9081                         _fnSaveState( settings );
9082                 } );
9083         } );
9084         
9085         
9086         
9087         /**
9088          * Provide a common method for plug-ins to check the version of DataTables being
9089          * used, in order to ensure compatibility.
9090          *
9091          *  @param {string} version Version string to check for, in the format "X.Y.Z".
9092          *    Note that the formats "X" and "X.Y" are also acceptable.
9093          *  @returns {boolean} true if this version of DataTables is greater or equal to
9094          *    the required version, or false if this version of DataTales is not
9095          *    suitable
9096          *  @static
9097          *  @dtopt API-Static
9098          *
9099          *  @example
9100          *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
9101          */
9102         DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
9103         {
9104                 var aThis = DataTable.version.split('.');
9105                 var aThat = version.split('.');
9106                 var iThis, iThat;
9107         
9108                 for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
9109                         iThis = parseInt( aThis[i], 10 ) || 0;
9110                         iThat = parseInt( aThat[i], 10 ) || 0;
9111         
9112                         // Parts are the same, keep comparing
9113                         if (iThis === iThat) {
9114                                 continue;
9115                         }
9116         
9117                         // Parts are different, return immediately
9118                         return iThis > iThat;
9119                 }
9120         
9121                 return true;
9122         };
9123         
9124         
9125         /**
9126          * Check if a `<table>` node is a DataTable table already or not.
9127          *
9128          *  @param {node|jquery|string} table Table node, jQuery object or jQuery
9129          *      selector for the table to test. Note that if more than more than one
9130          *      table is passed on, only the first will be checked
9131          *  @returns {boolean} true the table given is a DataTable, or false otherwise
9132          *  @static
9133          *  @dtopt API-Static
9134          *
9135          *  @example
9136          *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
9137          *      $('#example').dataTable();
9138          *    }
9139          */
9140         DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
9141         {
9142                 var t = $(table).get(0);
9143                 var is = false;
9144         
9145                 if ( table instanceof DataTable.Api ) {
9146                         return true;
9147                 }
9148         
9149                 $.each( DataTable.settings, function (i, o) {
9150                         var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;
9151                         var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;
9152         
9153                         if ( o.nTable === t || head === t || foot === t ) {
9154                                 is = true;
9155                         }
9156                 } );
9157         
9158                 return is;
9159         };
9160         
9161         
9162         /**
9163          * Get all DataTable tables that have been initialised - optionally you can
9164          * select to get only currently visible tables.
9165          *
9166          *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
9167          *    or visible tables only.
9168          *  @returns {array} Array of `table` nodes (not DataTable instances) which are
9169          *    DataTables
9170          *  @static
9171          *  @dtopt API-Static
9172          *
9173          *  @example
9174          *    $.each( $.fn.dataTable.tables(true), function () {
9175          *      $(table).DataTable().columns.adjust();
9176          *    } );
9177          */
9178         DataTable.tables = DataTable.fnTables = function ( visible )
9179         {
9180                 var api = false;
9181         
9182                 if ( $.isPlainObject( visible ) ) {
9183                         api = visible.api;
9184                         visible = visible.visible;
9185                 }
9186         
9187                 var a = $.map( DataTable.settings, function (o) {
9188                         if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
9189                                 return o.nTable;
9190                         }
9191                 } );
9192         
9193                 return api ?
9194                         new _Api( a ) :
9195                         a;
9196         };
9197         
9198         
9199         /**
9200          * Convert from camel case parameters to Hungarian notation. This is made public
9201          * for the extensions to provide the same ability as DataTables core to accept
9202          * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
9203          * parameters.
9204          *
9205          *  @param {object} src The model object which holds all parameters that can be
9206          *    mapped.
9207          *  @param {object} user The object to convert from camel case to Hungarian.
9208          *  @param {boolean} force When set to `true`, properties which already have a
9209          *    Hungarian value in the `user` object will be overwritten. Otherwise they
9210          *    won't be.
9211          */
9212         DataTable.camelToHungarian = _fnCamelToHungarian;
9213         
9214         
9215         
9216         /**
9217          *
9218          */
9219         _api_register( '$()', function ( selector, opts ) {
9220                 var
9221                         rows   = this.rows( opts ).nodes(), // Get all rows
9222                         jqRows = $(rows);
9223         
9224                 return $( [].concat(
9225                         jqRows.filter( selector ).toArray(),
9226                         jqRows.find( selector ).toArray()
9227                 ) );
9228         } );
9229         
9230         
9231         // jQuery functions to operate on the tables
9232         $.each( [ 'on', 'one', 'off' ], function (i, key) {
9233                 _api_register( key+'()', function ( /* event, handler */ ) {
9234                         var args = Array.prototype.slice.call(arguments);
9235         
9236                         // Add the `dt` namespace automatically if it isn't already present
9237                         args[0] = $.map( args[0].split( /\s/ ), function ( e ) {
9238                                 return ! e.match(/\.dt\b/) ?
9239                                         e+'.dt' :
9240                                         e;
9241                                 } ).join( ' ' );
9242         
9243                         var inst = $( this.tables().nodes() );
9244                         inst[key].apply( inst, args );
9245                         return this;
9246                 } );
9247         } );
9248         
9249         
9250         _api_register( 'clear()', function () {
9251                 return this.iterator( 'table', function ( settings ) {
9252                         _fnClearTable( settings );
9253                 } );
9254         } );
9255         
9256         
9257         _api_register( 'settings()', function () {
9258                 return new _Api( this.context, this.context );
9259         } );
9260         
9261         
9262         _api_register( 'init()', function () {
9263                 var ctx = this.context;
9264                 return ctx.length ? ctx[0].oInit : null;
9265         } );
9266         
9267         
9268         _api_register( 'data()', function () {
9269                 return this.iterator( 'table', function ( settings ) {
9270                         return _pluck( settings.aoData, '_aData' );
9271                 } ).flatten();
9272         } );
9273         
9274         
9275         _api_register( 'destroy()', function ( remove ) {
9276                 remove = remove || false;
9277         
9278                 return this.iterator( 'table', function ( settings ) {
9279                         var orig      = settings.nTableWrapper.parentNode;
9280                         var classes   = settings.oClasses;
9281                         var table     = settings.nTable;
9282                         var tbody     = settings.nTBody;
9283                         var thead     = settings.nTHead;
9284                         var tfoot     = settings.nTFoot;
9285                         var jqTable   = $(table);
9286                         var jqTbody   = $(tbody);
9287                         var jqWrapper = $(settings.nTableWrapper);
9288                         var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
9289                         var i, ien;
9290         
9291                         // Flag to note that the table is currently being destroyed - no action
9292                         // should be taken
9293                         settings.bDestroying = true;
9294         
9295                         // Fire off the destroy callbacks for plug-ins etc
9296                         _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
9297         
9298                         // If not being removed from the document, make all columns visible
9299                         if ( ! remove ) {
9300                                 new _Api( settings ).columns().visible( true );
9301                         }
9302         
9303                         // Blitz all `DT` namespaced events (these are internal events, the
9304                         // lowercase, `dt` events are user subscribed and they are responsible
9305                         // for removing them
9306                         jqWrapper.off('.DT').find(':not(tbody *)').off('.DT');
9307                         $(window).off('.DT-'+settings.sInstance);
9308         
9309                         // When scrolling we had to break the table up - restore it
9310                         if ( table != thead.parentNode ) {
9311                                 jqTable.children('thead').detach();
9312                                 jqTable.append( thead );
9313                         }
9314         
9315                         if ( tfoot && table != tfoot.parentNode ) {
9316                                 jqTable.children('tfoot').detach();
9317                                 jqTable.append( tfoot );
9318                         }
9319         
9320                         settings.aaSorting = [];
9321                         settings.aaSortingFixed = [];
9322                         _fnSortingClasses( settings );
9323         
9324                         $( rows ).removeClass( settings.asStripeClasses.join(' ') );
9325         
9326                         $('th, td', thead).removeClass( classes.sSortable+' '+
9327                                 classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
9328                         );
9329         
9330                         if ( settings.bJUI ) {
9331                                 $('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach();
9332                                 $('th, td', thead).each( function () {
9333                                         var wrapper = $('div.'+classes.sSortJUIWrapper, this);
9334                                         $(this).append( wrapper.contents() );
9335                                         wrapper.detach();
9336                                 } );
9337                         }
9338         
9339                         // Add the TR elements back into the table in their original order
9340                         jqTbody.children().detach();
9341                         jqTbody.append( rows );
9342         
9343                         // Remove the DataTables generated nodes, events and classes
9344                         var removedMethod = remove ? 'remove' : 'detach';
9345                         jqTable[ removedMethod ]();
9346                         jqWrapper[ removedMethod ]();
9347         
9348                         // If we need to reattach the table to the document
9349                         if ( ! remove && orig ) {
9350                                 // insertBefore acts like appendChild if !arg[1]
9351                                 orig.insertBefore( table, settings.nTableReinsertBefore );
9352         
9353                                 // Restore the width of the original table - was read from the style property,
9354                                 // so we can restore directly to that
9355                                 jqTable
9356                                         .css( 'width', settings.sDestroyWidth )
9357                                         .removeClass( classes.sTable );
9358         
9359                                 // If the were originally stripe classes - then we add them back here.
9360                                 // Note this is not fool proof (for example if not all rows had stripe
9361                                 // classes - but it's a good effort without getting carried away
9362                                 ien = settings.asDestroyStripes.length;
9363         
9364                                 if ( ien ) {
9365                                         jqTbody.children().each( function (i) {
9366                                                 $(this).addClass( settings.asDestroyStripes[i % ien] );
9367                                         } );
9368                                 }
9369                         }
9370         
9371                         /* Remove the settings object from the settings array */
9372                         var idx = $.inArray( settings, DataTable.settings );
9373                         if ( idx !== -1 ) {
9374                                 DataTable.settings.splice( idx, 1 );
9375                         }
9376                 } );
9377         } );
9378         
9379         
9380         // Add the `every()` method for rows, columns and cells in a compact form
9381         $.each( [ 'column', 'row', 'cell' ], function ( i, type ) {
9382                 _api_register( type+'s().every()', function ( fn ) {
9383                         var opts = this.selector.opts;
9384                         var api = this;
9385         
9386                         return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {
9387                                 // Rows and columns:
9388                                 //  arg1 - index
9389                                 //  arg2 - table counter
9390                                 //  arg3 - loop counter
9391                                 //  arg4 - undefined
9392                                 // Cells:
9393                                 //  arg1 - row index
9394                                 //  arg2 - column index
9395                                 //  arg3 - table counter
9396                                 //  arg4 - loop counter
9397                                 fn.call(
9398                                         api[ type ](
9399                                                 arg1,
9400                                                 type==='cell' ? arg2 : opts,
9401                                                 type==='cell' ? opts : undefined
9402                                         ),
9403                                         arg1, arg2, arg3, arg4
9404                                 );
9405                         } );
9406                 } );
9407         } );
9408         
9409         
9410         // i18n method for extensions to be able to use the language object from the
9411         // DataTable
9412         _api_register( 'i18n()', function ( token, def, plural ) {
9413                 var ctx = this.context[0];
9414                 var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );
9415         
9416                 if ( resolved === undefined ) {
9417                         resolved = def;
9418                 }
9419         
9420                 if ( plural !== undefined && $.isPlainObject( resolved ) ) {
9421                         resolved = resolved[ plural ] !== undefined ?
9422                                 resolved[ plural ] :
9423                                 resolved._;
9424                 }
9425         
9426                 return resolved.replace( '%d', plural ); // nb: plural might be undefined,
9427         } );
9428
9429         /**
9430          * Version string for plug-ins to check compatibility. Allowed format is
9431          * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
9432          * only for non-release builds. See http://semver.org/ for more information.
9433          *  @member
9434          *  @type string
9435          *  @default Version number
9436          */
9437         DataTable.version = "1.10.15";
9438
9439         /**
9440          * Private data store, containing all of the settings objects that are
9441          * created for the tables on a given page.
9442          *
9443          * Note that the `DataTable.settings` object is aliased to
9444          * `jQuery.fn.dataTableExt` through which it may be accessed and
9445          * manipulated, or `jQuery.fn.dataTable.settings`.
9446          *  @member
9447          *  @type array
9448          *  @default []
9449          *  @private
9450          */
9451         DataTable.settings = [];
9452
9453         /**
9454          * Object models container, for the various models that DataTables has
9455          * available to it. These models define the objects that are used to hold
9456          * the active state and configuration of the table.
9457          *  @namespace
9458          */
9459         DataTable.models = {};
9460         
9461         
9462         
9463         /**
9464          * Template object for the way in which DataTables holds information about
9465          * search information for the global filter and individual column filters.
9466          *  @namespace
9467          */
9468         DataTable.models.oSearch = {
9469                 /**
9470                  * Flag to indicate if the filtering should be case insensitive or not
9471                  *  @type boolean
9472                  *  @default true
9473                  */
9474                 "bCaseInsensitive": true,
9475         
9476                 /**
9477                  * Applied search term
9478                  *  @type string
9479                  *  @default <i>Empty string</i>
9480                  */
9481                 "sSearch": "",
9482         
9483                 /**
9484                  * Flag to indicate if the search term should be interpreted as a
9485                  * regular expression (true) or not (false) and therefore and special
9486                  * regex characters escaped.
9487                  *  @type boolean
9488                  *  @default false
9489                  */
9490                 "bRegex": false,
9491         
9492                 /**
9493                  * Flag to indicate if DataTables is to use its smart filtering or not.
9494                  *  @type boolean
9495                  *  @default true
9496                  */
9497                 "bSmart": true
9498         };
9499         
9500         
9501         
9502         
9503         /**
9504          * Template object for the way in which DataTables holds information about
9505          * each individual row. This is the object format used for the settings
9506          * aoData array.
9507          *  @namespace
9508          */
9509         DataTable.models.oRow = {
9510                 /**
9511                  * TR element for the row
9512                  *  @type node
9513                  *  @default null
9514                  */
9515                 "nTr": null,
9516         
9517                 /**
9518                  * Array of TD elements for each row. This is null until the row has been
9519                  * created.
9520                  *  @type array nodes
9521                  *  @default []
9522                  */
9523                 "anCells": null,
9524         
9525                 /**
9526                  * Data object from the original data source for the row. This is either
9527                  * an array if using the traditional form of DataTables, or an object if
9528                  * using mData options. The exact type will depend on the passed in
9529                  * data from the data source, or will be an array if using DOM a data
9530                  * source.
9531                  *  @type array|object
9532                  *  @default []
9533                  */
9534                 "_aData": [],
9535         
9536                 /**
9537                  * Sorting data cache - this array is ostensibly the same length as the
9538                  * number of columns (although each index is generated only as it is
9539                  * needed), and holds the data that is used for sorting each column in the
9540                  * row. We do this cache generation at the start of the sort in order that
9541                  * the formatting of the sort data need be done only once for each cell
9542                  * per sort. This array should not be read from or written to by anything
9543                  * other than the master sorting methods.
9544                  *  @type array
9545                  *  @default null
9546                  *  @private
9547                  */
9548                 "_aSortData": null,
9549         
9550                 /**
9551                  * Per cell filtering data cache. As per the sort data cache, used to
9552                  * increase the performance of the filtering in DataTables
9553                  *  @type array
9554                  *  @default null
9555                  *  @private
9556                  */
9557                 "_aFilterData": null,
9558         
9559                 /**
9560                  * Filtering data cache. This is the same as the cell filtering cache, but
9561                  * in this case a string rather than an array. This is easily computed with
9562                  * a join on `_aFilterData`, but is provided as a cache so the join isn't
9563                  * needed on every search (memory traded for performance)
9564                  *  @type array
9565                  *  @default null
9566                  *  @private
9567                  */
9568                 "_sFilterRow": null,
9569         
9570                 /**
9571                  * Cache of the class name that DataTables has applied to the row, so we
9572                  * can quickly look at this variable rather than needing to do a DOM check
9573                  * on className for the nTr property.
9574                  *  @type string
9575                  *  @default <i>Empty string</i>
9576                  *  @private
9577                  */
9578                 "_sRowStripe": "",
9579         
9580                 /**
9581                  * Denote if the original data source was from the DOM, or the data source
9582                  * object. This is used for invalidating data, so DataTables can
9583                  * automatically read data from the original source, unless uninstructed
9584                  * otherwise.
9585                  *  @type string
9586                  *  @default null
9587                  *  @private
9588                  */
9589                 "src": null,
9590         
9591                 /**
9592                  * Index in the aoData array. This saves an indexOf lookup when we have the
9593                  * object, but want to know the index
9594                  *  @type integer
9595                  *  @default -1
9596                  *  @private
9597                  */
9598                 "idx": -1
9599         };
9600         
9601         
9602         /**
9603          * Template object for the column information object in DataTables. This object
9604          * is held in the settings aoColumns array and contains all the information that
9605          * DataTables needs about each individual column.
9606          *
9607          * Note that this object is related to {@link DataTable.defaults.column}
9608          * but this one is the internal data store for DataTables's cache of columns.
9609          * It should NOT be manipulated outside of DataTables. Any configuration should
9610          * be done through the initialisation options.
9611          *  @namespace
9612          */
9613         DataTable.models.oColumn = {
9614                 /**
9615                  * Column index. This could be worked out on-the-fly with $.inArray, but it
9616                  * is faster to just hold it as a variable
9617                  *  @type integer
9618                  *  @default null
9619                  */
9620                 "idx": null,
9621         
9622                 /**
9623                  * A list of the columns that sorting should occur on when this column
9624                  * is sorted. That this property is an array allows multi-column sorting
9625                  * to be defined for a column (for example first name / last name columns
9626                  * would benefit from this). The values are integers pointing to the
9627                  * columns to be sorted on (typically it will be a single integer pointing
9628                  * at itself, but that doesn't need to be the case).
9629                  *  @type array
9630                  */
9631                 "aDataSort": null,
9632         
9633                 /**
9634                  * Define the sorting directions that are applied to the column, in sequence
9635                  * as the column is repeatedly sorted upon - i.e. the first value is used
9636                  * as the sorting direction when the column if first sorted (clicked on).
9637                  * Sort it again (click again) and it will move on to the next index.
9638                  * Repeat until loop.
9639                  *  @type array
9640                  */
9641                 "asSorting": null,
9642         
9643                 /**
9644                  * Flag to indicate if the column is searchable, and thus should be included
9645                  * in the filtering or not.
9646                  *  @type boolean
9647                  */
9648                 "bSearchable": null,
9649         
9650                 /**
9651                  * Flag to indicate if the column is sortable or not.
9652                  *  @type boolean
9653                  */
9654                 "bSortable": null,
9655         
9656                 /**
9657                  * Flag to indicate if the column is currently visible in the table or not
9658                  *  @type boolean
9659                  */
9660                 "bVisible": null,
9661         
9662                 /**
9663                  * Store for manual type assignment using the `column.type` option. This
9664                  * is held in store so we can manipulate the column's `sType` property.
9665                  *  @type string
9666                  *  @default null
9667                  *  @private
9668                  */
9669                 "_sManualType": null,
9670         
9671                 /**
9672                  * Flag to indicate if HTML5 data attributes should be used as the data
9673                  * source for filtering or sorting. True is either are.
9674                  *  @type boolean
9675                  *  @default false
9676                  *  @private
9677                  */
9678                 "_bAttrSrc": false,
9679         
9680                 /**
9681                  * Developer definable function that is called whenever a cell is created (Ajax source,
9682                  * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9683                  * allowing you to modify the DOM element (add background colour for example) when the
9684                  * element is available.
9685                  *  @type function
9686                  *  @param {element} nTd The TD node that has been created
9687                  *  @param {*} sData The Data for the cell
9688                  *  @param {array|object} oData The data for the whole row
9689                  *  @param {int} iRow The row index for the aoData data store
9690                  *  @default null
9691                  */
9692                 "fnCreatedCell": null,
9693         
9694                 /**
9695                  * Function to get data from a cell in a column. You should <b>never</b>
9696                  * access data directly through _aData internally in DataTables - always use
9697                  * the method attached to this property. It allows mData to function as
9698                  * required. This function is automatically assigned by the column
9699                  * initialisation method
9700                  *  @type function
9701                  *  @param {array|object} oData The data array/object for the array
9702                  *    (i.e. aoData[]._aData)
9703                  *  @param {string} sSpecific The specific data type you want to get -
9704                  *    'display', 'type' 'filter' 'sort'
9705                  *  @returns {*} The data for the cell from the given row's data
9706                  *  @default null
9707                  */
9708                 "fnGetData": null,
9709         
9710                 /**
9711                  * Function to set data for a cell in the column. You should <b>never</b>
9712                  * set the data directly to _aData internally in DataTables - always use
9713                  * this method. It allows mData to function as required. This function
9714                  * is automatically assigned by the column initialisation method
9715                  *  @type function
9716                  *  @param {array|object} oData The data array/object for the array
9717                  *    (i.e. aoData[]._aData)
9718                  *  @param {*} sValue Value to set
9719                  *  @default null
9720                  */
9721                 "fnSetData": null,
9722         
9723                 /**
9724                  * Property to read the value for the cells in the column from the data
9725                  * source array / object. If null, then the default content is used, if a
9726                  * function is given then the return from the function is used.
9727                  *  @type function|int|string|null
9728                  *  @default null
9729                  */
9730                 "mData": null,
9731         
9732                 /**
9733                  * Partner property to mData which is used (only when defined) to get
9734                  * the data - i.e. it is basically the same as mData, but without the
9735                  * 'set' option, and also the data fed to it is the result from mData.
9736                  * This is the rendering method to match the data method of mData.
9737                  *  @type function|int|string|null
9738                  *  @default null
9739                  */
9740                 "mRender": null,
9741         
9742                 /**
9743                  * Unique header TH/TD element for this column - this is what the sorting
9744                  * listener is attached to (if sorting is enabled.)
9745                  *  @type node
9746                  *  @default null
9747                  */
9748                 "nTh": null,
9749         
9750                 /**
9751                  * Unique footer TH/TD element for this column (if there is one). Not used
9752                  * in DataTables as such, but can be used for plug-ins to reference the
9753                  * footer for each column.
9754                  *  @type node
9755                  *  @default null
9756                  */
9757                 "nTf": null,
9758         
9759                 /**
9760                  * The class to apply to all TD elements in the table's TBODY for the column
9761                  *  @type string
9762                  *  @default null
9763                  */
9764                 "sClass": null,
9765         
9766                 /**
9767                  * When DataTables calculates the column widths to assign to each column,
9768                  * it finds the longest string in each column and then constructs a
9769                  * temporary table and reads the widths from that. The problem with this
9770                  * is that "mmm" is much wider then "iiii", but the latter is a longer
9771                  * string - thus the calculation can go wrong (doing it properly and putting
9772                  * it into an DOM object and measuring that is horribly(!) slow). Thus as
9773                  * a "work around" we provide this option. It will append its value to the
9774                  * text that is found to be the longest string for the column - i.e. padding.
9775                  *  @type string
9776                  */
9777                 "sContentPadding": null,
9778         
9779                 /**
9780                  * Allows a default value to be given for a column's data, and will be used
9781                  * whenever a null data source is encountered (this can be because mData
9782                  * is set to null, or because the data source itself is null).
9783                  *  @type string
9784                  *  @default null
9785                  */
9786                 "sDefaultContent": null,
9787         
9788                 /**
9789                  * Name for the column, allowing reference to the column by name as well as
9790                  * by index (needs a lookup to work by name).
9791                  *  @type string
9792                  */
9793                 "sName": null,
9794         
9795                 /**
9796                  * Custom sorting data type - defines which of the available plug-ins in
9797                  * afnSortData the custom sorting will use - if any is defined.
9798                  *  @type string
9799                  *  @default std
9800                  */
9801                 "sSortDataType": 'std',
9802         
9803                 /**
9804                  * Class to be applied to the header element when sorting on this column
9805                  *  @type string
9806                  *  @default null
9807                  */
9808                 "sSortingClass": null,
9809         
9810                 /**
9811                  * Class to be applied to the header element when sorting on this column -
9812                  * when jQuery UI theming is used.
9813                  *  @type string
9814                  *  @default null
9815                  */
9816                 "sSortingClassJUI": null,
9817         
9818                 /**
9819                  * Title of the column - what is seen in the TH element (nTh).
9820                  *  @type string
9821                  */
9822                 "sTitle": null,
9823         
9824                 /**
9825                  * Column sorting and filtering type
9826                  *  @type string
9827                  *  @default null
9828                  */
9829                 "sType": null,
9830         
9831                 /**
9832                  * Width of the column
9833                  *  @type string
9834                  *  @default null
9835                  */
9836                 "sWidth": null,
9837         
9838                 /**
9839                  * Width of the column when it was first "encountered"
9840                  *  @type string
9841                  *  @default null
9842                  */
9843                 "sWidthOrig": null
9844         };
9845         
9846         
9847         /*
9848          * Developer note: The properties of the object below are given in Hungarian
9849          * notation, that was used as the interface for DataTables prior to v1.10, however
9850          * from v1.10 onwards the primary interface is camel case. In order to avoid
9851          * breaking backwards compatibility utterly with this change, the Hungarian
9852          * version is still, internally the primary interface, but is is not documented
9853          * - hence the @name tags in each doc comment. This allows a Javascript function
9854          * to create a map from Hungarian notation to camel case (going the other direction
9855          * would require each property to be listed, which would at around 3K to the size
9856          * of DataTables, while this method is about a 0.5K hit.
9857          *
9858          * Ultimately this does pave the way for Hungarian notation to be dropped
9859          * completely, but that is a massive amount of work and will break current
9860          * installs (therefore is on-hold until v2).
9861          */
9862         
9863         /**
9864          * Initialisation options that can be given to DataTables at initialisation
9865          * time.
9866          *  @namespace
9867          */
9868         DataTable.defaults = {
9869                 /**
9870                  * An array of data to use for the table, passed in at initialisation which
9871                  * will be used in preference to any data which is already in the DOM. This is
9872                  * particularly useful for constructing tables purely in Javascript, for
9873                  * example with a custom Ajax call.
9874                  *  @type array
9875                  *  @default null
9876                  *
9877                  *  @dtopt Option
9878                  *  @name DataTable.defaults.data
9879                  *
9880                  *  @example
9881                  *    // Using a 2D array data source
9882                  *    $(document).ready( function () {
9883                  *      $('#example').dataTable( {
9884                  *        "data": [
9885                  *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9886                  *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9887                  *        ],
9888                  *        "columns": [
9889                  *          { "title": "Engine" },
9890                  *          { "title": "Browser" },
9891                  *          { "title": "Platform" },
9892                  *          { "title": "Version" },
9893                  *          { "title": "Grade" }
9894                  *        ]
9895                  *      } );
9896                  *    } );
9897                  *
9898                  *  @example
9899                  *    // Using an array of objects as a data source (`data`)
9900                  *    $(document).ready( function () {
9901                  *      $('#example').dataTable( {
9902                  *        "data": [
9903                  *          {
9904                  *            "engine":   "Trident",
9905                  *            "browser":  "Internet Explorer 4.0",
9906                  *            "platform": "Win 95+",
9907                  *            "version":  4,
9908                  *            "grade":    "X"
9909                  *          },
9910                  *          {
9911                  *            "engine":   "Trident",
9912                  *            "browser":  "Internet Explorer 5.0",
9913                  *            "platform": "Win 95+",
9914                  *            "version":  5,
9915                  *            "grade":    "C"
9916                  *          }
9917                  *        ],
9918                  *        "columns": [
9919                  *          { "title": "Engine",   "data": "engine" },
9920                  *          { "title": "Browser",  "data": "browser" },
9921                  *          { "title": "Platform", "data": "platform" },
9922                  *          { "title": "Version",  "data": "version" },
9923                  *          { "title": "Grade",    "data": "grade" }
9924                  *        ]
9925                  *      } );
9926                  *    } );
9927                  */
9928                 "aaData": null,
9929         
9930         
9931                 /**
9932                  * If ordering is enabled, then DataTables will perform a first pass sort on
9933                  * initialisation. You can define which column(s) the sort is performed
9934                  * upon, and the sorting direction, with this variable. The `sorting` array
9935                  * should contain an array for each column to be sorted initially containing
9936                  * the column's index and a direction string ('asc' or 'desc').
9937                  *  @type array
9938                  *  @default [[0,'asc']]
9939                  *
9940                  *  @dtopt Option
9941                  *  @name DataTable.defaults.order
9942                  *
9943                  *  @example
9944                  *    // Sort by 3rd column first, and then 4th column
9945                  *    $(document).ready( function() {
9946                  *      $('#example').dataTable( {
9947                  *        "order": [[2,'asc'], [3,'desc']]
9948                  *      } );
9949                  *    } );
9950                  *
9951                  *    // No initial sorting
9952                  *    $(document).ready( function() {
9953                  *      $('#example').dataTable( {
9954                  *        "order": []
9955                  *      } );
9956                  *    } );
9957                  */
9958                 "aaSorting": [[0,'asc']],
9959         
9960         
9961                 /**
9962                  * This parameter is basically identical to the `sorting` parameter, but
9963                  * cannot be overridden by user interaction with the table. What this means
9964                  * is that you could have a column (visible or hidden) which the sorting
9965                  * will always be forced on first - any sorting after that (from the user)
9966                  * will then be performed as required. This can be useful for grouping rows
9967                  * together.
9968                  *  @type array
9969                  *  @default null
9970                  *
9971                  *  @dtopt Option
9972                  *  @name DataTable.defaults.orderFixed
9973                  *
9974                  *  @example
9975                  *    $(document).ready( function() {
9976                  *      $('#example').dataTable( {
9977                  *        "orderFixed": [[0,'asc']]
9978                  *      } );
9979                  *    } )
9980                  */
9981                 "aaSortingFixed": [],
9982         
9983         
9984                 /**
9985                  * DataTables can be instructed to load data to display in the table from a
9986                  * Ajax source. This option defines how that Ajax call is made and where to.
9987                  *
9988                  * The `ajax` property has three different modes of operation, depending on
9989                  * how it is defined. These are:
9990                  *
9991                  * * `string` - Set the URL from where the data should be loaded from.
9992                  * * `object` - Define properties for `jQuery.ajax`.
9993                  * * `function` - Custom data get function
9994                  *
9995                  * `string`
9996                  * --------
9997                  *
9998                  * As a string, the `ajax` property simply defines the URL from which
9999                  * DataTables will load data.
10000                  *
10001                  * `object`
10002                  * --------
10003                  *
10004                  * As an object, the parameters in the object are passed to
10005                  * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
10006                  * of the Ajax request. DataTables has a number of default parameters which
10007                  * you can override using this option. Please refer to the jQuery
10008                  * documentation for a full description of the options available, although
10009                  * the following parameters provide additional options in DataTables or
10010                  * require special consideration:
10011                  *
10012                  * * `data` - As with jQuery, `data` can be provided as an object, but it
10013                  *   can also be used as a function to manipulate the data DataTables sends
10014                  *   to the server. The function takes a single parameter, an object of
10015                  *   parameters with the values that DataTables has readied for sending. An
10016                  *   object may be returned which will be merged into the DataTables
10017                  *   defaults, or you can add the items to the object that was passed in and
10018                  *   not return anything from the function. This supersedes `fnServerParams`
10019                  *   from DataTables 1.9-.
10020                  *
10021                  * * `dataSrc` - By default DataTables will look for the property `data` (or
10022                  *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
10023                  *   from an Ajax source or for server-side processing - this parameter
10024                  *   allows that property to be changed. You can use Javascript dotted
10025                  *   object notation to get a data source for multiple levels of nesting, or
10026                  *   it my be used as a function. As a function it takes a single parameter,
10027                  *   the JSON returned from the server, which can be manipulated as
10028                  *   required, with the returned value being that used by DataTables as the
10029                  *   data source for the table. This supersedes `sAjaxDataProp` from
10030                  *   DataTables 1.9-.
10031                  *
10032                  * * `success` - Should not be overridden it is used internally in
10033                  *   DataTables. To manipulate / transform the data returned by the server
10034                  *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
10035                  *
10036                  * `function`
10037                  * ----------
10038                  *
10039                  * As a function, making the Ajax call is left up to yourself allowing
10040                  * complete control of the Ajax request. Indeed, if desired, a method other
10041                  * than Ajax could be used to obtain the required data, such as Web storage
10042                  * or an AIR database.
10043                  *
10044                  * The function is given four parameters and no return is required. The
10045                  * parameters are:
10046                  *
10047                  * 1. _object_ - Data to send to the server
10048                  * 2. _function_ - Callback function that must be executed when the required
10049                  *    data has been obtained. That data should be passed into the callback
10050                  *    as the only parameter
10051                  * 3. _object_ - DataTables settings object for the table
10052                  *
10053                  * Note that this supersedes `fnServerData` from DataTables 1.9-.
10054                  *
10055                  *  @type string|object|function
10056                  *  @default null
10057                  *
10058                  *  @dtopt Option
10059                  *  @name DataTable.defaults.ajax
10060                  *  @since 1.10.0
10061                  *
10062                  * @example
10063                  *   // Get JSON data from a file via Ajax.
10064                  *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
10065                  *   $('#example').dataTable( {
10066                  *     "ajax": "data.json"
10067                  *   } );
10068                  *
10069                  * @example
10070                  *   // Get JSON data from a file via Ajax, using `dataSrc` to change
10071                  *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
10072                  *   $('#example').dataTable( {
10073                  *     "ajax": {
10074                  *       "url": "data.json",
10075                  *       "dataSrc": "tableData"
10076                  *     }
10077                  *   } );
10078                  *
10079                  * @example
10080                  *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
10081                  *   // from a plain array rather than an array in an object
10082                  *   $('#example').dataTable( {
10083                  *     "ajax": {
10084                  *       "url": "data.json",
10085                  *       "dataSrc": ""
10086                  *     }
10087                  *   } );
10088                  *
10089                  * @example
10090                  *   // Manipulate the data returned from the server - add a link to data
10091                  *   // (note this can, should, be done using `render` for the column - this
10092                  *   // is just a simple example of how the data can be manipulated).
10093                  *   $('#example').dataTable( {
10094                  *     "ajax": {
10095                  *       "url": "data.json",
10096                  *       "dataSrc": function ( json ) {
10097                  *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
10098                  *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
10099                  *         }
10100                  *         return json;
10101                  *       }
10102                  *     }
10103                  *   } );
10104                  *
10105                  * @example
10106                  *   // Add data to the request
10107                  *   $('#example').dataTable( {
10108                  *     "ajax": {
10109                  *       "url": "data.json",
10110                  *       "data": function ( d ) {
10111                  *         return {
10112                  *           "extra_search": $('#extra').val()
10113                  *         };
10114                  *       }
10115                  *     }
10116                  *   } );
10117                  *
10118                  * @example
10119                  *   // Send request as POST
10120                  *   $('#example').dataTable( {
10121                  *     "ajax": {
10122                  *       "url": "data.json",
10123                  *       "type": "POST"
10124                  *     }
10125                  *   } );
10126                  *
10127                  * @example
10128                  *   // Get the data from localStorage (could interface with a form for
10129                  *   // adding, editing and removing rows).
10130                  *   $('#example').dataTable( {
10131                  *     "ajax": function (data, callback, settings) {
10132                  *       callback(
10133                  *         JSON.parse( localStorage.getItem('dataTablesData') )
10134                  *       );
10135                  *     }
10136                  *   } );
10137                  */
10138                 "ajax": null,
10139         
10140         
10141                 /**
10142                  * This parameter allows you to readily specify the entries in the length drop
10143                  * down menu that DataTables shows when pagination is enabled. It can be
10144                  * either a 1D array of options which will be used for both the displayed
10145                  * option and the value, or a 2D array which will use the array in the first
10146                  * position as the value, and the array in the second position as the
10147                  * displayed options (useful for language strings such as 'All').
10148                  *
10149                  * Note that the `pageLength` property will be automatically set to the
10150                  * first value given in this array, unless `pageLength` is also provided.
10151                  *  @type array
10152                  *  @default [ 10, 25, 50, 100 ]
10153                  *
10154                  *  @dtopt Option
10155                  *  @name DataTable.defaults.lengthMenu
10156                  *
10157                  *  @example
10158                  *    $(document).ready( function() {
10159                  *      $('#example').dataTable( {
10160                  *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
10161                  *      } );
10162                  *    } );
10163                  */
10164                 "aLengthMenu": [ 10, 25, 50, 100 ],
10165         
10166         
10167                 /**
10168                  * The `columns` option in the initialisation parameter allows you to define
10169                  * details about the way individual columns behave. For a full list of
10170                  * column options that can be set, please see
10171                  * {@link DataTable.defaults.column}. Note that if you use `columns` to
10172                  * define your columns, you must have an entry in the array for every single
10173                  * column that you have in your table (these can be null if you don't which
10174                  * to specify any options).
10175                  *  @member
10176                  *
10177                  *  @name DataTable.defaults.column
10178                  */
10179                 "aoColumns": null,
10180         
10181                 /**
10182                  * Very similar to `columns`, `columnDefs` allows you to target a specific
10183                  * column, multiple columns, or all columns, using the `targets` property of
10184                  * each object in the array. This allows great flexibility when creating
10185                  * tables, as the `columnDefs` arrays can be of any length, targeting the
10186                  * columns you specifically want. `columnDefs` may use any of the column
10187                  * options available: {@link DataTable.defaults.column}, but it _must_
10188                  * have `targets` defined in each object in the array. Values in the `targets`
10189                  * array may be:
10190                  *   <ul>
10191                  *     <li>a string - class name will be matched on the TH for the column</li>
10192                  *     <li>0 or a positive integer - column index counting from the left</li>
10193                  *     <li>a negative integer - column index counting from the right</li>
10194                  *     <li>the string "_all" - all columns (i.e. assign a default)</li>
10195                  *   </ul>
10196                  *  @member
10197                  *
10198                  *  @name DataTable.defaults.columnDefs
10199                  */
10200                 "aoColumnDefs": null,
10201         
10202         
10203                 /**
10204                  * Basically the same as `search`, this parameter defines the individual column
10205                  * filtering state at initialisation time. The array must be of the same size
10206                  * as the number of columns, and each element be an object with the parameters
10207                  * `search` and `escapeRegex` (the latter is optional). 'null' is also
10208                  * accepted and the default will be used.
10209                  *  @type array
10210                  *  @default []
10211                  *
10212                  *  @dtopt Option
10213                  *  @name DataTable.defaults.searchCols
10214                  *
10215                  *  @example
10216                  *    $(document).ready( function() {
10217                  *      $('#example').dataTable( {
10218                  *        "searchCols": [
10219                  *          null,
10220                  *          { "search": "My filter" },
10221                  *          null,
10222                  *          { "search": "^[0-9]", "escapeRegex": false }
10223                  *        ]
10224                  *      } );
10225                  *    } )
10226                  */
10227                 "aoSearchCols": [],
10228         
10229         
10230                 /**
10231                  * An array of CSS classes that should be applied to displayed rows. This
10232                  * array may be of any length, and DataTables will apply each class
10233                  * sequentially, looping when required.
10234                  *  @type array
10235                  *  @default null <i>Will take the values determined by the `oClasses.stripe*`
10236                  *    options</i>
10237                  *
10238                  *  @dtopt Option
10239                  *  @name DataTable.defaults.stripeClasses
10240                  *
10241                  *  @example
10242                  *    $(document).ready( function() {
10243                  *      $('#example').dataTable( {
10244                  *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
10245                  *      } );
10246                  *    } )
10247                  */
10248                 "asStripeClasses": null,
10249         
10250         
10251                 /**
10252                  * Enable or disable automatic column width calculation. This can be disabled
10253                  * as an optimisation (it takes some time to calculate the widths) if the
10254                  * tables widths are passed in using `columns`.
10255                  *  @type boolean
10256                  *  @default true
10257                  *
10258                  *  @dtopt Features
10259                  *  @name DataTable.defaults.autoWidth
10260                  *
10261                  *  @example
10262                  *    $(document).ready( function () {
10263                  *      $('#example').dataTable( {
10264                  *        "autoWidth": false
10265                  *      } );
10266                  *    } );
10267                  */
10268                 "bAutoWidth": true,
10269         
10270         
10271                 /**
10272                  * Deferred rendering can provide DataTables with a huge speed boost when you
10273                  * are using an Ajax or JS data source for the table. This option, when set to
10274                  * true, will cause DataTables to defer the creation of the table elements for
10275                  * each row until they are needed for a draw - saving a significant amount of
10276                  * time.
10277                  *  @type boolean
10278                  *  @default false
10279                  *
10280                  *  @dtopt Features
10281                  *  @name DataTable.defaults.deferRender
10282                  *
10283                  *  @example
10284                  *    $(document).ready( function() {
10285                  *      $('#example').dataTable( {
10286                  *        "ajax": "sources/arrays.txt",
10287                  *        "deferRender": true
10288                  *      } );
10289                  *    } );
10290                  */
10291                 "bDeferRender": false,
10292         
10293         
10294                 /**
10295                  * Replace a DataTable which matches the given selector and replace it with
10296                  * one which has the properties of the new initialisation object passed. If no
10297                  * table matches the selector, then the new DataTable will be constructed as
10298                  * per normal.
10299                  *  @type boolean
10300                  *  @default false
10301                  *
10302                  *  @dtopt Options
10303                  *  @name DataTable.defaults.destroy
10304                  *
10305                  *  @example
10306                  *    $(document).ready( function() {
10307                  *      $('#example').dataTable( {
10308                  *        "srollY": "200px",
10309                  *        "paginate": false
10310                  *      } );
10311                  *
10312                  *      // Some time later....
10313                  *      $('#example').dataTable( {
10314                  *        "filter": false,
10315                  *        "destroy": true
10316                  *      } );
10317                  *    } );
10318                  */
10319                 "bDestroy": false,
10320         
10321         
10322                 /**
10323                  * Enable or disable filtering of data. Filtering in DataTables is "smart" in
10324                  * that it allows the end user to input multiple words (space separated) and
10325                  * will match a row containing those words, even if not in the order that was
10326                  * specified (this allow matching across multiple columns). Note that if you
10327                  * wish to use filtering in DataTables this must remain 'true' - to remove the
10328                  * default filtering input box and retain filtering abilities, please use
10329                  * {@link DataTable.defaults.dom}.
10330                  *  @type boolean
10331                  *  @default true
10332                  *
10333                  *  @dtopt Features
10334                  *  @name DataTable.defaults.searching
10335                  *
10336                  *  @example
10337                  *    $(document).ready( function () {
10338                  *      $('#example').dataTable( {
10339                  *        "searching": false
10340                  *      } );
10341                  *    } );
10342                  */
10343                 "bFilter": true,
10344         
10345         
10346                 /**
10347                  * Enable or disable the table information display. This shows information
10348                  * about the data that is currently visible on the page, including information
10349                  * about filtered data if that action is being performed.
10350                  *  @type boolean
10351                  *  @default true
10352                  *
10353                  *  @dtopt Features
10354                  *  @name DataTable.defaults.info
10355                  *
10356                  *  @example
10357                  *    $(document).ready( function () {
10358                  *      $('#example').dataTable( {
10359                  *        "info": false
10360                  *      } );
10361                  *    } );
10362                  */
10363                 "bInfo": true,
10364         
10365         
10366                 /**
10367                  * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
10368                  * slightly different and additional mark-up from what DataTables has
10369                  * traditionally used).
10370                  *  @type boolean
10371                  *  @default false
10372                  *
10373                  *  @dtopt Features
10374                  *  @name DataTable.defaults.jQueryUI
10375                  *
10376                  *  @example
10377                  *    $(document).ready( function() {
10378                  *      $('#example').dataTable( {
10379                  *        "jQueryUI": true
10380                  *      } );
10381                  *    } );
10382                  */
10383                 "bJQueryUI": false,
10384         
10385         
10386                 /**
10387                  * Allows the end user to select the size of a formatted page from a select
10388                  * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
10389                  *  @type boolean
10390                  *  @default true
10391                  *
10392                  *  @dtopt Features
10393                  *  @name DataTable.defaults.lengthChange
10394                  *
10395                  *  @example
10396                  *    $(document).ready( function () {
10397                  *      $('#example').dataTable( {
10398                  *        "lengthChange": false
10399                  *      } );
10400                  *    } );
10401                  */
10402                 "bLengthChange": true,
10403         
10404         
10405                 /**
10406                  * Enable or disable pagination.
10407                  *  @type boolean
10408                  *  @default true
10409                  *
10410                  *  @dtopt Features
10411                  *  @name DataTable.defaults.paging
10412                  *
10413                  *  @example
10414                  *    $(document).ready( function () {
10415                  *      $('#example').dataTable( {
10416                  *        "paging": false
10417                  *      } );
10418                  *    } );
10419                  */
10420                 "bPaginate": true,
10421         
10422         
10423                 /**
10424                  * Enable or disable the display of a 'processing' indicator when the table is
10425                  * being processed (e.g. a sort). This is particularly useful for tables with
10426                  * large amounts of data where it can take a noticeable amount of time to sort
10427                  * the entries.
10428                  *  @type boolean
10429                  *  @default false
10430                  *
10431                  *  @dtopt Features
10432                  *  @name DataTable.defaults.processing
10433                  *
10434                  *  @example
10435                  *    $(document).ready( function () {
10436                  *      $('#example').dataTable( {
10437                  *        "processing": true
10438                  *      } );
10439                  *    } );
10440                  */
10441                 "bProcessing": false,
10442         
10443         
10444                 /**
10445                  * Retrieve the DataTables object for the given selector. Note that if the
10446                  * table has already been initialised, this parameter will cause DataTables
10447                  * to simply return the object that has already been set up - it will not take
10448                  * account of any changes you might have made to the initialisation object
10449                  * passed to DataTables (setting this parameter to true is an acknowledgement
10450                  * that you understand this). `destroy` can be used to reinitialise a table if
10451                  * you need.
10452                  *  @type boolean
10453                  *  @default false
10454                  *
10455                  *  @dtopt Options
10456                  *  @name DataTable.defaults.retrieve
10457                  *
10458                  *  @example
10459                  *    $(document).ready( function() {
10460                  *      initTable();
10461                  *      tableActions();
10462                  *    } );
10463                  *
10464                  *    function initTable ()
10465                  *    {
10466                  *      return $('#example').dataTable( {
10467                  *        "scrollY": "200px",
10468                  *        "paginate": false,
10469                  *        "retrieve": true
10470                  *      } );
10471                  *    }
10472                  *
10473                  *    function tableActions ()
10474                  *    {
10475                  *      var table = initTable();
10476                  *      // perform API operations with oTable
10477                  *    }
10478                  */
10479                 "bRetrieve": false,
10480         
10481         
10482                 /**
10483                  * When vertical (y) scrolling is enabled, DataTables will force the height of
10484                  * the table's viewport to the given height at all times (useful for layout).
10485                  * However, this can look odd when filtering data down to a small data set,
10486                  * and the footer is left "floating" further down. This parameter (when
10487                  * enabled) will cause DataTables to collapse the table's viewport down when
10488                  * the result set will fit within the given Y height.
10489                  *  @type boolean
10490                  *  @default false
10491                  *
10492                  *  @dtopt Options
10493                  *  @name DataTable.defaults.scrollCollapse
10494                  *
10495                  *  @example
10496                  *    $(document).ready( function() {
10497                  *      $('#example').dataTable( {
10498                  *        "scrollY": "200",
10499                  *        "scrollCollapse": true
10500                  *      } );
10501                  *    } );
10502                  */
10503                 "bScrollCollapse": false,
10504         
10505         
10506                 /**
10507                  * Configure DataTables to use server-side processing. Note that the
10508                  * `ajax` parameter must also be given in order to give DataTables a
10509                  * source to obtain the required data for each draw.
10510                  *  @type boolean
10511                  *  @default false
10512                  *
10513                  *  @dtopt Features
10514                  *  @dtopt Server-side
10515                  *  @name DataTable.defaults.serverSide
10516                  *
10517                  *  @example
10518                  *    $(document).ready( function () {
10519                  *      $('#example').dataTable( {
10520                  *        "serverSide": true,
10521                  *        "ajax": "xhr.php"
10522                  *      } );
10523                  *    } );
10524                  */
10525                 "bServerSide": false,
10526         
10527         
10528                 /**
10529                  * Enable or disable sorting of columns. Sorting of individual columns can be
10530                  * disabled by the `sortable` option for each column.
10531                  *  @type boolean
10532                  *  @default true
10533                  *
10534                  *  @dtopt Features
10535                  *  @name DataTable.defaults.ordering
10536                  *
10537                  *  @example
10538                  *    $(document).ready( function () {
10539                  *      $('#example').dataTable( {
10540                  *        "ordering": false
10541                  *      } );
10542                  *    } );
10543                  */
10544                 "bSort": true,
10545         
10546         
10547                 /**
10548                  * Enable or display DataTables' ability to sort multiple columns at the
10549                  * same time (activated by shift-click by the user).
10550                  *  @type boolean
10551                  *  @default true
10552                  *
10553                  *  @dtopt Options
10554                  *  @name DataTable.defaults.orderMulti
10555                  *
10556                  *  @example
10557                  *    // Disable multiple column sorting ability
10558                  *    $(document).ready( function () {
10559                  *      $('#example').dataTable( {
10560                  *        "orderMulti": false
10561                  *      } );
10562                  *    } );
10563                  */
10564                 "bSortMulti": true,
10565         
10566         
10567                 /**
10568                  * Allows control over whether DataTables should use the top (true) unique
10569                  * cell that is found for a single column, or the bottom (false - default).
10570                  * This is useful when using complex headers.
10571                  *  @type boolean
10572                  *  @default false
10573                  *
10574                  *  @dtopt Options
10575                  *  @name DataTable.defaults.orderCellsTop
10576                  *
10577                  *  @example
10578                  *    $(document).ready( function() {
10579                  *      $('#example').dataTable( {
10580                  *        "orderCellsTop": true
10581                  *      } );
10582                  *    } );
10583                  */
10584                 "bSortCellsTop": false,
10585         
10586         
10587                 /**
10588                  * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10589                  * `sorting\_3` to the columns which are currently being sorted on. This is
10590                  * presented as a feature switch as it can increase processing time (while
10591                  * classes are removed and added) so for large data sets you might want to
10592                  * turn this off.
10593                  *  @type boolean
10594                  *  @default true
10595                  *
10596                  *  @dtopt Features
10597                  *  @name DataTable.defaults.orderClasses
10598                  *
10599                  *  @example
10600                  *    $(document).ready( function () {
10601                  *      $('#example').dataTable( {
10602                  *        "orderClasses": false
10603                  *      } );
10604                  *    } );
10605                  */
10606                 "bSortClasses": true,
10607         
10608         
10609                 /**
10610                  * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10611                  * used to save table display information such as pagination information,
10612                  * display length, filtering and sorting. As such when the end user reloads
10613                  * the page the display display will match what thy had previously set up.
10614                  *
10615                  * Due to the use of `localStorage` the default state saving is not supported
10616                  * in IE6 or 7. If state saving is required in those browsers, use
10617                  * `stateSaveCallback` to provide a storage solution such as cookies.
10618                  *  @type boolean
10619                  *  @default false
10620                  *
10621                  *  @dtopt Features
10622                  *  @name DataTable.defaults.stateSave
10623                  *
10624                  *  @example
10625                  *    $(document).ready( function () {
10626                  *      $('#example').dataTable( {
10627                  *        "stateSave": true
10628                  *      } );
10629                  *    } );
10630                  */
10631                 "bStateSave": false,
10632         
10633         
10634                 /**
10635                  * This function is called when a TR element is created (and all TD child
10636                  * elements have been inserted), or registered if using a DOM source, allowing
10637                  * manipulation of the TR element (adding classes etc).
10638                  *  @type function
10639                  *  @param {node} row "TR" element for the current row
10640                  *  @param {array} data Raw data array for this row
10641                  *  @param {int} dataIndex The index of this row in the internal aoData array
10642                  *
10643                  *  @dtopt Callbacks
10644                  *  @name DataTable.defaults.createdRow
10645                  *
10646                  *  @example
10647                  *    $(document).ready( function() {
10648                  *      $('#example').dataTable( {
10649                  *        "createdRow": function( row, data, dataIndex ) {
10650                  *          // Bold the grade for all 'A' grade browsers
10651                  *          if ( data[4] == "A" )
10652                  *          {
10653                  *            $('td:eq(4)', row).html( '<b>A</b>' );
10654                  *          }
10655                  *        }
10656                  *      } );
10657                  *    } );
10658                  */
10659                 "fnCreatedRow": null,
10660         
10661         
10662                 /**
10663                  * This function is called on every 'draw' event, and allows you to
10664                  * dynamically modify any aspect you want about the created DOM.
10665                  *  @type function
10666                  *  @param {object} settings DataTables settings object
10667                  *
10668                  *  @dtopt Callbacks
10669                  *  @name DataTable.defaults.drawCallback
10670                  *
10671                  *  @example
10672                  *    $(document).ready( function() {
10673                  *      $('#example').dataTable( {
10674                  *        "drawCallback": function( settings ) {
10675                  *          alert( 'DataTables has redrawn the table' );
10676                  *        }
10677                  *      } );
10678                  *    } );
10679                  */
10680                 "fnDrawCallback": null,
10681         
10682         
10683                 /**
10684                  * Identical to fnHeaderCallback() but for the table footer this function
10685                  * allows you to modify the table footer on every 'draw' event.
10686                  *  @type function
10687                  *  @param {node} foot "TR" element for the footer
10688                  *  @param {array} data Full table data (as derived from the original HTML)
10689                  *  @param {int} start Index for the current display starting point in the
10690                  *    display array
10691                  *  @param {int} end Index for the current display ending point in the
10692                  *    display array
10693                  *  @param {array int} display Index array to translate the visual position
10694                  *    to the full data array
10695                  *
10696                  *  @dtopt Callbacks
10697                  *  @name DataTable.defaults.footerCallback
10698                  *
10699                  *  @example
10700                  *    $(document).ready( function() {
10701                  *      $('#example').dataTable( {
10702                  *        "footerCallback": function( tfoot, data, start, end, display ) {
10703                  *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10704                  *        }
10705                  *      } );
10706                  *    } )
10707                  */
10708                 "fnFooterCallback": null,
10709         
10710         
10711                 /**
10712                  * When rendering large numbers in the information element for the table
10713                  * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10714                  * to have a comma separator for the 'thousands' units (e.g. 1 million is
10715                  * rendered as "1,000,000") to help readability for the end user. This
10716                  * function will override the default method DataTables uses.
10717                  *  @type function
10718                  *  @member
10719                  *  @param {int} toFormat number to be formatted
10720                  *  @returns {string} formatted string for DataTables to show the number
10721                  *
10722                  *  @dtopt Callbacks
10723                  *  @name DataTable.defaults.formatNumber
10724                  *
10725                  *  @example
10726                  *    // Format a number using a single quote for the separator (note that
10727                  *    // this can also be done with the language.thousands option)
10728                  *    $(document).ready( function() {
10729                  *      $('#example').dataTable( {
10730                  *        "formatNumber": function ( toFormat ) {
10731                  *          return toFormat.toString().replace(
10732                  *            /\B(?=(\d{3})+(?!\d))/g, "'"
10733                  *          );
10734                  *        };
10735                  *      } );
10736                  *    } );
10737                  */
10738                 "fnFormatNumber": function ( toFormat ) {
10739                         return toFormat.toString().replace(
10740                                 /\B(?=(\d{3})+(?!\d))/g,
10741                                 this.oLanguage.sThousands
10742                         );
10743                 },
10744         
10745         
10746                 /**
10747                  * This function is called on every 'draw' event, and allows you to
10748                  * dynamically modify the header row. This can be used to calculate and
10749                  * display useful information about the table.
10750                  *  @type function
10751                  *  @param {node} head "TR" element for the header
10752                  *  @param {array} data Full table data (as derived from the original HTML)
10753                  *  @param {int} start Index for the current display starting point in the
10754                  *    display array
10755                  *  @param {int} end Index for the current display ending point in the
10756                  *    display array
10757                  *  @param {array int} display Index array to translate the visual position
10758                  *    to the full data array
10759                  *
10760                  *  @dtopt Callbacks
10761                  *  @name DataTable.defaults.headerCallback
10762                  *
10763                  *  @example
10764                  *    $(document).ready( function() {
10765                  *      $('#example').dataTable( {
10766                  *        "fheaderCallback": function( head, data, start, end, display ) {
10767                  *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10768                  *        }
10769                  *      } );
10770                  *    } )
10771                  */
10772                 "fnHeaderCallback": null,
10773         
10774         
10775                 /**
10776                  * The information element can be used to convey information about the current
10777                  * state of the table. Although the internationalisation options presented by
10778                  * DataTables are quite capable of dealing with most customisations, there may
10779                  * be times where you wish to customise the string further. This callback
10780                  * allows you to do exactly that.
10781                  *  @type function
10782                  *  @param {object} oSettings DataTables settings object
10783                  *  @param {int} start Starting position in data for the draw
10784                  *  @param {int} end End position in data for the draw
10785                  *  @param {int} max Total number of rows in the table (regardless of
10786                  *    filtering)
10787                  *  @param {int} total Total number of rows in the data set, after filtering
10788                  *  @param {string} pre The string that DataTables has formatted using it's
10789                  *    own rules
10790                  *  @returns {string} The string to be displayed in the information element.
10791                  *
10792                  *  @dtopt Callbacks
10793                  *  @name DataTable.defaults.infoCallback
10794                  *
10795                  *  @example
10796                  *    $('#example').dataTable( {
10797                  *      "infoCallback": function( settings, start, end, max, total, pre ) {
10798                  *        return start +" to "+ end;
10799                  *      }
10800                  *    } );
10801                  */
10802                 "fnInfoCallback": null,
10803         
10804         
10805                 /**
10806                  * Called when the table has been initialised. Normally DataTables will
10807                  * initialise sequentially and there will be no need for this function,
10808                  * however, this does not hold true when using external language information
10809                  * since that is obtained using an async XHR call.
10810                  *  @type function
10811                  *  @param {object} settings DataTables settings object
10812                  *  @param {object} json The JSON object request from the server - only
10813                  *    present if client-side Ajax sourced data is used
10814                  *
10815                  *  @dtopt Callbacks
10816                  *  @name DataTable.defaults.initComplete
10817                  *
10818                  *  @example
10819                  *    $(document).ready( function() {
10820                  *      $('#example').dataTable( {
10821                  *        "initComplete": function(settings, json) {
10822                  *          alert( 'DataTables has finished its initialisation.' );
10823                  *        }
10824                  *      } );
10825                  *    } )
10826                  */
10827                 "fnInitComplete": null,
10828         
10829         
10830                 /**
10831                  * Called at the very start of each table draw and can be used to cancel the
10832                  * draw by returning false, any other return (including undefined) results in
10833                  * the full draw occurring).
10834                  *  @type function
10835                  *  @param {object} settings DataTables settings object
10836                  *  @returns {boolean} False will cancel the draw, anything else (including no
10837                  *    return) will allow it to complete.
10838                  *
10839                  *  @dtopt Callbacks
10840                  *  @name DataTable.defaults.preDrawCallback
10841                  *
10842                  *  @example
10843                  *    $(document).ready( function() {
10844                  *      $('#example').dataTable( {
10845                  *        "preDrawCallback": function( settings ) {
10846                  *          if ( $('#test').val() == 1 ) {
10847                  *            return false;
10848                  *          }
10849                  *        }
10850                  *      } );
10851                  *    } );
10852                  */
10853                 "fnPreDrawCallback": null,
10854         
10855         
10856                 /**
10857                  * This function allows you to 'post process' each row after it have been
10858                  * generated for each table draw, but before it is rendered on screen. This
10859                  * function might be used for setting the row class name etc.
10860                  *  @type function
10861                  *  @param {node} row "TR" element for the current row
10862                  *  @param {array} data Raw data array for this row
10863                  *  @param {int} displayIndex The display index for the current table draw
10864                  *  @param {int} displayIndexFull The index of the data in the full list of
10865                  *    rows (after filtering)
10866                  *
10867                  *  @dtopt Callbacks
10868                  *  @name DataTable.defaults.rowCallback
10869                  *
10870                  *  @example
10871                  *    $(document).ready( function() {
10872                  *      $('#example').dataTable( {
10873                  *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10874                  *          // Bold the grade for all 'A' grade browsers
10875                  *          if ( data[4] == "A" ) {
10876                  *            $('td:eq(4)', row).html( '<b>A</b>' );
10877                  *          }
10878                  *        }
10879                  *      } );
10880                  *    } );
10881                  */
10882                 "fnRowCallback": null,
10883         
10884         
10885                 /**
10886                  * __Deprecated__ The functionality provided by this parameter has now been
10887                  * superseded by that provided through `ajax`, which should be used instead.
10888                  *
10889                  * This parameter allows you to override the default function which obtains
10890                  * the data from the server so something more suitable for your application.
10891                  * For example you could use POST data, or pull information from a Gears or
10892                  * AIR database.
10893                  *  @type function
10894                  *  @member
10895                  *  @param {string} source HTTP source to obtain the data from (`ajax`)
10896                  *  @param {array} data A key/value pair object containing the data to send
10897                  *    to the server
10898                  *  @param {function} callback to be called on completion of the data get
10899                  *    process that will draw the data on the page.
10900                  *  @param {object} settings DataTables settings object
10901                  *
10902                  *  @dtopt Callbacks
10903                  *  @dtopt Server-side
10904                  *  @name DataTable.defaults.serverData
10905                  *
10906                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
10907                  */
10908                 "fnServerData": null,
10909         
10910         
10911                 /**
10912                  * __Deprecated__ The functionality provided by this parameter has now been
10913                  * superseded by that provided through `ajax`, which should be used instead.
10914                  *
10915                  *  It is often useful to send extra data to the server when making an Ajax
10916                  * request - for example custom filtering information, and this callback
10917                  * function makes it trivial to send extra information to the server. The
10918                  * passed in parameter is the data set that has been constructed by
10919                  * DataTables, and you can add to this or modify it as you require.
10920                  *  @type function
10921                  *  @param {array} data Data array (array of objects which are name/value
10922                  *    pairs) that has been constructed by DataTables and will be sent to the
10923                  *    server. In the case of Ajax sourced data with server-side processing
10924                  *    this will be an empty array, for server-side processing there will be a
10925                  *    significant number of parameters!
10926                  *  @returns {undefined} Ensure that you modify the data array passed in,
10927                  *    as this is passed by reference.
10928                  *
10929                  *  @dtopt Callbacks
10930                  *  @dtopt Server-side
10931                  *  @name DataTable.defaults.serverParams
10932                  *
10933                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
10934                  */
10935                 "fnServerParams": null,
10936         
10937         
10938                 /**
10939                  * Load the table state. With this function you can define from where, and how, the
10940                  * state of a table is loaded. By default DataTables will load from `localStorage`
10941                  * but you might wish to use a server-side database or cookies.
10942                  *  @type function
10943                  *  @member
10944                  *  @param {object} settings DataTables settings object
10945                  *  @param {object} callback Callback that can be executed when done. It
10946                  *    should be passed the loaded state object.
10947                  *  @return {object} The DataTables state object to be loaded
10948                  *
10949                  *  @dtopt Callbacks
10950                  *  @name DataTable.defaults.stateLoadCallback
10951                  *
10952                  *  @example
10953                  *    $(document).ready( function() {
10954                  *      $('#example').dataTable( {
10955                  *        "stateSave": true,
10956                  *        "stateLoadCallback": function (settings, callback) {
10957                  *          $.ajax( {
10958                  *            "url": "/state_load",
10959                  *            "dataType": "json",
10960                  *            "success": function (json) {
10961                  *              callback( json );
10962                  *            }
10963                  *          } );
10964                  *        }
10965                  *      } );
10966                  *    } );
10967                  */
10968                 "fnStateLoadCallback": function ( settings ) {
10969                         try {
10970                                 return JSON.parse(
10971                                         (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
10972                                                 'DataTables_'+settings.sInstance+'_'+location.pathname
10973                                         )
10974                                 );
10975                         } catch (e) {}
10976                 },
10977         
10978         
10979                 /**
10980                  * Callback which allows modification of the saved state prior to loading that state.
10981                  * This callback is called when the table is loading state from the stored data, but
10982                  * prior to the settings object being modified by the saved state. Note that for
10983                  * plug-in authors, you should use the `stateLoadParams` event to load parameters for
10984                  * a plug-in.
10985                  *  @type function
10986                  *  @param {object} settings DataTables settings object
10987                  *  @param {object} data The state object that is to be loaded
10988                  *
10989                  *  @dtopt Callbacks
10990                  *  @name DataTable.defaults.stateLoadParams
10991                  *
10992                  *  @example
10993                  *    // Remove a saved filter, so filtering is never loaded
10994                  *    $(document).ready( function() {
10995                  *      $('#example').dataTable( {
10996                  *        "stateSave": true,
10997                  *        "stateLoadParams": function (settings, data) {
10998                  *          data.oSearch.sSearch = "";
10999                  *        }
11000                  *      } );
11001                  *    } );
11002                  *
11003                  *  @example
11004                  *    // Disallow state loading by returning false
11005                  *    $(document).ready( function() {
11006                  *      $('#example').dataTable( {
11007                  *        "stateSave": true,
11008                  *        "stateLoadParams": function (settings, data) {
11009                  *          return false;
11010                  *        }
11011                  *      } );
11012                  *    } );
11013                  */
11014                 "fnStateLoadParams": null,
11015         
11016         
11017                 /**
11018                  * Callback that is called when the state has been loaded from the state saving method
11019                  * and the DataTables settings object has been modified as a result of the loaded state.
11020                  *  @type function
11021                  *  @param {object} settings DataTables settings object
11022                  *  @param {object} data The state object that was loaded
11023                  *
11024                  *  @dtopt Callbacks
11025                  *  @name DataTable.defaults.stateLoaded
11026                  *
11027                  *  @example
11028                  *    // Show an alert with the filtering value that was saved
11029                  *    $(document).ready( function() {
11030                  *      $('#example').dataTable( {
11031                  *        "stateSave": true,
11032                  *        "stateLoaded": function (settings, data) {
11033                  *          alert( 'Saved filter was: '+data.oSearch.sSearch );
11034                  *        }
11035                  *      } );
11036                  *    } );
11037                  */
11038                 "fnStateLoaded": null,
11039         
11040         
11041                 /**
11042                  * Save the table state. This function allows you to define where and how the state
11043                  * information for the table is stored By default DataTables will use `localStorage`
11044                  * but you might wish to use a server-side database or cookies.
11045                  *  @type function
11046                  *  @member
11047                  *  @param {object} settings DataTables settings object
11048                  *  @param {object} data The state object to be saved
11049                  *
11050                  *  @dtopt Callbacks
11051                  *  @name DataTable.defaults.stateSaveCallback
11052                  *
11053                  *  @example
11054                  *    $(document).ready( function() {
11055                  *      $('#example').dataTable( {
11056                  *        "stateSave": true,
11057                  *        "stateSaveCallback": function (settings, data) {
11058                  *          // Send an Ajax request to the server with the state object
11059                  *          $.ajax( {
11060                  *            "url": "/state_save",
11061                  *            "data": data,
11062                  *            "dataType": "json",
11063                  *            "method": "POST"
11064                  *            "success": function () {}
11065                  *          } );
11066                  *        }
11067                  *      } );
11068                  *    } );
11069                  */
11070                 "fnStateSaveCallback": function ( settings, data ) {
11071                         try {
11072                                 (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
11073                                         'DataTables_'+settings.sInstance+'_'+location.pathname,
11074                                         JSON.stringify( data )
11075                                 );
11076                         } catch (e) {}
11077                 },
11078         
11079         
11080                 /**
11081                  * Callback which allows modification of the state to be saved. Called when the table
11082                  * has changed state a new state save is required. This method allows modification of
11083                  * the state saving object prior to actually doing the save, including addition or
11084                  * other state properties or modification. Note that for plug-in authors, you should
11085                  * use the `stateSaveParams` event to save parameters for a plug-in.
11086                  *  @type function
11087                  *  @param {object} settings DataTables settings object
11088                  *  @param {object} data The state object to be saved
11089                  *
11090                  *  @dtopt Callbacks
11091                  *  @name DataTable.defaults.stateSaveParams
11092                  *
11093                  *  @example
11094                  *    // Remove a saved filter, so filtering is never saved
11095                  *    $(document).ready( function() {
11096                  *      $('#example').dataTable( {
11097                  *        "stateSave": true,
11098                  *        "stateSaveParams": function (settings, data) {
11099                  *          data.oSearch.sSearch = "";
11100                  *        }
11101                  *      } );
11102                  *    } );
11103                  */
11104                 "fnStateSaveParams": null,
11105         
11106         
11107                 /**
11108                  * Duration for which the saved state information is considered valid. After this period
11109                  * has elapsed the state will be returned to the default.
11110                  * Value is given in seconds.
11111                  *  @type int
11112                  *  @default 7200 <i>(2 hours)</i>
11113                  *
11114                  *  @dtopt Options
11115                  *  @name DataTable.defaults.stateDuration
11116                  *
11117                  *  @example
11118                  *    $(document).ready( function() {
11119                  *      $('#example').dataTable( {
11120                  *        "stateDuration": 60*60*24; // 1 day
11121                  *      } );
11122                  *    } )
11123                  */
11124                 "iStateDuration": 7200,
11125         
11126         
11127                 /**
11128                  * When enabled DataTables will not make a request to the server for the first
11129                  * page draw - rather it will use the data already on the page (no sorting etc
11130                  * will be applied to it), thus saving on an XHR at load time. `deferLoading`
11131                  * is used to indicate that deferred loading is required, but it is also used
11132                  * to tell DataTables how many records there are in the full table (allowing
11133                  * the information element and pagination to be displayed correctly). In the case
11134                  * where a filtering is applied to the table on initial load, this can be
11135                  * indicated by giving the parameter as an array, where the first element is
11136                  * the number of records available after filtering and the second element is the
11137                  * number of records without filtering (allowing the table information element
11138                  * to be shown correctly).
11139                  *  @type int | array
11140                  *  @default null
11141                  *
11142                  *  @dtopt Options
11143                  *  @name DataTable.defaults.deferLoading
11144                  *
11145                  *  @example
11146                  *    // 57 records available in the table, no filtering applied
11147                  *    $(document).ready( function() {
11148                  *      $('#example').dataTable( {
11149                  *        "serverSide": true,
11150                  *        "ajax": "scripts/server_processing.php",
11151                  *        "deferLoading": 57
11152                  *      } );
11153                  *    } );
11154                  *
11155                  *  @example
11156                  *    // 57 records after filtering, 100 without filtering (an initial filter applied)
11157                  *    $(document).ready( function() {
11158                  *      $('#example').dataTable( {
11159                  *        "serverSide": true,
11160                  *        "ajax": "scripts/server_processing.php",
11161                  *        "deferLoading": [ 57, 100 ],
11162                  *        "search": {
11163                  *          "search": "my_filter"
11164                  *        }
11165                  *      } );
11166                  *    } );
11167                  */
11168                 "iDeferLoading": null,
11169         
11170         
11171                 /**
11172                  * Number of rows to display on a single page when using pagination. If
11173                  * feature enabled (`lengthChange`) then the end user will be able to override
11174                  * this to a custom setting using a pop-up menu.
11175                  *  @type int
11176                  *  @default 10
11177                  *
11178                  *  @dtopt Options
11179                  *  @name DataTable.defaults.pageLength
11180                  *
11181                  *  @example
11182                  *    $(document).ready( function() {
11183                  *      $('#example').dataTable( {
11184                  *        "pageLength": 50
11185                  *      } );
11186                  *    } )
11187                  */
11188                 "iDisplayLength": 10,
11189         
11190         
11191                 /**
11192                  * Define the starting point for data display when using DataTables with
11193                  * pagination. Note that this parameter is the number of records, rather than
11194                  * the page number, so if you have 10 records per page and want to start on
11195                  * the third page, it should be "20".
11196                  *  @type int
11197                  *  @default 0
11198                  *
11199                  *  @dtopt Options
11200                  *  @name DataTable.defaults.displayStart
11201                  *
11202                  *  @example
11203                  *    $(document).ready( function() {
11204                  *      $('#example').dataTable( {
11205                  *        "displayStart": 20
11206                  *      } );
11207                  *    } )
11208                  */
11209                 "iDisplayStart": 0,
11210         
11211         
11212                 /**
11213                  * By default DataTables allows keyboard navigation of the table (sorting, paging,
11214                  * and filtering) by adding a `tabindex` attribute to the required elements. This
11215                  * allows you to tab through the controls and press the enter key to activate them.
11216                  * The tabindex is default 0, meaning that the tab follows the flow of the document.
11217                  * You can overrule this using this parameter if you wish. Use a value of -1 to
11218                  * disable built-in keyboard navigation.
11219                  *  @type int
11220                  *  @default 0
11221                  *
11222                  *  @dtopt Options
11223                  *  @name DataTable.defaults.tabIndex
11224                  *
11225                  *  @example
11226                  *    $(document).ready( function() {
11227                  *      $('#example').dataTable( {
11228                  *        "tabIndex": 1
11229                  *      } );
11230                  *    } );
11231                  */
11232                 "iTabIndex": 0,
11233         
11234         
11235                 /**
11236                  * Classes that DataTables assigns to the various components and features
11237                  * that it adds to the HTML table. This allows classes to be configured
11238                  * during initialisation in addition to through the static
11239                  * {@link DataTable.ext.oStdClasses} object).
11240                  *  @namespace
11241                  *  @name DataTable.defaults.classes
11242                  */
11243                 "oClasses": {},
11244         
11245         
11246                 /**
11247                  * All strings that DataTables uses in the user interface that it creates
11248                  * are defined in this object, allowing you to modified them individually or
11249                  * completely replace them all as required.
11250                  *  @namespace
11251                  *  @name DataTable.defaults.language
11252                  */
11253                 "oLanguage": {
11254                         /**
11255                          * Strings that are used for WAI-ARIA labels and controls only (these are not
11256                          * actually visible on the page, but will be read by screenreaders, and thus
11257                          * must be internationalised as well).
11258                          *  @namespace
11259                          *  @name DataTable.defaults.language.aria
11260                          */
11261                         "oAria": {
11262                                 /**
11263                                  * ARIA label that is added to the table headers when the column may be
11264                                  * sorted ascending by activing the column (click or return when focused).
11265                                  * Note that the column header is prefixed to this string.
11266                                  *  @type string
11267                                  *  @default : activate to sort column ascending
11268                                  *
11269                                  *  @dtopt Language
11270                                  *  @name DataTable.defaults.language.aria.sortAscending
11271                                  *
11272                                  *  @example
11273                                  *    $(document).ready( function() {
11274                                  *      $('#example').dataTable( {
11275                                  *        "language": {
11276                                  *          "aria": {
11277                                  *            "sortAscending": " - click/return to sort ascending"
11278                                  *          }
11279                                  *        }
11280                                  *      } );
11281                                  *    } );
11282                                  */
11283                                 "sSortAscending": ": activate to sort column ascending",
11284         
11285                                 /**
11286                                  * ARIA label that is added to the table headers when the column may be
11287                                  * sorted descending by activing the column (click or return when focused).
11288                                  * Note that the column header is prefixed to this string.
11289                                  *  @type string
11290                                  *  @default : activate to sort column ascending
11291                                  *
11292                                  *  @dtopt Language
11293                                  *  @name DataTable.defaults.language.aria.sortDescending
11294                                  *
11295                                  *  @example
11296                                  *    $(document).ready( function() {
11297                                  *      $('#example').dataTable( {
11298                                  *        "language": {
11299                                  *          "aria": {
11300                                  *            "sortDescending": " - click/return to sort descending"
11301                                  *          }
11302                                  *        }
11303                                  *      } );
11304                                  *    } );
11305                                  */
11306                                 "sSortDescending": ": activate to sort column descending"
11307                         },
11308         
11309                         /**
11310                          * Pagination string used by DataTables for the built-in pagination
11311                          * control types.
11312                          *  @namespace
11313                          *  @name DataTable.defaults.language.paginate
11314                          */
11315                         "oPaginate": {
11316                                 /**
11317                                  * Text to use when using the 'full_numbers' type of pagination for the
11318                                  * button to take the user to the first page.
11319                                  *  @type string
11320                                  *  @default First
11321                                  *
11322                                  *  @dtopt Language
11323                                  *  @name DataTable.defaults.language.paginate.first
11324                                  *
11325                                  *  @example
11326                                  *    $(document).ready( function() {
11327                                  *      $('#example').dataTable( {
11328                                  *        "language": {
11329                                  *          "paginate": {
11330                                  *            "first": "First page"
11331                                  *          }
11332                                  *        }
11333                                  *      } );
11334                                  *    } );
11335                                  */
11336                                 "sFirst": "First",
11337         
11338         
11339                                 /**
11340                                  * Text to use when using the 'full_numbers' type of pagination for the
11341                                  * button to take the user to the last page.
11342                                  *  @type string
11343                                  *  @default Last
11344                                  *
11345                                  *  @dtopt Language
11346                                  *  @name DataTable.defaults.language.paginate.last
11347                                  *
11348                                  *  @example
11349                                  *    $(document).ready( function() {
11350                                  *      $('#example').dataTable( {
11351                                  *        "language": {
11352                                  *          "paginate": {
11353                                  *            "last": "Last page"
11354                                  *          }
11355                                  *        }
11356                                  *      } );
11357                                  *    } );
11358                                  */
11359                                 "sLast": "Last",
11360         
11361         
11362                                 /**
11363                                  * Text to use for the 'next' pagination button (to take the user to the
11364                                  * next page).
11365                                  *  @type string
11366                                  *  @default Next
11367                                  *
11368                                  *  @dtopt Language
11369                                  *  @name DataTable.defaults.language.paginate.next
11370                                  *
11371                                  *  @example
11372                                  *    $(document).ready( function() {
11373                                  *      $('#example').dataTable( {
11374                                  *        "language": {
11375                                  *          "paginate": {
11376                                  *            "next": "Next page"
11377                                  *          }
11378                                  *        }
11379                                  *      } );
11380                                  *    } );
11381                                  */
11382                                 "sNext": "Next",
11383         
11384         
11385                                 /**
11386                                  * Text to use for the 'previous' pagination button (to take the user to
11387                                  * the previous page).
11388                                  *  @type string
11389                                  *  @default Previous
11390                                  *
11391                                  *  @dtopt Language
11392                                  *  @name DataTable.defaults.language.paginate.previous
11393                                  *
11394                                  *  @example
11395                                  *    $(document).ready( function() {
11396                                  *      $('#example').dataTable( {
11397                                  *        "language": {
11398                                  *          "paginate": {
11399                                  *            "previous": "Previous page"
11400                                  *          }
11401                                  *        }
11402                                  *      } );
11403                                  *    } );
11404                                  */
11405                                 "sPrevious": "Previous"
11406                         },
11407         
11408                         /**
11409                          * This string is shown in preference to `zeroRecords` when the table is
11410                          * empty of data (regardless of filtering). Note that this is an optional
11411                          * parameter - if it is not given, the value of `zeroRecords` will be used
11412                          * instead (either the default or given value).
11413                          *  @type string
11414                          *  @default No data available in table
11415                          *
11416                          *  @dtopt Language
11417                          *  @name DataTable.defaults.language.emptyTable
11418                          *
11419                          *  @example
11420                          *    $(document).ready( function() {
11421                          *      $('#example').dataTable( {
11422                          *        "language": {
11423                          *          "emptyTable": "No data available in table"
11424                          *        }
11425                          *      } );
11426                          *    } );
11427                          */
11428                         "sEmptyTable": "No data available in table",
11429         
11430         
11431                         /**
11432                          * This string gives information to the end user about the information
11433                          * that is current on display on the page. The following tokens can be
11434                          * used in the string and will be dynamically replaced as the table
11435                          * display updates. This tokens can be placed anywhere in the string, or
11436                          * removed as needed by the language requires:
11437                          *
11438                          * * `\_START\_` - Display index of the first record on the current page
11439                          * * `\_END\_` - Display index of the last record on the current page
11440                          * * `\_TOTAL\_` - Number of records in the table after filtering
11441                          * * `\_MAX\_` - Number of records in the table without filtering
11442                          * * `\_PAGE\_` - Current page number
11443                          * * `\_PAGES\_` - Total number of pages of data in the table
11444                          *
11445                          *  @type string
11446                          *  @default Showing _START_ to _END_ of _TOTAL_ entries
11447                          *
11448                          *  @dtopt Language
11449                          *  @name DataTable.defaults.language.info
11450                          *
11451                          *  @example
11452                          *    $(document).ready( function() {
11453                          *      $('#example').dataTable( {
11454                          *        "language": {
11455                          *          "info": "Showing page _PAGE_ of _PAGES_"
11456                          *        }
11457                          *      } );
11458                          *    } );
11459                          */
11460                         "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
11461         
11462         
11463                         /**
11464                          * Display information string for when the table is empty. Typically the
11465                          * format of this string should match `info`.
11466                          *  @type string
11467                          *  @default Showing 0 to 0 of 0 entries
11468                          *
11469                          *  @dtopt Language
11470                          *  @name DataTable.defaults.language.infoEmpty
11471                          *
11472                          *  @example
11473                          *    $(document).ready( function() {
11474                          *      $('#example').dataTable( {
11475                          *        "language": {
11476                          *          "infoEmpty": "No entries to show"
11477                          *        }
11478                          *      } );
11479                          *    } );
11480                          */
11481                         "sInfoEmpty": "Showing 0 to 0 of 0 entries",
11482         
11483         
11484                         /**
11485                          * When a user filters the information in a table, this string is appended
11486                          * to the information (`info`) to give an idea of how strong the filtering
11487                          * is. The variable _MAX_ is dynamically updated.
11488                          *  @type string
11489                          *  @default (filtered from _MAX_ total entries)
11490                          *
11491                          *  @dtopt Language
11492                          *  @name DataTable.defaults.language.infoFiltered
11493                          *
11494                          *  @example
11495                          *    $(document).ready( function() {
11496                          *      $('#example').dataTable( {
11497                          *        "language": {
11498                          *          "infoFiltered": " - filtering from _MAX_ records"
11499                          *        }
11500                          *      } );
11501                          *    } );
11502                          */
11503                         "sInfoFiltered": "(filtered from _MAX_ total entries)",
11504         
11505         
11506                         /**
11507                          * If can be useful to append extra information to the info string at times,
11508                          * and this variable does exactly that. This information will be appended to
11509                          * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
11510                          * being used) at all times.
11511                          *  @type string
11512                          *  @default <i>Empty string</i>
11513                          *
11514                          *  @dtopt Language
11515                          *  @name DataTable.defaults.language.infoPostFix
11516                          *
11517                          *  @example
11518                          *    $(document).ready( function() {
11519                          *      $('#example').dataTable( {
11520                          *        "language": {
11521                          *          "infoPostFix": "All records shown are derived from real information."
11522                          *        }
11523                          *      } );
11524                          *    } );
11525                          */
11526                         "sInfoPostFix": "",
11527         
11528         
11529                         /**
11530                          * This decimal place operator is a little different from the other
11531                          * language options since DataTables doesn't output floating point
11532                          * numbers, so it won't ever use this for display of a number. Rather,
11533                          * what this parameter does is modify the sort methods of the table so
11534                          * that numbers which are in a format which has a character other than
11535                          * a period (`.`) as a decimal place will be sorted numerically.
11536                          *
11537                          * Note that numbers with different decimal places cannot be shown in
11538                          * the same table and still be sortable, the table must be consistent.
11539                          * However, multiple different tables on the page can use different
11540                          * decimal place characters.
11541                          *  @type string
11542                          *  @default 
11543                          *
11544                          *  @dtopt Language
11545                          *  @name DataTable.defaults.language.decimal
11546                          *
11547                          *  @example
11548                          *    $(document).ready( function() {
11549                          *      $('#example').dataTable( {
11550                          *        "language": {
11551                          *          "decimal": ","
11552                          *          "thousands": "."
11553                          *        }
11554                          *      } );
11555                          *    } );
11556                          */
11557                         "sDecimal": "",
11558         
11559         
11560                         /**
11561                          * DataTables has a build in number formatter (`formatNumber`) which is
11562                          * used to format large numbers that are used in the table information.
11563                          * By default a comma is used, but this can be trivially changed to any
11564                          * character you wish with this parameter.
11565                          *  @type string
11566                          *  @default ,
11567                          *
11568                          *  @dtopt Language
11569                          *  @name DataTable.defaults.language.thousands
11570                          *
11571                          *  @example
11572                          *    $(document).ready( function() {
11573                          *      $('#example').dataTable( {
11574                          *        "language": {
11575                          *          "thousands": "'"
11576                          *        }
11577                          *      } );
11578                          *    } );
11579                          */
11580                         "sThousands": ",",
11581         
11582         
11583                         /**
11584                          * Detail the action that will be taken when the drop down menu for the
11585                          * pagination length option is changed. The '_MENU_' variable is replaced
11586                          * with a default select list of 10, 25, 50 and 100, and can be replaced
11587                          * with a custom select box if required.
11588                          *  @type string
11589                          *  @default Show _MENU_ entries
11590                          *
11591                          *  @dtopt Language
11592                          *  @name DataTable.defaults.language.lengthMenu
11593                          *
11594                          *  @example
11595                          *    // Language change only
11596                          *    $(document).ready( function() {
11597                          *      $('#example').dataTable( {
11598                          *        "language": {
11599                          *          "lengthMenu": "Display _MENU_ records"
11600                          *        }
11601                          *      } );
11602                          *    } );
11603                          *
11604                          *  @example
11605                          *    // Language and options change
11606                          *    $(document).ready( function() {
11607                          *      $('#example').dataTable( {
11608                          *        "language": {
11609                          *          "lengthMenu": 'Display <select>'+
11610                          *            '<option value="10">10</option>'+
11611                          *            '<option value="20">20</option>'+
11612                          *            '<option value="30">30</option>'+
11613                          *            '<option value="40">40</option>'+
11614                          *            '<option value="50">50</option>'+
11615                          *            '<option value="-1">All</option>'+
11616                          *            '</select> records'
11617                          *        }
11618                          *      } );
11619                          *    } );
11620                          */
11621                         "sLengthMenu": "Show _MENU_ entries",
11622         
11623         
11624                         /**
11625                          * When using Ajax sourced data and during the first draw when DataTables is
11626                          * gathering the data, this message is shown in an empty row in the table to
11627                          * indicate to the end user the the data is being loaded. Note that this
11628                          * parameter is not used when loading data by server-side processing, just
11629                          * Ajax sourced data with client-side processing.
11630                          *  @type string
11631                          *  @default Loading...
11632                          *
11633                          *  @dtopt Language
11634                          *  @name DataTable.defaults.language.loadingRecords
11635                          *
11636                          *  @example
11637                          *    $(document).ready( function() {
11638                          *      $('#example').dataTable( {
11639                          *        "language": {
11640                          *          "loadingRecords": "Please wait - loading..."
11641                          *        }
11642                          *      } );
11643                          *    } );
11644                          */
11645                         "sLoadingRecords": "Loading...",
11646         
11647         
11648                         /**
11649                          * Text which is displayed when the table is processing a user action
11650                          * (usually a sort command or similar).
11651                          *  @type string
11652                          *  @default Processing...
11653                          *
11654                          *  @dtopt Language
11655                          *  @name DataTable.defaults.language.processing
11656                          *
11657                          *  @example
11658                          *    $(document).ready( function() {
11659                          *      $('#example').dataTable( {
11660                          *        "language": {
11661                          *          "processing": "DataTables is currently busy"
11662                          *        }
11663                          *      } );
11664                          *    } );
11665                          */
11666                         "sProcessing": "Processing...",
11667         
11668         
11669                         /**
11670                          * Details the actions that will be taken when the user types into the
11671                          * filtering input text box. The variable "_INPUT_", if used in the string,
11672                          * is replaced with the HTML text box for the filtering input allowing
11673                          * control over where it appears in the string. If "_INPUT_" is not given
11674                          * then the input box is appended to the string automatically.
11675                          *  @type string
11676                          *  @default Search:
11677                          *
11678                          *  @dtopt Language
11679                          *  @name DataTable.defaults.language.search
11680                          *
11681                          *  @example
11682                          *    // Input text box will be appended at the end automatically
11683                          *    $(document).ready( function() {
11684                          *      $('#example').dataTable( {
11685                          *        "language": {
11686                          *          "search": "Filter records:"
11687                          *        }
11688                          *      } );
11689                          *    } );
11690                          *
11691                          *  @example
11692                          *    // Specify where the filter should appear
11693                          *    $(document).ready( function() {
11694                          *      $('#example').dataTable( {
11695                          *        "language": {
11696                          *          "search": "Apply filter _INPUT_ to table"
11697                          *        }
11698                          *      } );
11699                          *    } );
11700                          */
11701                         "sSearch": "Search:",
11702         
11703         
11704                         /**
11705                          * Assign a `placeholder` attribute to the search `input` element
11706                          *  @type string
11707                          *  @default 
11708                          *
11709                          *  @dtopt Language
11710                          *  @name DataTable.defaults.language.searchPlaceholder
11711                          */
11712                         "sSearchPlaceholder": "",
11713         
11714         
11715                         /**
11716                          * All of the language information can be stored in a file on the
11717                          * server-side, which DataTables will look up if this parameter is passed.
11718                          * It must store the URL of the language file, which is in a JSON format,
11719                          * and the object has the same properties as the oLanguage object in the
11720                          * initialiser object (i.e. the above parameters). Please refer to one of
11721                          * the example language files to see how this works in action.
11722                          *  @type string
11723                          *  @default <i>Empty string - i.e. disabled</i>
11724                          *
11725                          *  @dtopt Language
11726                          *  @name DataTable.defaults.language.url
11727                          *
11728                          *  @example
11729                          *    $(document).ready( function() {
11730                          *      $('#example').dataTable( {
11731                          *        "language": {
11732                          *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11733                          *        }
11734                          *      } );
11735                          *    } );
11736                          */
11737                         "sUrl": "",
11738         
11739         
11740                         /**
11741                          * Text shown inside the table records when the is no information to be
11742                          * displayed after filtering. `emptyTable` is shown when there is simply no
11743                          * information in the table at all (regardless of filtering).
11744                          *  @type string
11745                          *  @default No matching records found
11746                          *
11747                          *  @dtopt Language
11748                          *  @name DataTable.defaults.language.zeroRecords
11749                          *
11750                          *  @example
11751                          *    $(document).ready( function() {
11752                          *      $('#example').dataTable( {
11753                          *        "language": {
11754                          *          "zeroRecords": "No records to display"
11755                          *        }
11756                          *      } );
11757                          *    } );
11758                          */
11759                         "sZeroRecords": "No matching records found"
11760                 },
11761         
11762         
11763                 /**
11764                  * This parameter allows you to have define the global filtering state at
11765                  * initialisation time. As an object the `search` parameter must be
11766                  * defined, but all other parameters are optional. When `regex` is true,
11767                  * the search string will be treated as a regular expression, when false
11768                  * (default) it will be treated as a straight string. When `smart`
11769                  * DataTables will use it's smart filtering methods (to word match at
11770                  * any point in the data), when false this will not be done.
11771                  *  @namespace
11772                  *  @extends DataTable.models.oSearch
11773                  *
11774                  *  @dtopt Options
11775                  *  @name DataTable.defaults.search
11776                  *
11777                  *  @example
11778                  *    $(document).ready( function() {
11779                  *      $('#example').dataTable( {
11780                  *        "search": {"search": "Initial search"}
11781                  *      } );
11782                  *    } )
11783                  */
11784                 "oSearch": $.extend( {}, DataTable.models.oSearch ),
11785         
11786         
11787                 /**
11788                  * __Deprecated__ The functionality provided by this parameter has now been
11789                  * superseded by that provided through `ajax`, which should be used instead.
11790                  *
11791                  * By default DataTables will look for the property `data` (or `aaData` for
11792                  * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11793                  * source or for server-side processing - this parameter allows that
11794                  * property to be changed. You can use Javascript dotted object notation to
11795                  * get a data source for multiple levels of nesting.
11796                  *  @type string
11797                  *  @default data
11798                  *
11799                  *  @dtopt Options
11800                  *  @dtopt Server-side
11801                  *  @name DataTable.defaults.ajaxDataProp
11802                  *
11803                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
11804                  */
11805                 "sAjaxDataProp": "data",
11806         
11807         
11808                 /**
11809                  * __Deprecated__ The functionality provided by this parameter has now been
11810                  * superseded by that provided through `ajax`, which should be used instead.
11811                  *
11812                  * You can instruct DataTables to load data from an external
11813                  * source using this parameter (use aData if you want to pass data in you
11814                  * already have). Simply provide a url a JSON object can be obtained from.
11815                  *  @type string
11816                  *  @default null
11817                  *
11818                  *  @dtopt Options
11819                  *  @dtopt Server-side
11820                  *  @name DataTable.defaults.ajaxSource
11821                  *
11822                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
11823                  */
11824                 "sAjaxSource": null,
11825         
11826         
11827                 /**
11828                  * This initialisation variable allows you to specify exactly where in the
11829                  * DOM you want DataTables to inject the various controls it adds to the page
11830                  * (for example you might want the pagination controls at the top of the
11831                  * table). DIV elements (with or without a custom class) can also be added to
11832                  * aid styling. The follow syntax is used:
11833                  *   <ul>
11834                  *     <li>The following options are allowed:
11835                  *       <ul>
11836                  *         <li>'l' - Length changing</li>
11837                  *         <li>'f' - Filtering input</li>
11838                  *         <li>'t' - The table!</li>
11839                  *         <li>'i' - Information</li>
11840                  *         <li>'p' - Pagination</li>
11841                  *         <li>'r' - pRocessing</li>
11842                  *       </ul>
11843                  *     </li>
11844                  *     <li>The following constants are allowed:
11845                  *       <ul>
11846                  *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11847                  *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11848                  *       </ul>
11849                  *     </li>
11850                  *     <li>The following syntax is expected:
11851                  *       <ul>
11852                  *         <li>'&lt;' and '&gt;' - div elements</li>
11853                  *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11854                  *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11855                  *       </ul>
11856                  *     </li>
11857                  *     <li>Examples:
11858                  *       <ul>
11859                  *         <li>'&lt;"wrapper"flipt&gt;'</li>
11860                  *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11861                  *       </ul>
11862                  *     </li>
11863                  *   </ul>
11864                  *  @type string
11865                  *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11866                  *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11867                  *
11868                  *  @dtopt Options
11869                  *  @name DataTable.defaults.dom
11870                  *
11871                  *  @example
11872                  *    $(document).ready( function() {
11873                  *      $('#example').dataTable( {
11874                  *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11875                  *      } );
11876                  *    } );
11877                  */
11878                 "sDom": "lfrtip",
11879         
11880         
11881                 /**
11882                  * Search delay option. This will throttle full table searches that use the
11883                  * DataTables provided search input element (it does not effect calls to
11884                  * `dt-api search()`, providing a delay before the search is made.
11885                  *  @type integer
11886                  *  @default 0
11887                  *
11888                  *  @dtopt Options
11889                  *  @name DataTable.defaults.searchDelay
11890                  *
11891                  *  @example
11892                  *    $(document).ready( function() {
11893                  *      $('#example').dataTable( {
11894                  *        "searchDelay": 200
11895                  *      } );
11896                  *    } )
11897                  */
11898                 "searchDelay": null,
11899         
11900         
11901                 /**
11902                  * DataTables features six different built-in options for the buttons to
11903                  * display for pagination control:
11904                  *
11905                  * * `numbers` - Page number buttons only
11906                  * * `simple` - 'Previous' and 'Next' buttons only
11907                  * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11908                  * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11909                  * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus page numbers
11910                  * * `first_last_numbers` - 'First' and 'Last' buttons, plus page numbers
11911                  *  
11912                  * Further methods can be added using {@link DataTable.ext.oPagination}.
11913                  *  @type string
11914                  *  @default simple_numbers
11915                  *
11916                  *  @dtopt Options
11917                  *  @name DataTable.defaults.pagingType
11918                  *
11919                  *  @example
11920                  *    $(document).ready( function() {
11921                  *      $('#example').dataTable( {
11922                  *        "pagingType": "full_numbers"
11923                  *      } );
11924                  *    } )
11925                  */
11926                 "sPaginationType": "simple_numbers",
11927         
11928         
11929                 /**
11930                  * Enable horizontal scrolling. When a table is too wide to fit into a
11931                  * certain layout, or you have a large number of columns in the table, you
11932                  * can enable x-scrolling to show the table in a viewport, which can be
11933                  * scrolled. This property can be `true` which will allow the table to
11934                  * scroll horizontally when needed, or any CSS unit, or a number (in which
11935                  * case it will be treated as a pixel measurement). Setting as simply `true`
11936                  * is recommended.
11937                  *  @type boolean|string
11938                  *  @default <i>blank string - i.e. disabled</i>
11939                  *
11940                  *  @dtopt Features
11941                  *  @name DataTable.defaults.scrollX
11942                  *
11943                  *  @example
11944                  *    $(document).ready( function() {
11945                  *      $('#example').dataTable( {
11946                  *        "scrollX": true,
11947                  *        "scrollCollapse": true
11948                  *      } );
11949                  *    } );
11950                  */
11951                 "sScrollX": "",
11952         
11953         
11954                 /**
11955                  * This property can be used to force a DataTable to use more width than it
11956                  * might otherwise do when x-scrolling is enabled. For example if you have a
11957                  * table which requires to be well spaced, this parameter is useful for
11958                  * "over-sizing" the table, and thus forcing scrolling. This property can by
11959                  * any CSS unit, or a number (in which case it will be treated as a pixel
11960                  * measurement).
11961                  *  @type string
11962                  *  @default <i>blank string - i.e. disabled</i>
11963                  *
11964                  *  @dtopt Options
11965                  *  @name DataTable.defaults.scrollXInner
11966                  *
11967                  *  @example
11968                  *    $(document).ready( function() {
11969                  *      $('#example').dataTable( {
11970                  *        "scrollX": "100%",
11971                  *        "scrollXInner": "110%"
11972                  *      } );
11973                  *    } );
11974                  */
11975                 "sScrollXInner": "",
11976         
11977         
11978                 /**
11979                  * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
11980                  * to the given height, and enable scrolling for any data which overflows the
11981                  * current viewport. This can be used as an alternative to paging to display
11982                  * a lot of data in a small area (although paging and scrolling can both be
11983                  * enabled at the same time). This property can be any CSS unit, or a number
11984                  * (in which case it will be treated as a pixel measurement).
11985                  *  @type string
11986                  *  @default <i>blank string - i.e. disabled</i>
11987                  *
11988                  *  @dtopt Features
11989                  *  @name DataTable.defaults.scrollY
11990                  *
11991                  *  @example
11992                  *    $(document).ready( function() {
11993                  *      $('#example').dataTable( {
11994                  *        "scrollY": "200px",
11995                  *        "paginate": false
11996                  *      } );
11997                  *    } );
11998                  */
11999                 "sScrollY": "",
12000         
12001         
12002                 /**
12003                  * __Deprecated__ The functionality provided by this parameter has now been
12004                  * superseded by that provided through `ajax`, which should be used instead.
12005                  *
12006                  * Set the HTTP method that is used to make the Ajax call for server-side
12007                  * processing or Ajax sourced data.
12008                  *  @type string
12009                  *  @default GET
12010                  *
12011                  *  @dtopt Options
12012                  *  @dtopt Server-side
12013                  *  @name DataTable.defaults.serverMethod
12014                  *
12015                  *  @deprecated 1.10. Please use `ajax` for this functionality now.
12016                  */
12017                 "sServerMethod": "GET",
12018         
12019         
12020                 /**
12021                  * DataTables makes use of renderers when displaying HTML elements for
12022                  * a table. These renderers can be added or modified by plug-ins to
12023                  * generate suitable mark-up for a site. For example the Bootstrap
12024                  * integration plug-in for DataTables uses a paging button renderer to
12025                  * display pagination buttons in the mark-up required by Bootstrap.
12026                  *
12027                  * For further information about the renderers available see
12028                  * DataTable.ext.renderer
12029                  *  @type string|object
12030                  *  @default null
12031                  *
12032                  *  @name DataTable.defaults.renderer
12033                  *
12034                  */
12035                 "renderer": null,
12036         
12037         
12038                 /**
12039                  * Set the data property name that DataTables should use to get a row's id
12040                  * to set as the `id` property in the node.
12041                  *  @type string
12042                  *  @default DT_RowId
12043                  *
12044                  *  @name DataTable.defaults.rowId
12045                  */
12046                 "rowId": "DT_RowId"
12047         };
12048         
12049         _fnHungarianMap( DataTable.defaults );
12050         
12051         
12052         
12053         /*
12054          * Developer note - See note in model.defaults.js about the use of Hungarian
12055          * notation and camel case.
12056          */
12057         
12058         /**
12059          * Column options that can be given to DataTables at initialisation time.
12060          *  @namespace
12061          */
12062         DataTable.defaults.column = {
12063                 /**
12064                  * Define which column(s) an order will occur on for this column. This
12065                  * allows a column's ordering to take multiple columns into account when
12066                  * doing a sort or use the data from a different column. For example first
12067                  * name / last name columns make sense to do a multi-column sort over the
12068                  * two columns.
12069                  *  @type array|int
12070                  *  @default null <i>Takes the value of the column index automatically</i>
12071                  *
12072                  *  @name DataTable.defaults.column.orderData
12073                  *  @dtopt Columns
12074                  *
12075                  *  @example
12076                  *    // Using `columnDefs`
12077                  *    $(document).ready( function() {
12078                  *      $('#example').dataTable( {
12079                  *        "columnDefs": [
12080                  *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
12081                  *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
12082                  *          { "orderData": 2, "targets": [ 2 ] }
12083                  *        ]
12084                  *      } );
12085                  *    } );
12086                  *
12087                  *  @example
12088                  *    // Using `columns`
12089                  *    $(document).ready( function() {
12090                  *      $('#example').dataTable( {
12091                  *        "columns": [
12092                  *          { "orderData": [ 0, 1 ] },
12093                  *          { "orderData": [ 1, 0 ] },
12094                  *          { "orderData": 2 },
12095                  *          null,
12096                  *          null
12097                  *        ]
12098                  *      } );
12099                  *    } );
12100                  */
12101                 "aDataSort": null,
12102                 "iDataSort": -1,
12103         
12104         
12105                 /**
12106                  * You can control the default ordering direction, and even alter the
12107                  * behaviour of the sort handler (i.e. only allow ascending ordering etc)
12108                  * using this parameter.
12109                  *  @type array
12110                  *  @default [ 'asc', 'desc' ]
12111                  *
12112                  *  @name DataTable.defaults.column.orderSequence
12113                  *  @dtopt Columns
12114                  *
12115                  *  @example
12116                  *    // Using `columnDefs`
12117                  *    $(document).ready( function() {
12118                  *      $('#example').dataTable( {
12119                  *        "columnDefs": [
12120                  *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
12121                  *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
12122                  *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
12123                  *        ]
12124                  *      } );
12125                  *    } );
12126                  *
12127                  *  @example
12128                  *    // Using `columns`
12129                  *    $(document).ready( function() {
12130                  *      $('#example').dataTable( {
12131                  *        "columns": [
12132                  *          null,
12133                  *          { "orderSequence": [ "asc" ] },
12134                  *          { "orderSequence": [ "desc", "asc", "asc" ] },
12135                  *          { "orderSequence": [ "desc" ] },
12136                  *          null
12137                  *        ]
12138                  *      } );
12139                  *    } );
12140                  */
12141                 "asSorting": [ 'asc', 'desc' ],
12142         
12143         
12144                 /**
12145                  * Enable or disable filtering on the data in this column.
12146                  *  @type boolean
12147                  *  @default true
12148                  *
12149                  *  @name DataTable.defaults.column.searchable
12150                  *  @dtopt Columns
12151                  *
12152                  *  @example
12153                  *    // Using `columnDefs`
12154                  *    $(document).ready( function() {
12155                  *      $('#example').dataTable( {
12156                  *        "columnDefs": [
12157                  *          { "searchable": false, "targets": [ 0 ] }
12158                  *        ] } );
12159                  *    } );
12160                  *
12161                  *  @example
12162                  *    // Using `columns`
12163                  *    $(document).ready( function() {
12164                  *      $('#example').dataTable( {
12165                  *        "columns": [
12166                  *          { "searchable": false },
12167                  *          null,
12168                  *          null,
12169                  *          null,
12170                  *          null
12171                  *        ] } );
12172                  *    } );
12173                  */
12174                 "bSearchable": true,
12175         
12176         
12177                 /**
12178                  * Enable or disable ordering on this column.
12179                  *  @type boolean
12180                  *  @default true
12181                  *
12182                  *  @name DataTable.defaults.column.orderable
12183                  *  @dtopt Columns
12184                  *
12185                  *  @example
12186                  *    // Using `columnDefs`
12187                  *    $(document).ready( function() {
12188                  *      $('#example').dataTable( {
12189                  *        "columnDefs": [
12190                  *          { "orderable": false, "targets": [ 0 ] }
12191                  *        ] } );
12192                  *    } );
12193                  *
12194                  *  @example
12195                  *    // Using `columns`
12196                  *    $(document).ready( function() {
12197                  *      $('#example').dataTable( {
12198                  *        "columns": [
12199                  *          { "orderable": false },
12200                  *          null,
12201                  *          null,
12202                  *          null,
12203                  *          null
12204                  *        ] } );
12205                  *    } );
12206                  */
12207                 "bSortable": true,
12208         
12209         
12210                 /**
12211                  * Enable or disable the display of this column.
12212                  *  @type boolean
12213                  *  @default true
12214                  *
12215                  *  @name DataTable.defaults.column.visible
12216                  *  @dtopt Columns
12217                  *
12218                  *  @example
12219                  *    // Using `columnDefs`
12220                  *    $(document).ready( function() {
12221                  *      $('#example').dataTable( {
12222                  *        "columnDefs": [
12223                  *          { "visible": false, "targets": [ 0 ] }
12224                  *        ] } );
12225                  *    } );
12226                  *
12227                  *  @example
12228                  *    // Using `columns`
12229                  *    $(document).ready( function() {
12230                  *      $('#example').dataTable( {
12231                  *        "columns": [
12232                  *          { "visible": false },
12233                  *          null,
12234                  *          null,
12235                  *          null,
12236                  *          null
12237                  *        ] } );
12238                  *    } );
12239                  */
12240                 "bVisible": true,
12241         
12242         
12243                 /**
12244                  * Developer definable function that is called whenever a cell is created (Ajax source,
12245                  * etc) or processed for input (DOM source). This can be used as a compliment to mRender
12246                  * allowing you to modify the DOM element (add background colour for example) when the
12247                  * element is available.
12248                  *  @type function
12249                  *  @param {element} td The TD node that has been created
12250                  *  @param {*} cellData The Data for the cell
12251                  *  @param {array|object} rowData The data for the whole row
12252                  *  @param {int} row The row index for the aoData data store
12253                  *  @param {int} col The column index for aoColumns
12254                  *
12255                  *  @name DataTable.defaults.column.createdCell
12256                  *  @dtopt Columns
12257                  *
12258                  *  @example
12259                  *    $(document).ready( function() {
12260                  *      $('#example').dataTable( {
12261                  *        "columnDefs": [ {
12262                  *          "targets": [3],
12263                  *          "createdCell": function (td, cellData, rowData, row, col) {
12264                  *            if ( cellData == "1.7" ) {
12265                  *              $(td).css('color', 'blue')
12266                  *            }
12267                  *          }
12268                  *        } ]
12269                  *      });
12270                  *    } );
12271                  */
12272                 "fnCreatedCell": null,
12273         
12274         
12275                 /**
12276                  * This parameter has been replaced by `data` in DataTables to ensure naming
12277                  * consistency. `dataProp` can still be used, as there is backwards
12278                  * compatibility in DataTables for this option, but it is strongly
12279                  * recommended that you use `data` in preference to `dataProp`.
12280                  *  @name DataTable.defaults.column.dataProp
12281                  */
12282         
12283         
12284                 /**
12285                  * This property can be used to read data from any data source property,
12286                  * including deeply nested objects / properties. `data` can be given in a
12287                  * number of different ways which effect its behaviour:
12288                  *
12289                  * * `integer` - treated as an array index for the data source. This is the
12290                  *   default that DataTables uses (incrementally increased for each column).
12291                  * * `string` - read an object property from the data source. There are
12292                  *   three 'special' options that can be used in the string to alter how
12293                  *   DataTables reads the data from the source object:
12294                  *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12295                  *      Javascript to read from nested objects, so to can the options
12296                  *      specified in `data`. For example: `browser.version` or
12297                  *      `browser.name`. If your object parameter name contains a period, use
12298                  *      `\\` to escape it - i.e. `first\\.name`.
12299                  *    * `[]` - Array notation. DataTables can automatically combine data
12300                  *      from and array source, joining the data with the characters provided
12301                  *      between the two brackets. For example: `name[, ]` would provide a
12302                  *      comma-space separated list from the source array. If no characters
12303                  *      are provided between the brackets, the original array source is
12304                  *      returned.
12305                  *    * `()` - Function notation. Adding `()` to the end of a parameter will
12306                  *      execute a function of the name given. For example: `browser()` for a
12307                  *      simple function on the data source, `browser.version()` for a
12308                  *      function in a nested property or even `browser().version` to get an
12309                  *      object property if the function called returns an object. Note that
12310                  *      function notation is recommended for use in `render` rather than
12311                  *      `data` as it is much simpler to use as a renderer.
12312                  * * `null` - use the original data source for the row rather than plucking
12313                  *   data directly from it. This action has effects on two other
12314                  *   initialisation options:
12315                  *    * `defaultContent` - When null is given as the `data` option and
12316                  *      `defaultContent` is specified for the column, the value defined by
12317                  *      `defaultContent` will be used for the cell.
12318                  *    * `render` - When null is used for the `data` option and the `render`
12319                  *      option is specified for the column, the whole data source for the
12320                  *      row is used for the renderer.
12321                  * * `function` - the function given will be executed whenever DataTables
12322                  *   needs to set or get the data for a cell in the column. The function
12323                  *   takes three parameters:
12324                  *    * Parameters:
12325                  *      * `{array|object}` The data source for the row
12326                  *      * `{string}` The type call data requested - this will be 'set' when
12327                  *        setting data or 'filter', 'display', 'type', 'sort' or undefined
12328                  *        when gathering data. Note that when `undefined` is given for the
12329                  *        type DataTables expects to get the raw data for the object back<
12330                  *      * `{*}` Data to set when the second parameter is 'set'.
12331                  *    * Return:
12332                  *      * The return value from the function is not required when 'set' is
12333                  *        the type of call, but otherwise the return is what will be used
12334                  *        for the data requested.
12335                  *
12336                  * Note that `data` is a getter and setter option. If you just require
12337                  * formatting of data for output, you will likely want to use `render` which
12338                  * is simply a getter and thus simpler to use.
12339                  *
12340                  * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
12341                  * name change reflects the flexibility of this property and is consistent
12342                  * with the naming of mRender. If 'mDataProp' is given, then it will still
12343                  * be used by DataTables, as it automatically maps the old name to the new
12344                  * if required.
12345                  *
12346                  *  @type string|int|function|null
12347                  *  @default null <i>Use automatically calculated column index</i>
12348                  *
12349                  *  @name DataTable.defaults.column.data
12350                  *  @dtopt Columns
12351                  *
12352                  *  @example
12353                  *    // Read table data from objects
12354                  *    // JSON structure for each row:
12355                  *    //   {
12356                  *    //      "engine": {value},
12357                  *    //      "browser": {value},
12358                  *    //      "platform": {value},
12359                  *    //      "version": {value},
12360                  *    //      "grade": {value}
12361                  *    //   }
12362                  *    $(document).ready( function() {
12363                  *      $('#example').dataTable( {
12364                  *        "ajaxSource": "sources/objects.txt",
12365                  *        "columns": [
12366                  *          { "data": "engine" },
12367                  *          { "data": "browser" },
12368                  *          { "data": "platform" },
12369                  *          { "data": "version" },
12370                  *          { "data": "grade" }
12371                  *        ]
12372                  *      } );
12373                  *    } );
12374                  *
12375                  *  @example
12376                  *    // Read information from deeply nested objects
12377                  *    // JSON structure for each row:
12378                  *    //   {
12379                  *    //      "engine": {value},
12380                  *    //      "browser": {value},
12381                  *    //      "platform": {
12382                  *    //         "inner": {value}
12383                  *    //      },
12384                  *    //      "details": [
12385                  *    //         {value}, {value}
12386                  *    //      ]
12387                  *    //   }
12388                  *    $(document).ready( function() {
12389                  *      $('#example').dataTable( {
12390                  *        "ajaxSource": "sources/deep.txt",
12391                  *        "columns": [
12392                  *          { "data": "engine" },
12393                  *          { "data": "browser" },
12394                  *          { "data": "platform.inner" },
12395                  *          { "data": "platform.details.0" },
12396                  *          { "data": "platform.details.1" }
12397                  *        ]
12398                  *      } );
12399                  *    } );
12400                  *
12401                  *  @example
12402                  *    // Using `data` as a function to provide different information for
12403                  *    // sorting, filtering and display. In this case, currency (price)
12404                  *    $(document).ready( function() {
12405                  *      $('#example').dataTable( {
12406                  *        "columnDefs": [ {
12407                  *          "targets": [ 0 ],
12408                  *          "data": function ( source, type, val ) {
12409                  *            if (type === 'set') {
12410                  *              source.price = val;
12411                  *              // Store the computed dislay and filter values for efficiency
12412                  *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
12413                  *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
12414                  *              return;
12415                  *            }
12416                  *            else if (type === 'display') {
12417                  *              return source.price_display;
12418                  *            }
12419                  *            else if (type === 'filter') {
12420                  *              return source.price_filter;
12421                  *            }
12422                  *            // 'sort', 'type' and undefined all just use the integer
12423                  *            return source.price;
12424                  *          }
12425                  *        } ]
12426                  *      } );
12427                  *    } );
12428                  *
12429                  *  @example
12430                  *    // Using default content
12431                  *    $(document).ready( function() {
12432                  *      $('#example').dataTable( {
12433                  *        "columnDefs": [ {
12434                  *          "targets": [ 0 ],
12435                  *          "data": null,
12436                  *          "defaultContent": "Click to edit"
12437                  *        } ]
12438                  *      } );
12439                  *    } );
12440                  *
12441                  *  @example
12442                  *    // Using array notation - outputting a list from an array
12443                  *    $(document).ready( function() {
12444                  *      $('#example').dataTable( {
12445                  *        "columnDefs": [ {
12446                  *          "targets": [ 0 ],
12447                  *          "data": "name[, ]"
12448                  *        } ]
12449                  *      } );
12450                  *    } );
12451                  *
12452                  */
12453                 "mData": null,
12454         
12455         
12456                 /**
12457                  * This property is the rendering partner to `data` and it is suggested that
12458                  * when you want to manipulate data for display (including filtering,
12459                  * sorting etc) without altering the underlying data for the table, use this
12460                  * property. `render` can be considered to be the the read only companion to
12461                  * `data` which is read / write (then as such more complex). Like `data`
12462                  * this option can be given in a number of different ways to effect its
12463                  * behaviour:
12464                  *
12465                  * * `integer` - treated as an array index for the data source. This is the
12466                  *   default that DataTables uses (incrementally increased for each column).
12467                  * * `string` - read an object property from the data source. There are
12468                  *   three 'special' options that can be used in the string to alter how
12469                  *   DataTables reads the data from the source object:
12470                  *    * `.` - Dotted Javascript notation. Just as you use a `.` in
12471                  *      Javascript to read from nested objects, so to can the options
12472                  *      specified in `data`. For example: `browser.version` or
12473                  *      `browser.name`. If your object parameter name contains a period, use
12474                  *      `\\` to escape it - i.e. `first\\.name`.
12475                  *    * `[]` - Array notation. DataTables can automatically combine data
12476                  *      from and array source, joining the data with the characters provided
12477                  *      between the two brackets. For example: `name[, ]` would provide a
12478                  *      comma-space separated list from the source array. If no characters
12479                  *      are provided between the brackets, the original array source is
12480                  *      returned.
12481                  *    * `()` - Function notation. Adding `()` to the end of a parameter will
12482                  *      execute a function of the name given. For example: `browser()` for a
12483                  *      simple function on the data source, `browser.version()` for a
12484                  *      function in a nested property or even `browser().version` to get an
12485                  *      object property if the function called returns an object.
12486                  * * `object` - use different data for the different data types requested by
12487                  *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
12488                  *   of the object is the data type the property refers to and the value can
12489                  *   defined using an integer, string or function using the same rules as
12490                  *   `render` normally does. Note that an `_` option _must_ be specified.
12491                  *   This is the default value to use if you haven't specified a value for
12492                  *   the data type requested by DataTables.
12493                  * * `function` - the function given will be executed whenever DataTables
12494                  *   needs to set or get the data for a cell in the column. The function
12495                  *   takes three parameters:
12496                  *    * Parameters:
12497                  *      * {array|object} The data source for the row (based on `data`)
12498                  *      * {string} The type call data requested - this will be 'filter',
12499                  *        'display', 'type' or 'sort'.
12500                  *      * {array|object} The full data source for the row (not based on
12501                  *        `data`)
12502                  *    * Return:
12503                  *      * The return value from the function is what will be used for the
12504                  *        data requested.
12505                  *
12506                  *  @type string|int|function|object|null
12507                  *  @default null Use the data source value.
12508                  *
12509                  *  @name DataTable.defaults.column.render
12510                  *  @dtopt Columns
12511                  *
12512                  *  @example
12513                  *    // Create a comma separated list from an array of objects
12514                  *    $(document).ready( function() {
12515                  *      $('#example').dataTable( {
12516                  *        "ajaxSource": "sources/deep.txt",
12517                  *        "columns": [
12518                  *          { "data": "engine" },
12519                  *          { "data": "browser" },
12520                  *          {
12521                  *            "data": "platform",
12522                  *            "render": "[, ].name"
12523                  *          }
12524                  *        ]
12525                  *      } );
12526                  *    } );
12527                  *
12528                  *  @example
12529                  *    // Execute a function to obtain data
12530                  *    $(document).ready( function() {
12531                  *      $('#example').dataTable( {
12532                  *        "columnDefs": [ {
12533                  *          "targets": [ 0 ],
12534                  *          "data": null, // Use the full data source object for the renderer's source
12535                  *          "render": "browserName()"
12536                  *        } ]
12537                  *      } );
12538                  *    } );
12539                  *
12540                  *  @example
12541                  *    // As an object, extracting different data for the different types
12542                  *    // This would be used with a data source such as:
12543                  *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
12544                  *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
12545                  *    // (which has both forms) is used for filtering for if a user inputs either format, while
12546                  *    // the formatted phone number is the one that is shown in the table.
12547                  *    $(document).ready( function() {
12548                  *      $('#example').dataTable( {
12549                  *        "columnDefs": [ {
12550                  *          "targets": [ 0 ],
12551                  *          "data": null, // Use the full data source object for the renderer's source
12552                  *          "render": {
12553                  *            "_": "phone",
12554                  *            "filter": "phone_filter",
12555                  *            "display": "phone_display"
12556                  *          }
12557                  *        } ]
12558                  *      } );
12559                  *    } );
12560                  *
12561                  *  @example
12562                  *    // Use as a function to create a link from the data source
12563                  *    $(document).ready( function() {
12564                  *      $('#example').dataTable( {
12565                  *        "columnDefs": [ {
12566                  *          "targets": [ 0 ],
12567                  *          "data": "download_link",
12568                  *          "render": function ( data, type, full ) {
12569                  *            return '<a href="'+data+'">Download</a>';
12570                  *          }
12571                  *        } ]
12572                  *      } );
12573                  *    } );
12574                  */
12575                 "mRender": null,
12576         
12577         
12578                 /**
12579                  * Change the cell type created for the column - either TD cells or TH cells. This
12580                  * can be useful as TH cells have semantic meaning in the table body, allowing them
12581                  * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12582                  *  @type string
12583                  *  @default td
12584                  *
12585                  *  @name DataTable.defaults.column.cellType
12586                  *  @dtopt Columns
12587                  *
12588                  *  @example
12589                  *    // Make the first column use TH cells
12590                  *    $(document).ready( function() {
12591                  *      $('#example').dataTable( {
12592                  *        "columnDefs": [ {
12593                  *          "targets": [ 0 ],
12594                  *          "cellType": "th"
12595                  *        } ]
12596                  *      } );
12597                  *    } );
12598                  */
12599                 "sCellType": "td",
12600         
12601         
12602                 /**
12603                  * Class to give to each cell in this column.
12604                  *  @type string
12605                  *  @default <i>Empty string</i>
12606                  *
12607                  *  @name DataTable.defaults.column.class
12608                  *  @dtopt Columns
12609                  *
12610                  *  @example
12611                  *    // Using `columnDefs`
12612                  *    $(document).ready( function() {
12613                  *      $('#example').dataTable( {
12614                  *        "columnDefs": [
12615                  *          { "class": "my_class", "targets": [ 0 ] }
12616                  *        ]
12617                  *      } );
12618                  *    } );
12619                  *
12620                  *  @example
12621                  *    // Using `columns`
12622                  *    $(document).ready( function() {
12623                  *      $('#example').dataTable( {
12624                  *        "columns": [
12625                  *          { "class": "my_class" },
12626                  *          null,
12627                  *          null,
12628                  *          null,
12629                  *          null
12630                  *        ]
12631                  *      } );
12632                  *    } );
12633                  */
12634                 "sClass": "",
12635         
12636                 /**
12637                  * When DataTables calculates the column widths to assign to each column,
12638                  * it finds the longest string in each column and then constructs a
12639                  * temporary table and reads the widths from that. The problem with this
12640                  * is that "mmm" is much wider then "iiii", but the latter is a longer
12641                  * string - thus the calculation can go wrong (doing it properly and putting
12642                  * it into an DOM object and measuring that is horribly(!) slow). Thus as
12643                  * a "work around" we provide this option. It will append its value to the
12644                  * text that is found to be the longest string for the column - i.e. padding.
12645                  * Generally you shouldn't need this!
12646                  *  @type string
12647                  *  @default <i>Empty string<i>
12648                  *
12649                  *  @name DataTable.defaults.column.contentPadding
12650                  *  @dtopt Columns
12651                  *
12652                  *  @example
12653                  *    // Using `columns`
12654                  *    $(document).ready( function() {
12655                  *      $('#example').dataTable( {
12656                  *        "columns": [
12657                  *          null,
12658                  *          null,
12659                  *          null,
12660                  *          {
12661                  *            "contentPadding": "mmm"
12662                  *          }
12663                  *        ]
12664                  *      } );
12665                  *    } );
12666                  */
12667                 "sContentPadding": "",
12668         
12669         
12670                 /**
12671                  * Allows a default value to be given for a column's data, and will be used
12672                  * whenever a null data source is encountered (this can be because `data`
12673                  * is set to null, or because the data source itself is null).
12674                  *  @type string
12675                  *  @default null
12676                  *
12677                  *  @name DataTable.defaults.column.defaultContent
12678                  *  @dtopt Columns
12679                  *
12680                  *  @example
12681                  *    // Using `columnDefs`
12682                  *    $(document).ready( function() {
12683                  *      $('#example').dataTable( {
12684                  *        "columnDefs": [
12685                  *          {
12686                  *            "data": null,
12687                  *            "defaultContent": "Edit",
12688                  *            "targets": [ -1 ]
12689                  *          }
12690                  *        ]
12691                  *      } );
12692                  *    } );
12693                  *
12694                  *  @example
12695                  *    // Using `columns`
12696                  *    $(document).ready( function() {
12697                  *      $('#example').dataTable( {
12698                  *        "columns": [
12699                  *          null,
12700                  *          null,
12701                  *          null,
12702                  *          {
12703                  *            "data": null,
12704                  *            "defaultContent": "Edit"
12705                  *          }
12706                  *        ]
12707                  *      } );
12708                  *    } );
12709                  */
12710                 "sDefaultContent": null,
12711         
12712         
12713                 /**
12714                  * This parameter is only used in DataTables' server-side processing. It can
12715                  * be exceptionally useful to know what columns are being displayed on the
12716                  * client side, and to map these to database fields. When defined, the names
12717                  * also allow DataTables to reorder information from the server if it comes
12718                  * back in an unexpected order (i.e. if you switch your columns around on the
12719                  * client-side, your server-side code does not also need updating).
12720                  *  @type string
12721                  *  @default <i>Empty string</i>
12722                  *
12723                  *  @name DataTable.defaults.column.name
12724                  *  @dtopt Columns
12725                  *
12726                  *  @example
12727                  *    // Using `columnDefs`
12728                  *    $(document).ready( function() {
12729                  *      $('#example').dataTable( {
12730                  *        "columnDefs": [
12731                  *          { "name": "engine", "targets": [ 0 ] },
12732                  *          { "name": "browser", "targets": [ 1 ] },
12733                  *          { "name": "platform", "targets": [ 2 ] },
12734                  *          { "name": "version", "targets": [ 3 ] },
12735                  *          { "name": "grade", "targets": [ 4 ] }
12736                  *        ]
12737                  *      } );
12738                  *    } );
12739                  *
12740                  *  @example
12741                  *    // Using `columns`
12742                  *    $(document).ready( function() {
12743                  *      $('#example').dataTable( {
12744                  *        "columns": [
12745                  *          { "name": "engine" },
12746                  *          { "name": "browser" },
12747                  *          { "name": "platform" },
12748                  *          { "name": "version" },
12749                  *          { "name": "grade" }
12750                  *        ]
12751                  *      } );
12752                  *    } );
12753                  */
12754                 "sName": "",
12755         
12756         
12757                 /**
12758                  * Defines a data source type for the ordering which can be used to read
12759                  * real-time information from the table (updating the internally cached
12760                  * version) prior to ordering. This allows ordering to occur on user
12761                  * editable elements such as form inputs.
12762                  *  @type string
12763                  *  @default std
12764                  *
12765                  *  @name DataTable.defaults.column.orderDataType
12766                  *  @dtopt Columns
12767                  *
12768                  *  @example
12769                  *    // Using `columnDefs`
12770                  *    $(document).ready( function() {
12771                  *      $('#example').dataTable( {
12772                  *        "columnDefs": [
12773                  *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12774                  *          { "type": "numeric", "targets": [ 3 ] },
12775                  *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12776                  *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12777                  *        ]
12778                  *      } );
12779                  *    } );
12780                  *
12781                  *  @example
12782                  *    // Using `columns`
12783                  *    $(document).ready( function() {
12784                  *      $('#example').dataTable( {
12785                  *        "columns": [
12786                  *          null,
12787                  *          null,
12788                  *          { "orderDataType": "dom-text" },
12789                  *          { "orderDataType": "dom-text", "type": "numeric" },
12790                  *          { "orderDataType": "dom-select" },
12791                  *          { "orderDataType": "dom-checkbox" }
12792                  *        ]
12793                  *      } );
12794                  *    } );
12795                  */
12796                 "sSortDataType": "std",
12797         
12798         
12799                 /**
12800                  * The title of this column.
12801                  *  @type string
12802                  *  @default null <i>Derived from the 'TH' value for this column in the
12803                  *    original HTML table.</i>
12804                  *
12805                  *  @name DataTable.defaults.column.title
12806                  *  @dtopt Columns
12807                  *
12808                  *  @example
12809                  *    // Using `columnDefs`
12810                  *    $(document).ready( function() {
12811                  *      $('#example').dataTable( {
12812                  *        "columnDefs": [
12813                  *          { "title": "My column title", "targets": [ 0 ] }
12814                  *        ]
12815                  *      } );
12816                  *    } );
12817                  *
12818                  *  @example
12819                  *    // Using `columns`
12820                  *    $(document).ready( function() {
12821                  *      $('#example').dataTable( {
12822                  *        "columns": [
12823                  *          { "title": "My column title" },
12824                  *          null,
12825                  *          null,
12826                  *          null,
12827                  *          null
12828                  *        ]
12829                  *      } );
12830                  *    } );
12831                  */
12832                 "sTitle": null,
12833         
12834         
12835                 /**
12836                  * The type allows you to specify how the data for this column will be
12837                  * ordered. Four types (string, numeric, date and html (which will strip
12838                  * HTML tags before ordering)) are currently available. Note that only date
12839                  * formats understood by Javascript's Date() object will be accepted as type
12840                  * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12841                  * 'numeric', 'date' or 'html' (by default). Further types can be adding
12842                  * through plug-ins.
12843                  *  @type string
12844                  *  @default null <i>Auto-detected from raw data</i>
12845                  *
12846                  *  @name DataTable.defaults.column.type
12847                  *  @dtopt Columns
12848                  *
12849                  *  @example
12850                  *    // Using `columnDefs`
12851                  *    $(document).ready( function() {
12852                  *      $('#example').dataTable( {
12853                  *        "columnDefs": [
12854                  *          { "type": "html", "targets": [ 0 ] }
12855                  *        ]
12856                  *      } );
12857                  *    } );
12858                  *
12859                  *  @example
12860                  *    // Using `columns`
12861                  *    $(document).ready( function() {
12862                  *      $('#example').dataTable( {
12863                  *        "columns": [
12864                  *          { "type": "html" },
12865                  *          null,
12866                  *          null,
12867                  *          null,
12868                  *          null
12869                  *        ]
12870                  *      } );
12871                  *    } );
12872                  */
12873                 "sType": null,
12874         
12875         
12876                 /**
12877                  * Defining the width of the column, this parameter may take any CSS value
12878                  * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12879                  * been given a specific width through this interface ensuring that the table
12880                  * remains readable.
12881                  *  @type string
12882                  *  @default null <i>Automatic</i>
12883                  *
12884                  *  @name DataTable.defaults.column.width
12885                  *  @dtopt Columns
12886                  *
12887                  *  @example
12888                  *    // Using `columnDefs`
12889                  *    $(document).ready( function() {
12890                  *      $('#example').dataTable( {
12891                  *        "columnDefs": [
12892                  *          { "width": "20%", "targets": [ 0 ] }
12893                  *        ]
12894                  *      } );
12895                  *    } );
12896                  *
12897                  *  @example
12898                  *    // Using `columns`
12899                  *    $(document).ready( function() {
12900                  *      $('#example').dataTable( {
12901                  *        "columns": [
12902                  *          { "width": "20%" },
12903                  *          null,
12904                  *          null,
12905                  *          null,
12906                  *          null
12907                  *        ]
12908                  *      } );
12909                  *    } );
12910                  */
12911                 "sWidth": null
12912         };
12913         
12914         _fnHungarianMap( DataTable.defaults.column );
12915         
12916         
12917         
12918         /**
12919          * DataTables settings object - this holds all the information needed for a
12920          * given table, including configuration, data and current application of the
12921          * table options. DataTables does not have a single instance for each DataTable
12922          * with the settings attached to that instance, but rather instances of the
12923          * DataTable "class" are created on-the-fly as needed (typically by a
12924          * $().dataTable() call) and the settings object is then applied to that
12925          * instance.
12926          *
12927          * Note that this object is related to {@link DataTable.defaults} but this
12928          * one is the internal data store for DataTables's cache of columns. It should
12929          * NOT be manipulated outside of DataTables. Any configuration should be done
12930          * through the initialisation options.
12931          *  @namespace
12932          *  @todo Really should attach the settings object to individual instances so we
12933          *    don't need to create new instances on each $().dataTable() call (if the
12934          *    table already exists). It would also save passing oSettings around and
12935          *    into every single function. However, this is a very significant
12936          *    architecture change for DataTables and will almost certainly break
12937          *    backwards compatibility with older installations. This is something that
12938          *    will be done in 2.0.
12939          */
12940         DataTable.models.oSettings = {
12941                 /**
12942                  * Primary features of DataTables and their enablement state.
12943                  *  @namespace
12944                  */
12945                 "oFeatures": {
12946         
12947                         /**
12948                          * Flag to say if DataTables should automatically try to calculate the
12949                          * optimum table and columns widths (true) or not (false).
12950                          * Note that this parameter will be set by the initialisation routine. To
12951                          * set a default use {@link DataTable.defaults}.
12952                          *  @type boolean
12953                          */
12954                         "bAutoWidth": null,
12955         
12956                         /**
12957                          * Delay the creation of TR and TD elements until they are actually
12958                          * needed by a driven page draw. This can give a significant speed
12959                          * increase for Ajax source and Javascript source data, but makes no
12960                          * difference at all fro DOM and server-side processing tables.
12961                          * Note that this parameter will be set by the initialisation routine. To
12962                          * set a default use {@link DataTable.defaults}.
12963                          *  @type boolean
12964                          */
12965                         "bDeferRender": null,
12966         
12967                         /**
12968                          * Enable filtering on the table or not. Note that if this is disabled
12969                          * then there is no filtering at all on the table, including fnFilter.
12970                          * To just remove the filtering input use sDom and remove the 'f' option.
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                         "bFilter": null,
12976         
12977                         /**
12978                          * Table information element (the 'Showing x of y records' div) enable
12979                          * flag.
12980                          * Note that this parameter will be set by the initialisation routine. To
12981                          * set a default use {@link DataTable.defaults}.
12982                          *  @type boolean
12983                          */
12984                         "bInfo": null,
12985         
12986                         /**
12987                          * Present a user control allowing the end user to change the page size
12988                          * when pagination is enabled.
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                         "bLengthChange": null,
12994         
12995                         /**
12996                          * Pagination enabled or not. Note that if this is disabled then length
12997                          * changing must also be disabled.
12998                          * Note that this parameter will be set by the initialisation routine. To
12999                          * set a default use {@link DataTable.defaults}.
13000                          *  @type boolean
13001                          */
13002                         "bPaginate": null,
13003         
13004                         /**
13005                          * Processing indicator enable flag whenever DataTables is enacting a
13006                          * user request - typically an Ajax request for server-side processing.
13007                          * Note that this parameter will be set by the initialisation routine. To
13008                          * set a default use {@link DataTable.defaults}.
13009                          *  @type boolean
13010                          */
13011                         "bProcessing": null,
13012         
13013                         /**
13014                          * Server-side processing enabled flag - when enabled DataTables will
13015                          * get all data from the server for every draw - there is no filtering,
13016                          * sorting or paging done on the client-side.
13017                          * Note that this parameter will be set by the initialisation routine. To
13018                          * set a default use {@link DataTable.defaults}.
13019                          *  @type boolean
13020                          */
13021                         "bServerSide": null,
13022         
13023                         /**
13024                          * Sorting enablement flag.
13025                          * Note that this parameter will be set by the initialisation routine. To
13026                          * set a default use {@link DataTable.defaults}.
13027                          *  @type boolean
13028                          */
13029                         "bSort": null,
13030         
13031                         /**
13032                          * Multi-column sorting
13033                          * Note that this parameter will be set by the initialisation routine. To
13034                          * set a default use {@link DataTable.defaults}.
13035                          *  @type boolean
13036                          */
13037                         "bSortMulti": null,
13038         
13039                         /**
13040                          * Apply a class to the columns which are being sorted to provide a
13041                          * visual highlight or not. This can slow things down when enabled since
13042                          * there is a lot of DOM interaction.
13043                          * Note that this parameter will be set by the initialisation routine. To
13044                          * set a default use {@link DataTable.defaults}.
13045                          *  @type boolean
13046                          */
13047                         "bSortClasses": null,
13048         
13049                         /**
13050                          * State saving enablement flag.
13051                          * Note that this parameter will be set by the initialisation routine. To
13052                          * set a default use {@link DataTable.defaults}.
13053                          *  @type boolean
13054                          */
13055                         "bStateSave": null
13056                 },
13057         
13058         
13059                 /**
13060                  * Scrolling settings for a table.
13061                  *  @namespace
13062                  */
13063                 "oScroll": {
13064                         /**
13065                          * When the table is shorter in height than sScrollY, collapse the
13066                          * table container down to the height of the table (when true).
13067                          * Note that this parameter will be set by the initialisation routine. To
13068                          * set a default use {@link DataTable.defaults}.
13069                          *  @type boolean
13070                          */
13071                         "bCollapse": null,
13072         
13073                         /**
13074                          * Width of the scrollbar for the web-browser's platform. Calculated
13075                          * during table initialisation.
13076                          *  @type int
13077                          *  @default 0
13078                          */
13079                         "iBarWidth": 0,
13080         
13081                         /**
13082                          * Viewport width for horizontal scrolling. Horizontal scrolling is
13083                          * disabled if an empty string.
13084                          * Note that this parameter will be set by the initialisation routine. To
13085                          * set a default use {@link DataTable.defaults}.
13086                          *  @type string
13087                          */
13088                         "sX": null,
13089         
13090                         /**
13091                          * Width to expand the table to when using x-scrolling. Typically you
13092                          * should not need to use this.
13093                          * Note that this parameter will be set by the initialisation routine. To
13094                          * set a default use {@link DataTable.defaults}.
13095                          *  @type string
13096                          *  @deprecated
13097                          */
13098                         "sXInner": null,
13099         
13100                         /**
13101                          * Viewport height for vertical scrolling. Vertical scrolling is disabled
13102                          * if an empty string.
13103                          * Note that this parameter will be set by the initialisation routine. To
13104                          * set a default use {@link DataTable.defaults}.
13105                          *  @type string
13106                          */
13107                         "sY": null
13108                 },
13109         
13110                 /**
13111                  * Language information for the table.
13112                  *  @namespace
13113                  *  @extends DataTable.defaults.oLanguage
13114                  */
13115                 "oLanguage": {
13116                         /**
13117                          * Information callback function. See
13118                          * {@link DataTable.defaults.fnInfoCallback}
13119                          *  @type function
13120                          *  @default null
13121                          */
13122                         "fnInfoCallback": null
13123                 },
13124         
13125                 /**
13126                  * Browser support parameters
13127                  *  @namespace
13128                  */
13129                 "oBrowser": {
13130                         /**
13131                          * Indicate if the browser incorrectly calculates width:100% inside a
13132                          * scrolling element (IE6/7)
13133                          *  @type boolean
13134                          *  @default false
13135                          */
13136                         "bScrollOversize": false,
13137         
13138                         /**
13139                          * Determine if the vertical scrollbar is on the right or left of the
13140                          * scrolling container - needed for rtl language layout, although not
13141                          * all browsers move the scrollbar (Safari).
13142                          *  @type boolean
13143                          *  @default false
13144                          */
13145                         "bScrollbarLeft": false,
13146         
13147                         /**
13148                          * Flag for if `getBoundingClientRect` is fully supported or not
13149                          *  @type boolean
13150                          *  @default false
13151                          */
13152                         "bBounding": false,
13153         
13154                         /**
13155                          * Browser scrollbar width
13156                          *  @type integer
13157                          *  @default 0
13158                          */
13159                         "barWidth": 0
13160                 },
13161         
13162         
13163                 "ajax": null,
13164         
13165         
13166                 /**
13167                  * Array referencing the nodes which are used for the features. The
13168                  * parameters of this object match what is allowed by sDom - i.e.
13169                  *   <ul>
13170                  *     <li>'l' - Length changing</li>
13171                  *     <li>'f' - Filtering input</li>
13172                  *     <li>'t' - The table!</li>
13173                  *     <li>'i' - Information</li>
13174                  *     <li>'p' - Pagination</li>
13175                  *     <li>'r' - pRocessing</li>
13176                  *   </ul>
13177                  *  @type array
13178                  *  @default []
13179                  */
13180                 "aanFeatures": [],
13181         
13182                 /**
13183                  * Store data information - see {@link DataTable.models.oRow} for detailed
13184                  * information.
13185                  *  @type array
13186                  *  @default []
13187                  */
13188                 "aoData": [],
13189         
13190                 /**
13191                  * Array of indexes which are in the current display (after filtering etc)
13192                  *  @type array
13193                  *  @default []
13194                  */
13195                 "aiDisplay": [],
13196         
13197                 /**
13198                  * Array of indexes for display - no filtering
13199                  *  @type array
13200                  *  @default []
13201                  */
13202                 "aiDisplayMaster": [],
13203         
13204                 /**
13205                  * Map of row ids to data indexes
13206                  *  @type object
13207                  *  @default {}
13208                  */
13209                 "aIds": {},
13210         
13211                 /**
13212                  * Store information about each column that is in use
13213                  *  @type array
13214                  *  @default []
13215                  */
13216                 "aoColumns": [],
13217         
13218                 /**
13219                  * Store information about the table's header
13220                  *  @type array
13221                  *  @default []
13222                  */
13223                 "aoHeader": [],
13224         
13225                 /**
13226                  * Store information about the table's footer
13227                  *  @type array
13228                  *  @default []
13229                  */
13230                 "aoFooter": [],
13231         
13232                 /**
13233                  * Store the applied global search information in case we want to force a
13234                  * research or compare the old search to a new one.
13235                  * Note that this parameter will be set by the initialisation routine. To
13236                  * set a default use {@link DataTable.defaults}.
13237                  *  @namespace
13238                  *  @extends DataTable.models.oSearch
13239                  */
13240                 "oPreviousSearch": {},
13241         
13242                 /**
13243                  * Store the applied search for each column - see
13244                  * {@link DataTable.models.oSearch} for the format that is used for the
13245                  * filtering information for each column.
13246                  *  @type array
13247                  *  @default []
13248                  */
13249                 "aoPreSearchCols": [],
13250         
13251                 /**
13252                  * Sorting that is applied to the table. Note that the inner arrays are
13253                  * used in the following manner:
13254                  * <ul>
13255                  *   <li>Index 0 - column number</li>
13256                  *   <li>Index 1 - current sorting direction</li>
13257                  * </ul>
13258                  * Note that this parameter will be set by the initialisation routine. To
13259                  * set a default use {@link DataTable.defaults}.
13260                  *  @type array
13261                  *  @todo These inner arrays should really be objects
13262                  */
13263                 "aaSorting": null,
13264         
13265                 /**
13266                  * Sorting that is always applied to the table (i.e. prefixed in front of
13267                  * aaSorting).
13268                  * Note that this parameter will be set by the initialisation routine. To
13269                  * set a default use {@link DataTable.defaults}.
13270                  *  @type array
13271                  *  @default []
13272                  */
13273                 "aaSortingFixed": [],
13274         
13275                 /**
13276                  * Classes to use for the striping of a table.
13277                  * Note that this parameter will be set by the initialisation routine. To
13278                  * set a default use {@link DataTable.defaults}.
13279                  *  @type array
13280                  *  @default []
13281                  */
13282                 "asStripeClasses": null,
13283         
13284                 /**
13285                  * If restoring a table - we should restore its striping classes as well
13286                  *  @type array
13287                  *  @default []
13288                  */
13289                 "asDestroyStripes": [],
13290         
13291                 /**
13292                  * If restoring a table - we should restore its width
13293                  *  @type int
13294                  *  @default 0
13295                  */
13296                 "sDestroyWidth": 0,
13297         
13298                 /**
13299                  * Callback functions array for every time a row is inserted (i.e. on a draw).
13300                  *  @type array
13301                  *  @default []
13302                  */
13303                 "aoRowCallback": [],
13304         
13305                 /**
13306                  * Callback functions for the header on each draw.
13307                  *  @type array
13308                  *  @default []
13309                  */
13310                 "aoHeaderCallback": [],
13311         
13312                 /**
13313                  * Callback function for the footer on each draw.
13314                  *  @type array
13315                  *  @default []
13316                  */
13317                 "aoFooterCallback": [],
13318         
13319                 /**
13320                  * Array of callback functions for draw callback functions
13321                  *  @type array
13322                  *  @default []
13323                  */
13324                 "aoDrawCallback": [],
13325         
13326                 /**
13327                  * Array of callback functions for row created function
13328                  *  @type array
13329                  *  @default []
13330                  */
13331                 "aoRowCreatedCallback": [],
13332         
13333                 /**
13334                  * Callback functions for just before the table is redrawn. A return of
13335                  * false will be used to cancel the draw.
13336                  *  @type array
13337                  *  @default []
13338                  */
13339                 "aoPreDrawCallback": [],
13340         
13341                 /**
13342                  * Callback functions for when the table has been initialised.
13343                  *  @type array
13344                  *  @default []
13345                  */
13346                 "aoInitComplete": [],
13347         
13348         
13349                 /**
13350                  * Callbacks for modifying the settings to be stored for state saving, prior to
13351                  * saving state.
13352                  *  @type array
13353                  *  @default []
13354                  */
13355                 "aoStateSaveParams": [],
13356         
13357                 /**
13358                  * Callbacks for modifying the settings that have been stored for state saving
13359                  * prior to using the stored values to restore the state.
13360                  *  @type array
13361                  *  @default []
13362                  */
13363                 "aoStateLoadParams": [],
13364         
13365                 /**
13366                  * Callbacks for operating on the settings object once the saved state has been
13367                  * loaded
13368                  *  @type array
13369                  *  @default []
13370                  */
13371                 "aoStateLoaded": [],
13372         
13373                 /**
13374                  * Cache the table ID for quick access
13375                  *  @type string
13376                  *  @default <i>Empty string</i>
13377                  */
13378                 "sTableId": "",
13379         
13380                 /**
13381                  * The TABLE node for the main table
13382                  *  @type node
13383                  *  @default null
13384                  */
13385                 "nTable": null,
13386         
13387                 /**
13388                  * Permanent ref to the thead element
13389                  *  @type node
13390                  *  @default null
13391                  */
13392                 "nTHead": null,
13393         
13394                 /**
13395                  * Permanent ref to the tfoot element - if it exists
13396                  *  @type node
13397                  *  @default null
13398                  */
13399                 "nTFoot": null,
13400         
13401                 /**
13402                  * Permanent ref to the tbody element
13403                  *  @type node
13404                  *  @default null
13405                  */
13406                 "nTBody": null,
13407         
13408                 /**
13409                  * Cache the wrapper node (contains all DataTables controlled elements)
13410                  *  @type node
13411                  *  @default null
13412                  */
13413                 "nTableWrapper": null,
13414         
13415                 /**
13416                  * Indicate if when using server-side processing the loading of data
13417                  * should be deferred until the second draw.
13418                  * Note that this parameter will be set by the initialisation routine. To
13419                  * set a default use {@link DataTable.defaults}.
13420                  *  @type boolean
13421                  *  @default false
13422                  */
13423                 "bDeferLoading": false,
13424         
13425                 /**
13426                  * Indicate if all required information has been read in
13427                  *  @type boolean
13428                  *  @default false
13429                  */
13430                 "bInitialised": false,
13431         
13432                 /**
13433                  * Information about open rows. Each object in the array has the parameters
13434                  * 'nTr' and 'nParent'
13435                  *  @type array
13436                  *  @default []
13437                  */
13438                 "aoOpenRows": [],
13439         
13440                 /**
13441                  * Dictate the positioning of DataTables' control elements - see
13442                  * {@link DataTable.model.oInit.sDom}.
13443                  * Note that this parameter will be set by the initialisation routine. To
13444                  * set a default use {@link DataTable.defaults}.
13445                  *  @type string
13446                  *  @default null
13447                  */
13448                 "sDom": null,
13449         
13450                 /**
13451                  * Search delay (in mS)
13452                  *  @type integer
13453                  *  @default null
13454                  */
13455                 "searchDelay": null,
13456         
13457                 /**
13458                  * Which type of pagination should be used.
13459                  * Note that this parameter will be set by the initialisation routine. To
13460                  * set a default use {@link DataTable.defaults}.
13461                  *  @type string
13462                  *  @default two_button
13463                  */
13464                 "sPaginationType": "two_button",
13465         
13466                 /**
13467                  * The state duration (for `stateSave`) in seconds.
13468                  * Note that this parameter will be set by the initialisation routine. To
13469                  * set a default use {@link DataTable.defaults}.
13470                  *  @type int
13471                  *  @default 0
13472                  */
13473                 "iStateDuration": 0,
13474         
13475                 /**
13476                  * Array of callback functions for state saving. Each array element is an
13477                  * object with the following parameters:
13478                  *   <ul>
13479                  *     <li>function:fn - function to call. Takes two parameters, oSettings
13480                  *       and the JSON string to save that has been thus far created. Returns
13481                  *       a JSON string to be inserted into a json object
13482                  *       (i.e. '"param": [ 0, 1, 2]')</li>
13483                  *     <li>string:sName - name of callback</li>
13484                  *   </ul>
13485                  *  @type array
13486                  *  @default []
13487                  */
13488                 "aoStateSave": [],
13489         
13490                 /**
13491                  * Array of callback functions for state loading. Each array element is an
13492                  * object with the following parameters:
13493                  *   <ul>
13494                  *     <li>function:fn - function to call. Takes two parameters, oSettings
13495                  *       and the object stored. May return false to cancel state loading</li>
13496                  *     <li>string:sName - name of callback</li>
13497                  *   </ul>
13498                  *  @type array
13499                  *  @default []
13500                  */
13501                 "aoStateLoad": [],
13502         
13503                 /**
13504                  * State that was saved. Useful for back reference
13505                  *  @type object
13506                  *  @default null
13507                  */
13508                 "oSavedState": null,
13509         
13510                 /**
13511                  * State that was loaded. Useful for back reference
13512                  *  @type object
13513                  *  @default null
13514                  */
13515                 "oLoadedState": null,
13516         
13517                 /**
13518                  * Source url for AJAX data for the table.
13519                  * Note that this parameter will be set by the initialisation routine. To
13520                  * set a default use {@link DataTable.defaults}.
13521                  *  @type string
13522                  *  @default null
13523                  */
13524                 "sAjaxSource": null,
13525         
13526                 /**
13527                  * Property from a given object from which to read the table data from. This
13528                  * can be an empty string (when not server-side processing), in which case
13529                  * it is  assumed an an array is given directly.
13530                  * Note that this parameter will be set by the initialisation routine. To
13531                  * set a default use {@link DataTable.defaults}.
13532                  *  @type string
13533                  */
13534                 "sAjaxDataProp": null,
13535         
13536                 /**
13537                  * Note if draw should be blocked while getting data
13538                  *  @type boolean
13539                  *  @default true
13540                  */
13541                 "bAjaxDataGet": true,
13542         
13543                 /**
13544                  * The last jQuery XHR object that was used for server-side data gathering.
13545                  * This can be used for working with the XHR information in one of the
13546                  * callbacks
13547                  *  @type object
13548                  *  @default null
13549                  */
13550                 "jqXHR": null,
13551         
13552                 /**
13553                  * JSON returned from the server in the last Ajax request
13554                  *  @type object
13555                  *  @default undefined
13556                  */
13557                 "json": undefined,
13558         
13559                 /**
13560                  * Data submitted as part of the last Ajax request
13561                  *  @type object
13562                  *  @default undefined
13563                  */
13564                 "oAjaxData": undefined,
13565         
13566                 /**
13567                  * Function to get the server-side data.
13568                  * Note that this parameter will be set by the initialisation routine. To
13569                  * set a default use {@link DataTable.defaults}.
13570                  *  @type function
13571                  */
13572                 "fnServerData": null,
13573         
13574                 /**
13575                  * Functions which are called prior to sending an Ajax request so extra
13576                  * parameters can easily be sent to the server
13577                  *  @type array
13578                  *  @default []
13579                  */
13580                 "aoServerParams": [],
13581         
13582                 /**
13583                  * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
13584                  * required).
13585                  * Note that this parameter will be set by the initialisation routine. To
13586                  * set a default use {@link DataTable.defaults}.
13587                  *  @type string
13588                  */
13589                 "sServerMethod": null,
13590         
13591                 /**
13592                  * Format numbers for display.
13593                  * Note that this parameter will be set by the initialisation routine. To
13594                  * set a default use {@link DataTable.defaults}.
13595                  *  @type function
13596                  */
13597                 "fnFormatNumber": null,
13598         
13599                 /**
13600                  * List of options that can be used for the user selectable length menu.
13601                  * Note that this parameter will be set by the initialisation routine. To
13602                  * set a default use {@link DataTable.defaults}.
13603                  *  @type array
13604                  *  @default []
13605                  */
13606                 "aLengthMenu": null,
13607         
13608                 /**
13609                  * Counter for the draws that the table does. Also used as a tracker for
13610                  * server-side processing
13611                  *  @type int
13612                  *  @default 0
13613                  */
13614                 "iDraw": 0,
13615         
13616                 /**
13617                  * Indicate if a redraw is being done - useful for Ajax
13618                  *  @type boolean
13619                  *  @default false
13620                  */
13621                 "bDrawing": false,
13622         
13623                 /**
13624                  * Draw index (iDraw) of the last error when parsing the returned data
13625                  *  @type int
13626                  *  @default -1
13627                  */
13628                 "iDrawError": -1,
13629         
13630                 /**
13631                  * Paging display length
13632                  *  @type int
13633                  *  @default 10
13634                  */
13635                 "_iDisplayLength": 10,
13636         
13637                 /**
13638                  * Paging start point - aiDisplay index
13639                  *  @type int
13640                  *  @default 0
13641                  */
13642                 "_iDisplayStart": 0,
13643         
13644                 /**
13645                  * Server-side processing - number of records in the result set
13646                  * (i.e. before filtering), Use fnRecordsTotal rather than
13647                  * this property to get the value of the number of records, regardless of
13648                  * the server-side processing setting.
13649                  *  @type int
13650                  *  @default 0
13651                  *  @private
13652                  */
13653                 "_iRecordsTotal": 0,
13654         
13655                 /**
13656                  * Server-side processing - number of records in the current display set
13657                  * (i.e. after filtering). Use fnRecordsDisplay rather than
13658                  * this property to get the value of the number of records, regardless of
13659                  * the server-side processing setting.
13660                  *  @type boolean
13661                  *  @default 0
13662                  *  @private
13663                  */
13664                 "_iRecordsDisplay": 0,
13665         
13666                 /**
13667                  * Flag to indicate if jQuery UI marking and classes should be used.
13668                  * Note that this parameter will be set by the initialisation routine. To
13669                  * set a default use {@link DataTable.defaults}.
13670                  *  @type boolean
13671                  */
13672                 "bJUI": null,
13673         
13674                 /**
13675                  * The classes to use for the table
13676                  *  @type object
13677                  *  @default {}
13678                  */
13679                 "oClasses": {},
13680         
13681                 /**
13682                  * Flag attached to the settings object so you can check in the draw
13683                  * callback if filtering has been done in the draw. Deprecated in favour of
13684                  * events.
13685                  *  @type boolean
13686                  *  @default false
13687                  *  @deprecated
13688                  */
13689                 "bFiltered": false,
13690         
13691                 /**
13692                  * Flag attached to the settings object so you can check in the draw
13693                  * callback if sorting has been done in the draw. Deprecated in favour of
13694                  * events.
13695                  *  @type boolean
13696                  *  @default false
13697                  *  @deprecated
13698                  */
13699                 "bSorted": false,
13700         
13701                 /**
13702                  * Indicate that if multiple rows are in the header and there is more than
13703                  * one unique cell per column, if the top one (true) or bottom one (false)
13704                  * should be used for sorting / title by DataTables.
13705                  * Note that this parameter will be set by the initialisation routine. To
13706                  * set a default use {@link DataTable.defaults}.
13707                  *  @type boolean
13708                  */
13709                 "bSortCellsTop": null,
13710         
13711                 /**
13712                  * Initialisation object that is used for the table
13713                  *  @type object
13714                  *  @default null
13715                  */
13716                 "oInit": null,
13717         
13718                 /**
13719                  * Destroy callback functions - for plug-ins to attach themselves to the
13720                  * destroy so they can clean up markup and events.
13721                  *  @type array
13722                  *  @default []
13723                  */
13724                 "aoDestroyCallback": [],
13725         
13726         
13727                 /**
13728                  * Get the number of records in the current record set, before filtering
13729                  *  @type function
13730                  */
13731                 "fnRecordsTotal": function ()
13732                 {
13733                         return _fnDataSource( this ) == 'ssp' ?
13734                                 this._iRecordsTotal * 1 :
13735                                 this.aiDisplayMaster.length;
13736                 },
13737         
13738                 /**
13739                  * Get the number of records in the current record set, after filtering
13740                  *  @type function
13741                  */
13742                 "fnRecordsDisplay": function ()
13743                 {
13744                         return _fnDataSource( this ) == 'ssp' ?
13745                                 this._iRecordsDisplay * 1 :
13746                                 this.aiDisplay.length;
13747                 },
13748         
13749                 /**
13750                  * Get the display end point - aiDisplay index
13751                  *  @type function
13752                  */
13753                 "fnDisplayEnd": function ()
13754                 {
13755                         var
13756                                 len      = this._iDisplayLength,
13757                                 start    = this._iDisplayStart,
13758                                 calc     = start + len,
13759                                 records  = this.aiDisplay.length,
13760                                 features = this.oFeatures,
13761                                 paginate = features.bPaginate;
13762         
13763                         if ( features.bServerSide ) {
13764                                 return paginate === false || len === -1 ?
13765                                         start + records :
13766                                         Math.min( start+len, this._iRecordsDisplay );
13767                         }
13768                         else {
13769                                 return ! paginate || calc>records || len===-1 ?
13770                                         records :
13771                                         calc;
13772                         }
13773                 },
13774         
13775                 /**
13776                  * The DataTables object for this table
13777                  *  @type object
13778                  *  @default null
13779                  */
13780                 "oInstance": null,
13781         
13782                 /**
13783                  * Unique identifier for each instance of the DataTables object. If there
13784                  * is an ID on the table node, then it takes that value, otherwise an
13785                  * incrementing internal counter is used.
13786                  *  @type string
13787                  *  @default null
13788                  */
13789                 "sInstance": null,
13790         
13791                 /**
13792                  * tabindex attribute value that is added to DataTables control elements, allowing
13793                  * keyboard navigation of the table and its controls.
13794                  */
13795                 "iTabIndex": 0,
13796         
13797                 /**
13798                  * DIV container for the footer scrolling table if scrolling
13799                  */
13800                 "nScrollHead": null,
13801         
13802                 /**
13803                  * DIV container for the footer scrolling table if scrolling
13804                  */
13805                 "nScrollFoot": null,
13806         
13807                 /**
13808                  * Last applied sort
13809                  *  @type array
13810                  *  @default []
13811                  */
13812                 "aLastSort": [],
13813         
13814                 /**
13815                  * Stored plug-in instances
13816                  *  @type object
13817                  *  @default {}
13818                  */
13819                 "oPlugins": {},
13820         
13821                 /**
13822                  * Function used to get a row's id from the row's data
13823                  *  @type function
13824                  *  @default null
13825                  */
13826                 "rowIdFn": null,
13827         
13828                 /**
13829                  * Data location where to store a row's id
13830                  *  @type string
13831                  *  @default null
13832                  */
13833                 "rowId": null
13834         };
13835
13836         /**
13837          * Extension object for DataTables that is used to provide all extension
13838          * options.
13839          *
13840          * Note that the `DataTable.ext` object is available through
13841          * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13842          * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13843          *  @namespace
13844          *  @extends DataTable.models.ext
13845          */
13846         
13847         
13848         /**
13849          * DataTables extensions
13850          * 
13851          * This namespace acts as a collection area for plug-ins that can be used to
13852          * extend DataTables capabilities. Indeed many of the build in methods
13853          * use this method to provide their own capabilities (sorting methods for
13854          * example).
13855          *
13856          * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13857          * reasons
13858          *
13859          *  @namespace
13860          */
13861         DataTable.ext = _ext = {
13862                 /**
13863                  * Buttons. For use with the Buttons extension for DataTables. This is
13864                  * defined here so other extensions can define buttons regardless of load
13865                  * order. It is _not_ used by DataTables core.
13866                  *
13867                  *  @type object
13868                  *  @default {}
13869                  */
13870                 buttons: {},
13871         
13872         
13873                 /**
13874                  * Element class names
13875                  *
13876                  *  @type object
13877                  *  @default {}
13878                  */
13879                 classes: {},
13880         
13881         
13882                 /**
13883                  * DataTables build type (expanded by the download builder)
13884                  *
13885                  *  @type string
13886                  */
13887                 builder: "-source-",
13888         
13889         
13890                 /**
13891                  * Error reporting.
13892                  * 
13893                  * How should DataTables report an error. Can take the value 'alert',
13894                  * 'throw', 'none' or a function.
13895                  *
13896                  *  @type string|function
13897                  *  @default alert
13898                  */
13899                 errMode: "alert",
13900         
13901         
13902                 /**
13903                  * Feature plug-ins.
13904                  * 
13905                  * This is an array of objects which describe the feature plug-ins that are
13906                  * available to DataTables. These feature plug-ins are then available for
13907                  * use through the `dom` initialisation option.
13908                  * 
13909                  * Each feature plug-in is described by an object which must have the
13910                  * following properties:
13911                  * 
13912                  * * `fnInit` - function that is used to initialise the plug-in,
13913                  * * `cFeature` - a character so the feature can be enabled by the `dom`
13914                  *   instillation option. This is case sensitive.
13915                  *
13916                  * The `fnInit` function has the following input parameters:
13917                  *
13918                  * 1. `{object}` DataTables settings object: see
13919                  *    {@link DataTable.models.oSettings}
13920                  *
13921                  * And the following return is expected:
13922                  * 
13923                  * * {node|null} The element which contains your feature. Note that the
13924                  *   return may also be void if your plug-in does not require to inject any
13925                  *   DOM elements into DataTables control (`dom`) - for example this might
13926                  *   be useful when developing a plug-in which allows table control via
13927                  *   keyboard entry
13928                  *
13929                  *  @type array
13930                  *
13931                  *  @example
13932                  *    $.fn.dataTable.ext.features.push( {
13933                  *      "fnInit": function( oSettings ) {
13934                  *        return new TableTools( { "oDTSettings": oSettings } );
13935                  *      },
13936                  *      "cFeature": "T"
13937                  *    } );
13938                  */
13939                 feature: [],
13940         
13941         
13942                 /**
13943                  * Row searching.
13944                  * 
13945                  * This method of searching is complimentary to the default type based
13946                  * searching, and a lot more comprehensive as it allows you complete control
13947                  * over the searching logic. Each element in this array is a function
13948                  * (parameters described below) that is called for every row in the table,
13949                  * and your logic decides if it should be included in the searching data set
13950                  * or not.
13951                  *
13952                  * Searching functions have the following input parameters:
13953                  *
13954                  * 1. `{object}` DataTables settings object: see
13955                  *    {@link DataTable.models.oSettings}
13956                  * 2. `{array|object}` Data for the row to be processed (same as the
13957                  *    original format that was passed in as the data source, or an array
13958                  *    from a DOM data source
13959                  * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13960                  *    can be useful to retrieve the `TR` element if you need DOM interaction.
13961                  *
13962                  * And the following return is expected:
13963                  *
13964                  * * {boolean} Include the row in the searched result set (true) or not
13965                  *   (false)
13966                  *
13967                  * Note that as with the main search ability in DataTables, technically this
13968                  * is "filtering", since it is subtractive. However, for consistency in
13969                  * naming we call it searching here.
13970                  *
13971                  *  @type array
13972                  *  @default []
13973                  *
13974                  *  @example
13975                  *    // The following example shows custom search being applied to the
13976                  *    // fourth column (i.e. the data[3] index) based on two input values
13977                  *    // from the end-user, matching the data in a certain range.
13978                  *    $.fn.dataTable.ext.search.push(
13979                  *      function( settings, data, dataIndex ) {
13980                  *        var min = document.getElementById('min').value * 1;
13981                  *        var max = document.getElementById('max').value * 1;
13982                  *        var version = data[3] == "-" ? 0 : data[3]*1;
13983                  *
13984                  *        if ( min == "" && max == "" ) {
13985                  *          return true;
13986                  *        }
13987                  *        else if ( min == "" && version < max ) {
13988                  *          return true;
13989                  *        }
13990                  *        else if ( min < version && "" == max ) {
13991                  *          return true;
13992                  *        }
13993                  *        else if ( min < version && version < max ) {
13994                  *          return true;
13995                  *        }
13996                  *        return false;
13997                  *      }
13998                  *    );
13999                  */
14000                 search: [],
14001         
14002         
14003                 /**
14004                  * Selector extensions
14005                  *
14006                  * The `selector` option can be used to extend the options available for the
14007                  * selector modifier options (`selector-modifier` object data type) that
14008                  * each of the three built in selector types offer (row, column and cell +
14009                  * their plural counterparts). For example the Select extension uses this
14010                  * mechanism to provide an option to select only rows, columns and cells
14011                  * that have been marked as selected by the end user (`{selected: true}`),
14012                  * which can be used in conjunction with the existing built in selector
14013                  * options.
14014                  *
14015                  * Each property is an array to which functions can be pushed. The functions
14016                  * take three attributes:
14017                  *
14018                  * * Settings object for the host table
14019                  * * Options object (`selector-modifier` object type)
14020                  * * Array of selected item indexes
14021                  *
14022                  * The return is an array of the resulting item indexes after the custom
14023                  * selector has been applied.
14024                  *
14025                  *  @type object
14026                  */
14027                 selector: {
14028                         cell: [],
14029                         column: [],
14030                         row: []
14031                 },
14032         
14033         
14034                 /**
14035                  * Internal functions, exposed for used in plug-ins.
14036                  * 
14037                  * Please note that you should not need to use the internal methods for
14038                  * anything other than a plug-in (and even then, try to avoid if possible).
14039                  * The internal function may change between releases.
14040                  *
14041                  *  @type object
14042                  *  @default {}
14043                  */
14044                 internal: {},
14045         
14046         
14047                 /**
14048                  * Legacy configuration options. Enable and disable legacy options that
14049                  * are available in DataTables.
14050                  *
14051                  *  @type object
14052                  */
14053                 legacy: {
14054                         /**
14055                          * Enable / disable DataTables 1.9 compatible server-side processing
14056                          * requests
14057                          *
14058                          *  @type boolean
14059                          *  @default null
14060                          */
14061                         ajax: null
14062                 },
14063         
14064         
14065                 /**
14066                  * Pagination plug-in methods.
14067                  * 
14068                  * Each entry in this object is a function and defines which buttons should
14069                  * be shown by the pagination rendering method that is used for the table:
14070                  * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
14071                  * buttons are displayed in the document, while the functions here tell it
14072                  * what buttons to display. This is done by returning an array of button
14073                  * descriptions (what each button will do).
14074                  *
14075                  * Pagination types (the four built in options and any additional plug-in
14076                  * options defined here) can be used through the `paginationType`
14077                  * initialisation parameter.
14078                  *
14079                  * The functions defined take two parameters:
14080                  *
14081                  * 1. `{int} page` The current page index
14082                  * 2. `{int} pages` The number of pages in the table
14083                  *
14084                  * Each function is expected to return an array where each element of the
14085                  * array can be one of:
14086                  *
14087                  * * `first` - Jump to first page when activated
14088                  * * `last` - Jump to last page when activated
14089                  * * `previous` - Show previous page when activated
14090                  * * `next` - Show next page when activated
14091                  * * `{int}` - Show page of the index given
14092                  * * `{array}` - A nested array containing the above elements to add a
14093                  *   containing 'DIV' element (might be useful for styling).
14094                  *
14095                  * Note that DataTables v1.9- used this object slightly differently whereby
14096                  * an object with two functions would be defined for each plug-in. That
14097                  * ability is still supported by DataTables 1.10+ to provide backwards
14098                  * compatibility, but this option of use is now decremented and no longer
14099                  * documented in DataTables 1.10+.
14100                  *
14101                  *  @type object
14102                  *  @default {}
14103                  *
14104                  *  @example
14105                  *    // Show previous, next and current page buttons only
14106                  *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
14107                  *      return [ 'previous', page, 'next' ];
14108                  *    };
14109                  */
14110                 pager: {},
14111         
14112         
14113                 renderer: {
14114                         pageButton: {},
14115                         header: {}
14116                 },
14117         
14118         
14119                 /**
14120                  * Ordering plug-ins - custom data source
14121                  * 
14122                  * The extension options for ordering of data available here is complimentary
14123                  * to the default type based ordering that DataTables typically uses. It
14124                  * allows much greater control over the the data that is being used to
14125                  * order a column, but is necessarily therefore more complex.
14126                  * 
14127                  * This type of ordering is useful if you want to do ordering based on data
14128                  * live from the DOM (for example the contents of an 'input' element) rather
14129                  * than just the static string that DataTables knows of.
14130                  * 
14131                  * The way these plug-ins work is that you create an array of the values you
14132                  * wish to be ordering for the column in question and then return that
14133                  * array. The data in the array much be in the index order of the rows in
14134                  * the table (not the currently ordering order!). Which order data gathering
14135                  * function is run here depends on the `dt-init columns.orderDataType`
14136                  * parameter that is used for the column (if any).
14137                  *
14138                  * The functions defined take two parameters:
14139                  *
14140                  * 1. `{object}` DataTables settings object: see
14141                  *    {@link DataTable.models.oSettings}
14142                  * 2. `{int}` Target column index
14143                  *
14144                  * Each function is expected to return an array:
14145                  *
14146                  * * `{array}` Data for the column to be ordering upon
14147                  *
14148                  *  @type array
14149                  *
14150                  *  @example
14151                  *    // Ordering using `input` node values
14152                  *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
14153                  *    {
14154                  *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
14155                  *        return $('input', td).val();
14156                  *      } );
14157                  *    }
14158                  */
14159                 order: {},
14160         
14161         
14162                 /**
14163                  * Type based plug-ins.
14164                  *
14165                  * Each column in DataTables has a type assigned to it, either by automatic
14166                  * detection or by direct assignment using the `type` option for the column.
14167                  * The type of a column will effect how it is ordering and search (plug-ins
14168                  * can also make use of the column type if required).
14169                  *
14170                  * @namespace
14171                  */
14172                 type: {
14173                         /**
14174                          * Type detection functions.
14175                          *
14176                          * The functions defined in this object are used to automatically detect
14177                          * a column's type, making initialisation of DataTables super easy, even
14178                          * when complex data is in the table.
14179                          *
14180                          * The functions defined take two parameters:
14181                          *
14182                      *  1. `{*}` Data from the column cell to be analysed
14183                      *  2. `{settings}` DataTables settings object. This can be used to
14184                      *     perform context specific type detection - for example detection
14185                      *     based on language settings such as using a comma for a decimal
14186                      *     place. Generally speaking the options from the settings will not
14187                      *     be required
14188                          *
14189                          * Each function is expected to return:
14190                          *
14191                          * * `{string|null}` Data type detected, or null if unknown (and thus
14192                          *   pass it on to the other type detection functions.
14193                          *
14194                          *  @type array
14195                          *
14196                          *  @example
14197                          *    // Currency type detection plug-in:
14198                          *    $.fn.dataTable.ext.type.detect.push(
14199                          *      function ( data, settings ) {
14200                          *        // Check the numeric part
14201                          *        if ( ! $.isNumeric( data.substring(1) ) ) {
14202                          *          return null;
14203                          *        }
14204                          *
14205                          *        // Check prefixed by currency
14206                          *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
14207                          *          return 'currency';
14208                          *        }
14209                          *        return null;
14210                          *      }
14211                          *    );
14212                          */
14213                         detect: [],
14214         
14215         
14216                         /**
14217                          * Type based search formatting.
14218                          *
14219                          * The type based searching functions can be used to pre-format the
14220                          * data to be search on. For example, it can be used to strip HTML
14221                          * tags or to de-format telephone numbers for numeric only searching.
14222                          *
14223                          * Note that is a search is not defined for a column of a given type,
14224                          * no search formatting will be performed.
14225                          * 
14226                          * Pre-processing of searching data plug-ins - When you assign the sType
14227                          * for a column (or have it automatically detected for you by DataTables
14228                          * or a type detection plug-in), you will typically be using this for
14229                          * custom sorting, but it can also be used to provide custom searching
14230                          * by allowing you to pre-processing the data and returning the data in
14231                          * the format that should be searched upon. This is done by adding
14232                          * functions this object with a parameter name which matches the sType
14233                          * for that target column. This is the corollary of <i>afnSortData</i>
14234                          * for searching data.
14235                          *
14236                          * The functions defined take a single parameter:
14237                          *
14238                      *  1. `{*}` Data from the column cell to be prepared for searching
14239                          *
14240                          * Each function is expected to return:
14241                          *
14242                          * * `{string|null}` Formatted string that will be used for the searching.
14243                          *
14244                          *  @type object
14245                          *  @default {}
14246                          *
14247                          *  @example
14248                          *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
14249                          *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
14250                          *    }
14251                          */
14252                         search: {},
14253         
14254         
14255                         /**
14256                          * Type based ordering.
14257                          *
14258                          * The column type tells DataTables what ordering to apply to the table
14259                          * when a column is sorted upon. The order for each type that is defined,
14260                          * is defined by the functions available in this object.
14261                          *
14262                          * Each ordering option can be described by three properties added to
14263                          * this object:
14264                          *
14265                          * * `{type}-pre` - Pre-formatting function
14266                          * * `{type}-asc` - Ascending order function
14267                          * * `{type}-desc` - Descending order function
14268                          *
14269                          * All three can be used together, only `{type}-pre` or only
14270                          * `{type}-asc` and `{type}-desc` together. It is generally recommended
14271                          * that only `{type}-pre` is used, as this provides the optimal
14272                          * implementation in terms of speed, although the others are provided
14273                          * for compatibility with existing Javascript sort functions.
14274                          *
14275                          * `{type}-pre`: Functions defined take a single parameter:
14276                          *
14277                      *  1. `{*}` Data from the column cell to be prepared for ordering
14278                          *
14279                          * And return:
14280                          *
14281                          * * `{*}` Data to be sorted upon
14282                          *
14283                          * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
14284                          * functions, taking two parameters:
14285                          *
14286                      *  1. `{*}` Data to compare to the second parameter
14287                      *  2. `{*}` Data to compare to the first parameter
14288                          *
14289                          * And returning:
14290                          *
14291                          * * `{*}` Ordering match: <0 if first parameter should be sorted lower
14292                          *   than the second parameter, ===0 if the two parameters are equal and
14293                          *   >0 if the first parameter should be sorted height than the second
14294                          *   parameter.
14295                          * 
14296                          *  @type object
14297                          *  @default {}
14298                          *
14299                          *  @example
14300                          *    // Numeric ordering of formatted numbers with a pre-formatter
14301                          *    $.extend( $.fn.dataTable.ext.type.order, {
14302                          *      "string-pre": function(x) {
14303                          *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
14304                          *        return parseFloat( a );
14305                          *      }
14306                          *    } );
14307                          *
14308                          *  @example
14309                          *    // Case-sensitive string ordering, with no pre-formatting method
14310                          *    $.extend( $.fn.dataTable.ext.order, {
14311                          *      "string-case-asc": function(x,y) {
14312                          *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14313                          *      },
14314                          *      "string-case-desc": function(x,y) {
14315                          *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14316                          *      }
14317                          *    } );
14318                          */
14319                         order: {}
14320                 },
14321         
14322                 /**
14323                  * Unique DataTables instance counter
14324                  *
14325                  * @type int
14326                  * @private
14327                  */
14328                 _unique: 0,
14329         
14330         
14331                 //
14332                 // Depreciated
14333                 // The following properties are retained for backwards compatiblity only.
14334                 // The should not be used in new projects and will be removed in a future
14335                 // version
14336                 //
14337         
14338                 /**
14339                  * Version check function.
14340                  *  @type function
14341                  *  @depreciated Since 1.10
14342                  */
14343                 fnVersionCheck: DataTable.fnVersionCheck,
14344         
14345         
14346                 /**
14347                  * Index for what 'this' index API functions should use
14348                  *  @type int
14349                  *  @deprecated Since v1.10
14350                  */
14351                 iApiIndex: 0,
14352         
14353         
14354                 /**
14355                  * jQuery UI class container
14356                  *  @type object
14357                  *  @deprecated Since v1.10
14358                  */
14359                 oJUIClasses: {},
14360         
14361         
14362                 /**
14363                  * Software version
14364                  *  @type string
14365                  *  @deprecated Since v1.10
14366                  */
14367                 sVersion: DataTable.version
14368         };
14369         
14370         
14371         //
14372         // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
14373         //
14374         $.extend( _ext, {
14375                 afnFiltering: _ext.search,
14376                 aTypes:       _ext.type.detect,
14377                 ofnSearch:    _ext.type.search,
14378                 oSort:        _ext.type.order,
14379                 afnSortData:  _ext.order,
14380                 aoFeatures:   _ext.feature,
14381                 oApi:         _ext.internal,
14382                 oStdClasses:  _ext.classes,
14383                 oPagination:  _ext.pager
14384         } );
14385         
14386         
14387         $.extend( DataTable.ext.classes, {
14388                 "sTable": "dataTable",
14389                 "sNoFooter": "no-footer",
14390         
14391                 /* Paging buttons */
14392                 "sPageButton": "paginate_button",
14393                 "sPageButtonActive": "current",
14394                 "sPageButtonDisabled": "disabled",
14395         
14396                 /* Striping classes */
14397                 "sStripeOdd": "odd",
14398                 "sStripeEven": "even",
14399         
14400                 /* Empty row */
14401                 "sRowEmpty": "dataTables_empty",
14402         
14403                 /* Features */
14404                 "sWrapper": "dataTables_wrapper",
14405                 "sFilter": "dataTables_filter",
14406                 "sInfo": "dataTables_info",
14407                 "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
14408                 "sLength": "dataTables_length",
14409                 "sProcessing": "dataTables_processing",
14410         
14411                 /* Sorting */
14412                 "sSortAsc": "sorting_asc",
14413                 "sSortDesc": "sorting_desc",
14414                 "sSortable": "sorting", /* Sortable in both directions */
14415                 "sSortableAsc": "sorting_asc_disabled",
14416                 "sSortableDesc": "sorting_desc_disabled",
14417                 "sSortableNone": "sorting_disabled",
14418                 "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
14419         
14420                 /* Filtering */
14421                 "sFilterInput": "",
14422         
14423                 /* Page length */
14424                 "sLengthSelect": "",
14425         
14426                 /* Scrolling */
14427                 "sScrollWrapper": "dataTables_scroll",
14428                 "sScrollHead": "dataTables_scrollHead",
14429                 "sScrollHeadInner": "dataTables_scrollHeadInner",
14430                 "sScrollBody": "dataTables_scrollBody",
14431                 "sScrollFoot": "dataTables_scrollFoot",
14432                 "sScrollFootInner": "dataTables_scrollFootInner",
14433         
14434                 /* Misc */
14435                 "sHeaderTH": "",
14436                 "sFooterTH": "",
14437         
14438                 // Deprecated
14439                 "sSortJUIAsc": "",
14440                 "sSortJUIDesc": "",
14441                 "sSortJUI": "",
14442                 "sSortJUIAscAllowed": "",
14443                 "sSortJUIDescAllowed": "",
14444                 "sSortJUIWrapper": "",
14445                 "sSortIcon": "",
14446                 "sJUIHeader": "",
14447                 "sJUIFooter": ""
14448         } );
14449         
14450         
14451         (function() {
14452         
14453         // Reused strings for better compression. Closure compiler appears to have a
14454         // weird edge case where it is trying to expand strings rather than use the
14455         // variable version. This results in about 200 bytes being added, for very
14456         // little preference benefit since it this run on script load only.
14457         var _empty = '';
14458         _empty = '';
14459         
14460         var _stateDefault = _empty + 'ui-state-default';
14461         var _sortIcon     = _empty + 'css_right ui-icon ui-icon-';
14462         var _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix';
14463         
14464         $.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, {
14465                 /* Full numbers paging buttons */
14466                 "sPageButton":         "fg-button ui-button "+_stateDefault,
14467                 "sPageButtonActive":   "ui-state-disabled",
14468                 "sPageButtonDisabled": "ui-state-disabled",
14469         
14470                 /* Features */
14471                 "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
14472                         "ui-buttonset-multi paging_", /* Note that the type is postfixed */
14473         
14474                 /* Sorting */
14475                 "sSortAsc":            _stateDefault+" sorting_asc",
14476                 "sSortDesc":           _stateDefault+" sorting_desc",
14477                 "sSortable":           _stateDefault+" sorting",
14478                 "sSortableAsc":        _stateDefault+" sorting_asc_disabled",
14479                 "sSortableDesc":       _stateDefault+" sorting_desc_disabled",
14480                 "sSortableNone":       _stateDefault+" sorting_disabled",
14481                 "sSortJUIAsc":         _sortIcon+"triangle-1-n",
14482                 "sSortJUIDesc":        _sortIcon+"triangle-1-s",
14483                 "sSortJUI":            _sortIcon+"carat-2-n-s",
14484                 "sSortJUIAscAllowed":  _sortIcon+"carat-1-n",
14485                 "sSortJUIDescAllowed": _sortIcon+"carat-1-s",
14486                 "sSortJUIWrapper":     "DataTables_sort_wrapper",
14487                 "sSortIcon":           "DataTables_sort_icon",
14488         
14489                 /* Scrolling */
14490                 "sScrollHead": "dataTables_scrollHead "+_stateDefault,
14491                 "sScrollFoot": "dataTables_scrollFoot "+_stateDefault,
14492         
14493                 /* Misc */
14494                 "sHeaderTH":  _stateDefault,
14495                 "sFooterTH":  _stateDefault,
14496                 "sJUIHeader": _headerFooter+" ui-corner-tl ui-corner-tr",
14497                 "sJUIFooter": _headerFooter+" ui-corner-bl ui-corner-br"
14498         } );
14499         
14500         }());
14501         
14502         
14503         
14504         var extPagination = DataTable.ext.pager;
14505         
14506         function _numbers ( page, pages ) {
14507                 var
14508                         numbers = [],
14509                         buttons = extPagination.numbers_length,
14510                         half = Math.floor( buttons / 2 ),
14511                         i = 1;
14512         
14513                 if ( pages <= buttons ) {
14514                         numbers = _range( 0, pages );
14515                 }
14516                 else if ( page <= half ) {
14517                         numbers = _range( 0, buttons-2 );
14518                         numbers.push( 'ellipsis' );
14519                         numbers.push( pages-1 );
14520                 }
14521                 else if ( page >= pages - 1 - half ) {
14522                         numbers = _range( pages-(buttons-2), pages );
14523                         numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
14524                         numbers.splice( 0, 0, 0 );
14525                 }
14526                 else {
14527                         numbers = _range( page-half+2, page+half-1 );
14528                         numbers.push( 'ellipsis' );
14529                         numbers.push( pages-1 );
14530                         numbers.splice( 0, 0, 'ellipsis' );
14531                         numbers.splice( 0, 0, 0 );
14532                 }
14533         
14534                 numbers.DT_el = 'span';
14535                 return numbers;
14536         }
14537         
14538         
14539         $.extend( extPagination, {
14540                 simple: function ( page, pages ) {
14541                         return [ 'previous', 'next' ];
14542                 },
14543         
14544                 full: function ( page, pages ) {
14545                         return [  'first', 'previous', 'next', 'last' ];
14546                 },
14547         
14548                 numbers: function ( page, pages ) {
14549                         return [ _numbers(page, pages) ];
14550                 },
14551         
14552                 simple_numbers: function ( page, pages ) {
14553                         return [ 'previous', _numbers(page, pages), 'next' ];
14554                 },
14555         
14556                 full_numbers: function ( page, pages ) {
14557                         return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
14558                 },
14559                 
14560                 first_last_numbers: function (page, pages) {
14561                         return ['first', _numbers(page, pages), 'last'];
14562                 },
14563         
14564                 // For testing and plug-ins to use
14565                 _numbers: _numbers,
14566         
14567                 // Number of number buttons (including ellipsis) to show. _Must be odd!_
14568                 numbers_length: 7
14569         } );
14570         
14571         
14572         $.extend( true, DataTable.ext.renderer, {
14573                 pageButton: {
14574                         _: function ( settings, host, idx, buttons, page, pages ) {
14575                                 var classes = settings.oClasses;
14576                                 var lang = settings.oLanguage.oPaginate;
14577                                 var aria = settings.oLanguage.oAria.paginate || {};
14578                                 var btnDisplay, btnClass, counter=0;
14579         
14580                                 var attach = function( container, buttons ) {
14581                                         var i, ien, node, button;
14582                                         var clickHandler = function ( e ) {
14583                                                 _fnPageChange( settings, e.data.action, true );
14584                                         };
14585         
14586                                         for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
14587                                                 button = buttons[i];
14588         
14589                                                 if ( $.isArray( button ) ) {
14590                                                         var inner = $( '<'+(button.DT_el || 'div')+'/>' )
14591                                                                 .appendTo( container );
14592                                                         attach( inner, button );
14593                                                 }
14594                                                 else {
14595                                                         btnDisplay = null;
14596                                                         btnClass = '';
14597         
14598                                                         switch ( button ) {
14599                                                                 case 'ellipsis':
14600                                                                         container.append('<span class="ellipsis">&#x2026;</span>');
14601                                                                         break;
14602         
14603                                                                 case 'first':
14604                                                                         btnDisplay = lang.sFirst;
14605                                                                         btnClass = button + (page > 0 ?
14606                                                                                 '' : ' '+classes.sPageButtonDisabled);
14607                                                                         break;
14608         
14609                                                                 case 'previous':
14610                                                                         btnDisplay = lang.sPrevious;
14611                                                                         btnClass = button + (page > 0 ?
14612                                                                                 '' : ' '+classes.sPageButtonDisabled);
14613                                                                         break;
14614         
14615                                                                 case 'next':
14616                                                                         btnDisplay = lang.sNext;
14617                                                                         btnClass = button + (page < pages-1 ?
14618                                                                                 '' : ' '+classes.sPageButtonDisabled);
14619                                                                         break;
14620         
14621                                                                 case 'last':
14622                                                                         btnDisplay = lang.sLast;
14623                                                                         btnClass = button + (page < pages-1 ?
14624                                                                                 '' : ' '+classes.sPageButtonDisabled);
14625                                                                         break;
14626         
14627                                                                 default:
14628                                                                         btnDisplay = button + 1;
14629                                                                         btnClass = page === button ?
14630                                                                                 classes.sPageButtonActive : '';
14631                                                                         break;
14632                                                         }
14633         
14634                                                         if ( btnDisplay !== null ) {
14635                                                                 node = $('<a>', {
14636                                                                                 'class': classes.sPageButton+' '+btnClass,
14637                                                                                 'aria-controls': settings.sTableId,
14638                                                                                 'aria-label': aria[ button ],
14639                                                                                 'data-dt-idx': counter,
14640                                                                                 'tabindex': settings.iTabIndex,
14641                                                                                 'id': idx === 0 && typeof button === 'string' ?
14642                                                                                         settings.sTableId +'_'+ button :
14643                                                                                         null
14644                                                                         } )
14645                                                                         .html( btnDisplay )
14646                                                                         .appendTo( container );
14647         
14648                                                                 _fnBindAction(
14649                                                                         node, {action: button}, clickHandler
14650                                                                 );
14651         
14652                                                                 counter++;
14653                                                         }
14654                                                 }
14655                                         }
14656                                 };
14657         
14658                                 // IE9 throws an 'unknown error' if document.activeElement is used
14659                                 // inside an iframe or frame. Try / catch the error. Not good for
14660                                 // accessibility, but neither are frames.
14661                                 var activeEl;
14662         
14663                                 try {
14664                                         // Because this approach is destroying and recreating the paging
14665                                         // elements, focus is lost on the select button which is bad for
14666                                         // accessibility. So we want to restore focus once the draw has
14667                                         // completed
14668                                         activeEl = $(host).find(document.activeElement).data('dt-idx');
14669                                 }
14670                                 catch (e) {}
14671         
14672                                 attach( $(host).empty(), buttons );
14673         
14674                                 if ( activeEl !== undefined ) {
14675                                         $(host).find( '[data-dt-idx='+activeEl+']' ).focus();
14676                                 }
14677                         }
14678                 }
14679         } );
14680         
14681         
14682         
14683         // Built in type detection. See model.ext.aTypes for information about
14684         // what is required from this methods.
14685         $.extend( DataTable.ext.type.detect, [
14686                 // Plain numbers - first since V8 detects some plain numbers as dates
14687                 // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14688                 function ( d, settings )
14689                 {
14690                         var decimal = settings.oLanguage.sDecimal;
14691                         return _isNumber( d, decimal ) ? 'num'+decimal : null;
14692                 },
14693         
14694                 // Dates (only those recognised by the browser's Date.parse)
14695                 function ( d, settings )
14696                 {
14697                         // V8 tries _very_ hard to make a string passed into `Date.parse()`
14698                         // valid, so we need to use a regex to restrict date formats. Use a
14699                         // plug-in for anything other than ISO8601 style strings
14700                         if ( d && !(d instanceof Date) && ! _re_date.test(d) ) {
14701                                 return null;
14702                         }
14703                         var parsed = Date.parse(d);
14704                         return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14705                 },
14706         
14707                 // Formatted numbers
14708                 function ( d, settings )
14709                 {
14710                         var decimal = settings.oLanguage.sDecimal;
14711                         return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14712                 },
14713         
14714                 // HTML numeric
14715                 function ( d, settings )
14716                 {
14717                         var decimal = settings.oLanguage.sDecimal;
14718                         return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14719                 },
14720         
14721                 // HTML numeric, formatted
14722                 function ( d, settings )
14723                 {
14724                         var decimal = settings.oLanguage.sDecimal;
14725                         return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14726                 },
14727         
14728                 // HTML (this is strict checking - there must be html)
14729                 function ( d, settings )
14730                 {
14731                         return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14732                                 'html' : null;
14733                 }
14734         ] );
14735         
14736         
14737         
14738         // Filter formatting functions. See model.ext.ofnSearch for information about
14739         // what is required from these methods.
14740         // 
14741         // Note that additional search methods are added for the html numbers and
14742         // html formatted numbers by `_addNumericSort()` when we know what the decimal
14743         // place is
14744         
14745         
14746         $.extend( DataTable.ext.type.search, {
14747                 html: function ( data ) {
14748                         return _empty(data) ?
14749                                 data :
14750                                 typeof data === 'string' ?
14751                                         data
14752                                                 .replace( _re_new_lines, " " )
14753                                                 .replace( _re_html, "" ) :
14754                                         '';
14755                 },
14756         
14757                 string: function ( data ) {
14758                         return _empty(data) ?
14759                                 data :
14760                                 typeof data === 'string' ?
14761                                         data.replace( _re_new_lines, " " ) :
14762                                         data;
14763                 }
14764         } );
14765         
14766         
14767         
14768         var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
14769                 if ( d !== 0 && (!d || d === '-') ) {
14770                         return -Infinity;
14771                 }
14772         
14773                 // If a decimal place other than `.` is used, it needs to be given to the
14774                 // function so we can detect it and replace with a `.` which is the only
14775                 // decimal place Javascript recognises - it is not locale aware.
14776                 if ( decimalPlace ) {
14777                         d = _numToDecimal( d, decimalPlace );
14778                 }
14779         
14780                 if ( d.replace ) {
14781                         if ( re1 ) {
14782                                 d = d.replace( re1, '' );
14783                         }
14784         
14785                         if ( re2 ) {
14786                                 d = d.replace( re2, '' );
14787                         }
14788                 }
14789         
14790                 return d * 1;
14791         };
14792         
14793         
14794         // Add the numeric 'deformatting' functions for sorting and search. This is done
14795         // in a function to provide an easy ability for the language options to add
14796         // additional methods if a non-period decimal place is used.
14797         function _addNumericSort ( decimalPlace ) {
14798                 $.each(
14799                         {
14800                                 // Plain numbers
14801                                 "num": function ( d ) {
14802                                         return __numericReplace( d, decimalPlace );
14803                                 },
14804         
14805                                 // Formatted numbers
14806                                 "num-fmt": function ( d ) {
14807                                         return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14808                                 },
14809         
14810                                 // HTML numeric
14811                                 "html-num": function ( d ) {
14812                                         return __numericReplace( d, decimalPlace, _re_html );
14813                                 },
14814         
14815                                 // HTML numeric, formatted
14816                                 "html-num-fmt": function ( d ) {
14817                                         return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14818                                 }
14819                         },
14820                         function ( key, fn ) {
14821                                 // Add the ordering method
14822                                 _ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14823         
14824                                 // For HTML types add a search formatter that will strip the HTML
14825                                 if ( key.match(/^html\-/) ) {
14826                                         _ext.type.search[ key+decimalPlace ] = _ext.type.search.html;
14827                                 }
14828                         }
14829                 );
14830         }
14831         
14832         
14833         // Default sort methods
14834         $.extend( _ext.type.order, {
14835                 // Dates
14836                 "date-pre": function ( d ) {
14837                         return Date.parse( d ) || -Infinity;
14838                 },
14839         
14840                 // html
14841                 "html-pre": function ( a ) {
14842                         return _empty(a) ?
14843                                 '' :
14844                                 a.replace ?
14845                                         a.replace( /<.*?>/g, "" ).toLowerCase() :
14846                                         a+'';
14847                 },
14848         
14849                 // string
14850                 "string-pre": function ( a ) {
14851                         // This is a little complex, but faster than always calling toString,
14852                         // http://jsperf.com/tostring-v-check
14853                         return _empty(a) ?
14854                                 '' :
14855                                 typeof a === 'string' ?
14856                                         a.toLowerCase() :
14857                                         ! a.toString ?
14858                                                 '' :
14859                                                 a.toString();
14860                 },
14861         
14862                 // string-asc and -desc are retained only for compatibility with the old
14863                 // sort methods
14864                 "string-asc": function ( x, y ) {
14865                         return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14866                 },
14867         
14868                 "string-desc": function ( x, y ) {
14869                         return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14870                 }
14871         } );
14872         
14873         
14874         // Numeric sorting types - order doesn't matter here
14875         _addNumericSort( '' );
14876         
14877         
14878         $.extend( true, DataTable.ext.renderer, {
14879                 header: {
14880                         _: function ( settings, cell, column, classes ) {
14881                                 // No additional mark-up required
14882                                 // Attach a sort listener to update on sort - note that using the
14883                                 // `DT` namespace will allow the event to be removed automatically
14884                                 // on destroy, while the `dt` namespaced event is the one we are
14885                                 // listening for
14886                                 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14887                                         if ( settings !== ctx ) { // need to check this this is the host
14888                                                 return;               // table, not a nested one
14889                                         }
14890         
14891                                         var colIdx = column.idx;
14892         
14893                                         cell
14894                                                 .removeClass(
14895                                                         column.sSortingClass +' '+
14896                                                         classes.sSortAsc +' '+
14897                                                         classes.sSortDesc
14898                                                 )
14899                                                 .addClass( columns[ colIdx ] == 'asc' ?
14900                                                         classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14901                                                                 classes.sSortDesc :
14902                                                                 column.sSortingClass
14903                                                 );
14904                                 } );
14905                         },
14906         
14907                         jqueryui: function ( settings, cell, column, classes ) {
14908                                 $('<div/>')
14909                                         .addClass( classes.sSortJUIWrapper )
14910                                         .append( cell.contents() )
14911                                         .append( $('<span/>')
14912                                                 .addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
14913                                         )
14914                                         .appendTo( cell );
14915         
14916                                 // Attach a sort listener to update on sort
14917                                 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14918                                         if ( settings !== ctx ) {
14919                                                 return;
14920                                         }
14921         
14922                                         var colIdx = column.idx;
14923         
14924                                         cell
14925                                                 .removeClass( classes.sSortAsc +" "+classes.sSortDesc )
14926                                                 .addClass( columns[ colIdx ] == 'asc' ?
14927                                                         classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14928                                                                 classes.sSortDesc :
14929                                                                 column.sSortingClass
14930                                                 );
14931         
14932                                         cell
14933                                                 .find( 'span.'+classes.sSortIcon )
14934                                                 .removeClass(
14935                                                         classes.sSortJUIAsc +" "+
14936                                                         classes.sSortJUIDesc +" "+
14937                                                         classes.sSortJUI +" "+
14938                                                         classes.sSortJUIAscAllowed +" "+
14939                                                         classes.sSortJUIDescAllowed
14940                                                 )
14941                                                 .addClass( columns[ colIdx ] == 'asc' ?
14942                                                         classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14943                                                                 classes.sSortJUIDesc :
14944                                                                 column.sSortingClassJUI
14945                                                 );
14946                                 } );
14947                         }
14948                 }
14949         } );
14950         
14951         /*
14952          * Public helper functions. These aren't used internally by DataTables, or
14953          * called by any of the options passed into DataTables, but they can be used
14954          * externally by developers working with DataTables. They are helper functions
14955          * to make working with DataTables a little bit easier.
14956          */
14957         
14958         var __htmlEscapeEntities = function ( d ) {
14959                 return typeof d === 'string' ?
14960                         d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') :
14961                         d;
14962         };
14963         
14964         /**
14965          * Helpers for `columns.render`.
14966          *
14967          * The options defined here can be used with the `columns.render` initialisation
14968          * option to provide a display renderer. The following functions are defined:
14969          *
14970          * * `number` - Will format numeric data (defined by `columns.data`) for
14971          *   display, retaining the original unformatted data for sorting and filtering.
14972          *   It takes 5 parameters:
14973          *   * `string` - Thousands grouping separator
14974          *   * `string` - Decimal point indicator
14975          *   * `integer` - Number of decimal points to show
14976          *   * `string` (optional) - Prefix.
14977          *   * `string` (optional) - Postfix (/suffix).
14978          * * `text` - Escape HTML to help prevent XSS attacks. It has no optional
14979          *   parameters.
14980          *
14981          * @example
14982          *   // Column definition using the number renderer
14983          *   {
14984          *     data: "salary",
14985          *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14986          *   }
14987          *
14988          * @namespace
14989          */
14990         DataTable.render = {
14991                 number: function ( thousands, decimal, precision, prefix, postfix ) {
14992                         return {
14993                                 display: function ( d ) {
14994                                         if ( typeof d !== 'number' && typeof d !== 'string' ) {
14995                                                 return d;
14996                                         }
14997         
14998                                         var negative = d < 0 ? '-' : '';
14999                                         var flo = parseFloat( d );
15000         
15001                                         // If NaN then there isn't much formatting that we can do - just
15002                                         // return immediately, escaping any HTML (this was supposed to
15003                                         // be a number after all)
15004                                         if ( isNaN( flo ) ) {
15005                                                 return __htmlEscapeEntities( d );
15006                                         }
15007         
15008                                         flo = flo.toFixed( precision );
15009                                         d = Math.abs( flo );
15010         
15011                                         var intPart = parseInt( d, 10 );
15012                                         var floatPart = precision ?
15013                                                 decimal+(d - intPart).toFixed( precision ).substring( 2 ):
15014                                                 '';
15015         
15016                                         return negative + (prefix||'') +
15017                                                 intPart.toString().replace(
15018                                                         /\B(?=(\d{3})+(?!\d))/g, thousands
15019                                                 ) +
15020                                                 floatPart +
15021                                                 (postfix||'');
15022                                 }
15023                         };
15024                 },
15025         
15026                 text: function () {
15027                         return {
15028                                 display: __htmlEscapeEntities
15029                         };
15030                 }
15031         };
15032         
15033         
15034         /*
15035          * This is really a good bit rubbish this method of exposing the internal methods
15036          * publicly... - To be fixed in 2.0 using methods on the prototype
15037          */
15038         
15039         
15040         /**
15041          * Create a wrapper function for exporting an internal functions to an external API.
15042          *  @param {string} fn API function name
15043          *  @returns {function} wrapped function
15044          *  @memberof DataTable#internal
15045          */
15046         function _fnExternApiFunc (fn)
15047         {
15048                 return function() {
15049                         var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
15050                                 Array.prototype.slice.call(arguments)
15051                         );
15052                         return DataTable.ext.internal[fn].apply( this, args );
15053                 };
15054         }
15055         
15056         
15057         /**
15058          * Reference to internal functions for use by plug-in developers. Note that
15059          * these methods are references to internal functions and are considered to be
15060          * private. If you use these methods, be aware that they are liable to change
15061          * between versions.
15062          *  @namespace
15063          */
15064         $.extend( DataTable.ext.internal, {
15065                 _fnExternApiFunc: _fnExternApiFunc,
15066                 _fnBuildAjax: _fnBuildAjax,
15067                 _fnAjaxUpdate: _fnAjaxUpdate,
15068                 _fnAjaxParameters: _fnAjaxParameters,
15069                 _fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
15070                 _fnAjaxDataSrc: _fnAjaxDataSrc,
15071                 _fnAddColumn: _fnAddColumn,
15072                 _fnColumnOptions: _fnColumnOptions,
15073                 _fnAdjustColumnSizing: _fnAdjustColumnSizing,
15074                 _fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
15075                 _fnColumnIndexToVisible: _fnColumnIndexToVisible,
15076                 _fnVisbleColumns: _fnVisbleColumns,
15077                 _fnGetColumns: _fnGetColumns,
15078                 _fnColumnTypes: _fnColumnTypes,
15079                 _fnApplyColumnDefs: _fnApplyColumnDefs,
15080                 _fnHungarianMap: _fnHungarianMap,
15081                 _fnCamelToHungarian: _fnCamelToHungarian,
15082                 _fnLanguageCompat: _fnLanguageCompat,
15083                 _fnBrowserDetect: _fnBrowserDetect,
15084                 _fnAddData: _fnAddData,
15085                 _fnAddTr: _fnAddTr,
15086                 _fnNodeToDataIndex: _fnNodeToDataIndex,
15087                 _fnNodeToColumnIndex: _fnNodeToColumnIndex,
15088                 _fnGetCellData: _fnGetCellData,
15089                 _fnSetCellData: _fnSetCellData,
15090                 _fnSplitObjNotation: _fnSplitObjNotation,
15091                 _fnGetObjectDataFn: _fnGetObjectDataFn,
15092                 _fnSetObjectDataFn: _fnSetObjectDataFn,
15093                 _fnGetDataMaster: _fnGetDataMaster,
15094                 _fnClearTable: _fnClearTable,
15095                 _fnDeleteIndex: _fnDeleteIndex,
15096                 _fnInvalidate: _fnInvalidate,
15097                 _fnGetRowElements: _fnGetRowElements,
15098                 _fnCreateTr: _fnCreateTr,
15099                 _fnBuildHead: _fnBuildHead,
15100                 _fnDrawHead: _fnDrawHead,
15101                 _fnDraw: _fnDraw,
15102                 _fnReDraw: _fnReDraw,
15103                 _fnAddOptionsHtml: _fnAddOptionsHtml,
15104                 _fnDetectHeader: _fnDetectHeader,
15105                 _fnGetUniqueThs: _fnGetUniqueThs,
15106                 _fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
15107                 _fnFilterComplete: _fnFilterComplete,
15108                 _fnFilterCustom: _fnFilterCustom,
15109                 _fnFilterColumn: _fnFilterColumn,
15110                 _fnFilter: _fnFilter,
15111                 _fnFilterCreateSearch: _fnFilterCreateSearch,
15112                 _fnEscapeRegex: _fnEscapeRegex,
15113                 _fnFilterData: _fnFilterData,
15114                 _fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
15115                 _fnUpdateInfo: _fnUpdateInfo,
15116                 _fnInfoMacros: _fnInfoMacros,
15117                 _fnInitialise: _fnInitialise,
15118                 _fnInitComplete: _fnInitComplete,
15119                 _fnLengthChange: _fnLengthChange,
15120                 _fnFeatureHtmlLength: _fnFeatureHtmlLength,
15121                 _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
15122                 _fnPageChange: _fnPageChange,
15123                 _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
15124                 _fnProcessingDisplay: _fnProcessingDisplay,
15125                 _fnFeatureHtmlTable: _fnFeatureHtmlTable,
15126                 _fnScrollDraw: _fnScrollDraw,
15127                 _fnApplyToChildren: _fnApplyToChildren,
15128                 _fnCalculateColumnWidths: _fnCalculateColumnWidths,
15129                 _fnThrottle: _fnThrottle,
15130                 _fnConvertToWidth: _fnConvertToWidth,
15131                 _fnGetWidestNode: _fnGetWidestNode,
15132                 _fnGetMaxLenString: _fnGetMaxLenString,
15133                 _fnStringToCss: _fnStringToCss,
15134                 _fnSortFlatten: _fnSortFlatten,
15135                 _fnSort: _fnSort,
15136                 _fnSortAria: _fnSortAria,
15137                 _fnSortListener: _fnSortListener,
15138                 _fnSortAttachListener: _fnSortAttachListener,
15139                 _fnSortingClasses: _fnSortingClasses,
15140                 _fnSortData: _fnSortData,
15141                 _fnSaveState: _fnSaveState,
15142                 _fnLoadState: _fnLoadState,
15143                 _fnSettingsFromNode: _fnSettingsFromNode,
15144                 _fnLog: _fnLog,
15145                 _fnMap: _fnMap,
15146                 _fnBindAction: _fnBindAction,
15147                 _fnCallbackReg: _fnCallbackReg,
15148                 _fnCallbackFire: _fnCallbackFire,
15149                 _fnLengthOverflow: _fnLengthOverflow,
15150                 _fnRenderer: _fnRenderer,
15151                 _fnDataSource: _fnDataSource,
15152                 _fnRowAttributes: _fnRowAttributes,
15153                 _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
15154                                                 // in 1.10, so this dead-end function is
15155                                                 // added to prevent errors
15156         } );
15157         
15158
15159         // jQuery access
15160         $.fn.dataTable = DataTable;
15161
15162         // Provide access to the host jQuery object (circular reference)
15163         DataTable.$ = $;
15164
15165         // Legacy aliases
15166         $.fn.dataTableSettings = DataTable.settings;
15167         $.fn.dataTableExt = DataTable.ext;
15168
15169         // With a capital `D` we return a DataTables API instance rather than a
15170         // jQuery object
15171         $.fn.DataTable = function ( opts ) {
15172                 return $(this).dataTable( opts ).api();
15173         };
15174
15175         // All properties that are available to $.fn.dataTable should also be
15176         // available on $.fn.DataTable
15177         $.each( DataTable, function ( prop, val ) {
15178                 $.fn.DataTable[ prop ] = val;
15179         } );
15180
15181
15182         // Information about events fired by DataTables - for documentation.
15183         /**
15184          * Draw event, fired whenever the table is redrawn on the page, at the same
15185          * point as fnDrawCallback. This may be useful for binding events or
15186          * performing calculations when the table is altered at all.
15187          *  @name DataTable#draw.dt
15188          *  @event
15189          *  @param {event} e jQuery event object
15190          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15191          */
15192
15193         /**
15194          * Search event, fired when the searching applied to the table (using the
15195          * built-in global search, or column filters) is altered.
15196          *  @name DataTable#search.dt
15197          *  @event
15198          *  @param {event} e jQuery event object
15199          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15200          */
15201
15202         /**
15203          * Page change event, fired when the paging of the table is altered.
15204          *  @name DataTable#page.dt
15205          *  @event
15206          *  @param {event} e jQuery event object
15207          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15208          */
15209
15210         /**
15211          * Order event, fired when the ordering applied to the table is altered.
15212          *  @name DataTable#order.dt
15213          *  @event
15214          *  @param {event} e jQuery event object
15215          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15216          */
15217
15218         /**
15219          * DataTables initialisation complete event, fired when the table is fully
15220          * drawn, including Ajax data loaded, if Ajax data is required.
15221          *  @name DataTable#init.dt
15222          *  @event
15223          *  @param {event} e jQuery event object
15224          *  @param {object} oSettings DataTables settings object
15225          *  @param {object} json The JSON object request from the server - only
15226          *    present if client-side Ajax sourced data is used</li></ol>
15227          */
15228
15229         /**
15230          * State save event, fired when the table has changed state a new state save
15231          * is required. This event allows modification of the state saving object
15232          * prior to actually doing the save, including addition or other state
15233          * properties (for plug-ins) or modification of a DataTables core property.
15234          *  @name DataTable#stateSaveParams.dt
15235          *  @event
15236          *  @param {event} e jQuery event object
15237          *  @param {object} oSettings DataTables settings object
15238          *  @param {object} json The state information to be saved
15239          */
15240
15241         /**
15242          * State load event, fired when the table is loading state from the stored
15243          * data, but prior to the settings object being modified by the saved state
15244          * - allowing modification of the saved state is required or loading of
15245          * state for a plug-in.
15246          *  @name DataTable#stateLoadParams.dt
15247          *  @event
15248          *  @param {event} e jQuery event object
15249          *  @param {object} oSettings DataTables settings object
15250          *  @param {object} json The saved state information
15251          */
15252
15253         /**
15254          * State loaded event, fired when state has been loaded from stored data and
15255          * the settings object has been modified by the loaded data.
15256          *  @name DataTable#stateLoaded.dt
15257          *  @event
15258          *  @param {event} e jQuery event object
15259          *  @param {object} oSettings DataTables settings object
15260          *  @param {object} json The saved state information
15261          */
15262
15263         /**
15264          * Processing event, fired when DataTables is doing some kind of processing
15265          * (be it, order, searcg or anything else). It can be used to indicate to
15266          * the end user that there is something happening, or that something has
15267          * finished.
15268          *  @name DataTable#processing.dt
15269          *  @event
15270          *  @param {event} e jQuery event object
15271          *  @param {object} oSettings DataTables settings object
15272          *  @param {boolean} bShow Flag for if DataTables is doing processing or not
15273          */
15274
15275         /**
15276          * Ajax (XHR) event, fired whenever an Ajax request is completed from a
15277          * request to made to the server for new data. This event is called before
15278          * DataTables processed the returned data, so it can also be used to pre-
15279          * process the data returned from the server, if needed.
15280          *
15281          * Note that this trigger is called in `fnServerData`, if you override
15282          * `fnServerData` and which to use this event, you need to trigger it in you
15283          * success function.
15284          *  @name DataTable#xhr.dt
15285          *  @event
15286          *  @param {event} e jQuery event object
15287          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15288          *  @param {object} json JSON returned from the server
15289          *
15290          *  @example
15291          *     // Use a custom property returned from the server in another DOM element
15292          *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15293          *       $('#status').html( json.status );
15294          *     } );
15295          *
15296          *  @example
15297          *     // Pre-process the data returned from the server
15298          *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
15299          *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
15300          *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
15301          *       }
15302          *       // Note no return - manipulate the data directly in the JSON object.
15303          *     } );
15304          */
15305
15306         /**
15307          * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
15308          * or passing the bDestroy:true parameter in the initialisation object. This
15309          * can be used to remove bound events, added DOM nodes, etc.
15310          *  @name DataTable#destroy.dt
15311          *  @event
15312          *  @param {event} e jQuery event object
15313          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15314          */
15315
15316         /**
15317          * Page length change event, fired when number of records to show on each
15318          * page (the length) is changed.
15319          *  @name DataTable#length.dt
15320          *  @event
15321          *  @param {event} e jQuery event object
15322          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15323          *  @param {integer} len New length
15324          */
15325
15326         /**
15327          * Column sizing has changed.
15328          *  @name DataTable#column-sizing.dt
15329          *  @event
15330          *  @param {event} e jQuery event object
15331          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15332          */
15333
15334         /**
15335          * Column visibility has changed.
15336          *  @name DataTable#column-visibility.dt
15337          *  @event
15338          *  @param {event} e jQuery event object
15339          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
15340          *  @param {int} column Column index
15341          *  @param {bool} vis `false` if column now hidden, or `true` if visible
15342          */
15343
15344         return $.fn.dataTable;
15345 }));