CLIENT GUI Framework
[vnfsdk/refrepo.git] / openo-portal / portal-common / src / main / webapp / common / thirdparty / data-tables / jquery.dataTables.js
1 /*! DataTables 1.10.11\r
2  * ©2008-2015 SpryMedia Ltd - datatables.net/license\r
3  */\r
4 \r
5 /**\r
6  * @summary     DataTables\r
7  * @description Paginate, search and order HTML tables\r
8  * @version     1.10.11\r
9  * @file        jquery.dataTables.js\r
10  * @author      SpryMedia Ltd (www.sprymedia.co.uk)\r
11  * @contact     www.sprymedia.co.uk/contact\r
12  * @copyright   Copyright 2008-2015 SpryMedia Ltd.\r
13  *\r
14  * This source file is free software, available under the following license:\r
15  *   MIT license - http://datatables.net/license\r
16  *\r
17  * This source file is distributed in the hope that it will be useful, but\r
18  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
19  * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.\r
20  *\r
21  * For details please refer to: http://www.datatables.net\r
22  */\r
23 \r
24 /*jslint evil: true, undef: true, browser: true */\r
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*/\r
26 \r
27 (function( factory ) {\r
28         "use strict";\r
29 \r
30         if ( typeof define === 'function' && define.amd ) {\r
31                 // AMD\r
32                 define( ['jquery'], function ( $ ) {\r
33                         return factory( $, window, document );\r
34                 } );\r
35         }\r
36         else if ( typeof exports === 'object' ) {\r
37                 // CommonJS\r
38                 module.exports = function (root, $) {\r
39                         if ( ! root ) {\r
40                                 // CommonJS environments without a window global must pass a\r
41                                 // root. This will give an error otherwise\r
42                                 root = window;\r
43                         }\r
44 \r
45                         if ( ! $ ) {\r
46                                 $ = typeof window !== 'undefined' ? // jQuery's factory checks for a global window\r
47                                         require('jquery') :\r
48                                         require('jquery')( root );\r
49                         }\r
50 \r
51                         return factory( $, root, root.document );\r
52                 };\r
53         }\r
54         else {\r
55                 // Browser\r
56                 factory( jQuery, window, document );\r
57         }\r
58 }\r
59 (function( $, window, document, undefined ) {\r
60         "use strict";\r
61 \r
62         /**\r
63          * DataTables is a plug-in for the jQuery Javascript library. It is a highly\r
64          * flexible tool, based upon the foundations of progressive enhancement,\r
65          * which will add advanced interaction controls to any HTML table. For a\r
66          * full list of features please refer to\r
67          * [DataTables.net](href="http://datatables.net).\r
68          *\r
69          * Note that the `DataTable` object is not a global variable but is aliased\r
70          * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may\r
71          * be  accessed.\r
72          *\r
73          *  @class\r
74          *  @param {object} [init={}] Configuration object for DataTables. Options\r
75          *    are defined by {@link DataTable.defaults}\r
76          *  @requires jQuery 1.7+\r
77          *\r
78          *  @example\r
79          *    // Basic initialisation\r
80          *    $(document).ready( function {\r
81          *      $('#example').dataTable();\r
82          *    } );\r
83          *\r
84          *  @example\r
85          *    // Initialisation with configuration options - in this case, disable\r
86          *    // pagination and sorting.\r
87          *    $(document).ready( function {\r
88          *      $('#example').dataTable( {\r
89          *        "paginate": false,\r
90          *        "sort": false\r
91          *      } );\r
92          *    } );\r
93          */\r
94         var DataTable;\r
95 \r
96         \r
97         /*\r
98          * It is useful to have variables which are scoped locally so only the\r
99          * DataTables functions can access them and they don't leak into global space.\r
100          * At the same time these functions are often useful over multiple files in the\r
101          * core and API, so we list, or at least document, all variables which are used\r
102          * by DataTables as private variables here. This also ensures that there is no\r
103          * clashing of variable names and that they can easily referenced for reuse.\r
104          */\r
105         \r
106         \r
107         // Defined else where\r
108         //  _selector_run\r
109         //  _selector_opts\r
110         //  _selector_first\r
111         //  _selector_row_indexes\r
112         \r
113         var _ext; // DataTable.ext\r
114         var _Api; // DataTable.Api\r
115         var _api_register; // DataTable.Api.register\r
116         var _api_registerPlural; // DataTable.Api.registerPlural\r
117         \r
118         var _re_dic = {};\r
119         var _re_new_lines = /[\r\n]/g;\r
120         var _re_html = /<.*?>/g;\r
121         var _re_date_start = /^[\w\+\-]/;\r
122         var _re_date_end = /[\w\+\-]$/;\r
123         \r
124         // Escape regular expression special characters\r
125         var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );\r
126         \r
127         // http://en.wikipedia.org/wiki/Foreign_exchange_market\r
128         // - \u20BD - Russian ruble.\r
129         // - \u20a9 - South Korean Won\r
130         // - \u20BA - Turkish Lira\r
131         // - \u20B9 - Indian Rupee\r
132         // - R - Brazil (R$) and South Africa\r
133         // - fr - Swiss Franc\r
134         // - kr - Swedish krona, Norwegian krone and Danish krone\r
135         // - \u2009 is thin space and \u202F is narrow no-break space, both used in many\r
136         //   standards as thousands separators.\r
137         var _re_formatted_numeric = /[',$£€¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi;\r
138         \r
139         \r
140         var _empty = function ( d ) {\r
141                 return !d || d === true || d === '-' ? true : false;\r
142         };\r
143         \r
144         \r
145         var _intVal = function ( s ) {\r
146                 var integer = parseInt( s, 10 );\r
147                 return !isNaN(integer) && isFinite(s) ? integer : null;\r
148         };\r
149         \r
150         // Convert from a formatted number with characters other than `.` as the\r
151         // decimal place, to a Javascript number\r
152         var _numToDecimal = function ( num, decimalPoint ) {\r
153                 // Cache created regular expressions for speed as this function is called often\r
154                 if ( ! _re_dic[ decimalPoint ] ) {\r
155                         _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );\r
156                 }\r
157                 return typeof num === 'string' && decimalPoint !== '.' ?\r
158                         num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :\r
159                         num;\r
160         };\r
161         \r
162         \r
163         var _isNumber = function ( d, decimalPoint, formatted ) {\r
164                 var strType = typeof d === 'string';\r
165         \r
166                 // If empty return immediately so there must be a number if it is a\r
167                 // formatted string (this stops the string "k", or "kr", etc being detected\r
168                 // as a formatted number for currency\r
169                 if ( _empty( d ) ) {\r
170                         return true;\r
171                 }\r
172         \r
173                 if ( decimalPoint && strType ) {\r
174                         d = _numToDecimal( d, decimalPoint );\r
175                 }\r
176         \r
177                 if ( formatted && strType ) {\r
178                         d = d.replace( _re_formatted_numeric, '' );\r
179                 }\r
180         \r
181                 return !isNaN( parseFloat(d) ) && isFinite( d );\r
182         };\r
183         \r
184         \r
185         // A string without HTML in it can be considered to be HTML still\r
186         var _isHtml = function ( d ) {\r
187                 return _empty( d ) || typeof d === 'string';\r
188         };\r
189         \r
190         \r
191         var _htmlNumeric = function ( d, decimalPoint, formatted ) {\r
192                 if ( _empty( d ) ) {\r
193                         return true;\r
194                 }\r
195         \r
196                 var html = _isHtml( d );\r
197                 return ! html ?\r
198                         null :\r
199                         _isNumber( _stripHtml( d ), decimalPoint, formatted ) ?\r
200                                 true :\r
201                                 null;\r
202         };\r
203         \r
204         \r
205         var _pluck = function ( a, prop, prop2 ) {\r
206                 var out = [];\r
207                 var i=0, ien=a.length;\r
208         \r
209                 // Could have the test in the loop for slightly smaller code, but speed\r
210                 // is essential here\r
211                 if ( prop2 !== undefined ) {\r
212                         for ( ; i<ien ; i++ ) {\r
213                                 if ( a[i] && a[i][ prop ] ) {\r
214                                         out.push( a[i][ prop ][ prop2 ] );\r
215                                 }\r
216                         }\r
217                 }\r
218                 else {\r
219                         for ( ; i<ien ; i++ ) {\r
220                                 if ( a[i] ) {\r
221                                         out.push( a[i][ prop ] );\r
222                                 }\r
223                         }\r
224                 }\r
225         \r
226                 return out;\r
227         };\r
228         \r
229         \r
230         // Basically the same as _pluck, but rather than looping over `a` we use `order`\r
231         // as the indexes to pick from `a`\r
232         var _pluck_order = function ( a, order, prop, prop2 )\r
233         {\r
234                 var out = [];\r
235                 var i=0, ien=order.length;\r
236         \r
237                 // Could have the test in the loop for slightly smaller code, but speed\r
238                 // is essential here\r
239                 if ( prop2 !== undefined ) {\r
240                         for ( ; i<ien ; i++ ) {\r
241                                 if ( a[ order[i] ][ prop ] ) {\r
242                                         out.push( a[ order[i] ][ prop ][ prop2 ] );\r
243                                 }\r
244                         }\r
245                 }\r
246                 else {\r
247                         for ( ; i<ien ; i++ ) {\r
248                                 out.push( a[ order[i] ][ prop ] );\r
249                         }\r
250                 }\r
251         \r
252                 return out;\r
253         };\r
254         \r
255         \r
256         var _range = function ( len, start )\r
257         {\r
258                 var out = [];\r
259                 var end;\r
260         \r
261                 if ( start === undefined ) {\r
262                         start = 0;\r
263                         end = len;\r
264                 }\r
265                 else {\r
266                         end = start;\r
267                         start = len;\r
268                 }\r
269         \r
270                 for ( var i=start ; i<end ; i++ ) {\r
271                         out.push( i );\r
272                 }\r
273         \r
274                 return out;\r
275         };\r
276         \r
277         \r
278         var _removeEmpty = function ( a )\r
279         {\r
280                 var out = [];\r
281         \r
282                 for ( var i=0, ien=a.length ; i<ien ; i++ ) {\r
283                         if ( a[i] ) { // careful - will remove all falsy values!\r
284                                 out.push( a[i] );\r
285                         }\r
286                 }\r
287         \r
288                 return out;\r
289         };\r
290         \r
291         \r
292         var _stripHtml = function ( d ) {\r
293                 return d.replace( _re_html, '' );\r
294         };\r
295         \r
296         \r
297         /**\r
298          * Find the unique elements in a source array.\r
299          *\r
300          * @param  {array} src Source array\r
301          * @return {array} Array of unique items\r
302          * @ignore\r
303          */\r
304         var _unique = function ( src )\r
305         {\r
306                 // A faster unique method is to use object keys to identify used values,\r
307                 // but this doesn't work with arrays or objects, which we must also\r
308                 // consider. See jsperf.com/compare-array-unique-versions/4 for more\r
309                 // information.\r
310                 var\r
311                         out = [],\r
312                         val,\r
313                         i, ien=src.length,\r
314                         j, k=0;\r
315         \r
316                 again: for ( i=0 ; i<ien ; i++ ) {\r
317                         val = src[i];\r
318         \r
319                         for ( j=0 ; j<k ; j++ ) {\r
320                                 if ( out[j] === val ) {\r
321                                         continue again;\r
322                                 }\r
323                         }\r
324         \r
325                         out.push( val );\r
326                         k++;\r
327                 }\r
328         \r
329                 return out;\r
330         };\r
331         \r
332         \r
333         \r
334         /**\r
335          * Create a mapping object that allows camel case parameters to be looked up\r
336          * for their Hungarian counterparts. The mapping is stored in a private\r
337          * parameter called `_hungarianMap` which can be accessed on the source object.\r
338          *  @param {object} o\r
339          *  @memberof DataTable#oApi\r
340          */\r
341         function _fnHungarianMap ( o )\r
342         {\r
343                 var\r
344                         hungarian = 'a aa ai ao as b fn i m o s ',\r
345                         match,\r
346                         newKey,\r
347                         map = {};\r
348         \r
349                 $.each( o, function (key, val) {\r
350                         match = key.match(/^([^A-Z]+?)([A-Z])/);\r
351         \r
352                         if ( match && hungarian.indexOf(match[1]+' ') !== -1 )\r
353                         {\r
354                                 newKey = key.replace( match[0], match[2].toLowerCase() );\r
355                                 map[ newKey ] = key;\r
356         \r
357                                 if ( match[1] === 'o' )\r
358                                 {\r
359                                         _fnHungarianMap( o[key] );\r
360                                 }\r
361                         }\r
362                 } );\r
363         \r
364                 o._hungarianMap = map;\r
365         }\r
366         \r
367         \r
368         /**\r
369          * Convert from camel case parameters to Hungarian, based on a Hungarian map\r
370          * created by _fnHungarianMap.\r
371          *  @param {object} src The model object which holds all parameters that can be\r
372          *    mapped.\r
373          *  @param {object} user The object to convert from camel case to Hungarian.\r
374          *  @param {boolean} force When set to `true`, properties which already have a\r
375          *    Hungarian value in the `user` object will be overwritten. Otherwise they\r
376          *    won't be.\r
377          *  @memberof DataTable#oApi\r
378          */\r
379         function _fnCamelToHungarian ( src, user, force )\r
380         {\r
381                 if ( ! src._hungarianMap ) {\r
382                         _fnHungarianMap( src );\r
383                 }\r
384         \r
385                 var hungarianKey;\r
386         \r
387                 $.each( user, function (key, val) {\r
388                         hungarianKey = src._hungarianMap[ key ];\r
389         \r
390                         if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )\r
391                         {\r
392                                 // For objects, we need to buzz down into the object to copy parameters\r
393                                 if ( hungarianKey.charAt(0) === 'o' )\r
394                                 {\r
395                                         // Copy the camelCase options over to the hungarian\r
396                                         if ( ! user[ hungarianKey ] ) {\r
397                                                 user[ hungarianKey ] = {};\r
398                                         }\r
399                                         $.extend( true, user[hungarianKey], user[key] );\r
400         \r
401                                         _fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );\r
402                                 }\r
403                                 else {\r
404                                         user[hungarianKey] = user[ key ];\r
405                                 }\r
406                         }\r
407                 } );\r
408         }\r
409         \r
410         \r
411         /**\r
412          * Language compatibility - when certain options are given, and others aren't, we\r
413          * need to duplicate the values over, in order to provide backwards compatibility\r
414          * with older language files.\r
415          *  @param {object} oSettings dataTables settings object\r
416          *  @memberof DataTable#oApi\r
417          */\r
418         function _fnLanguageCompat( lang )\r
419         {\r
420                 var defaults = DataTable.defaults.oLanguage;\r
421                 var zeroRecords = lang.sZeroRecords;\r
422         \r
423                 /* Backwards compatibility - if there is no sEmptyTable given, then use the same as\r
424                  * sZeroRecords - assuming that is given.\r
425                  */\r
426                 if ( ! lang.sEmptyTable && zeroRecords &&\r
427                         defaults.sEmptyTable === "No data available in table" )\r
428                 {\r
429                         _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );\r
430                 }\r
431         \r
432                 /* Likewise with loading records */\r
433                 if ( ! lang.sLoadingRecords && zeroRecords &&\r
434                         defaults.sLoadingRecords === "Loading..." )\r
435                 {\r
436                         _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );\r
437                 }\r
438         \r
439                 // Old parameter name of the thousands separator mapped onto the new\r
440                 if ( lang.sInfoThousands ) {\r
441                         lang.sThousands = lang.sInfoThousands;\r
442                 }\r
443         \r
444                 var decimal = lang.sDecimal;\r
445                 if ( decimal ) {\r
446                         _addNumericSort( decimal );\r
447                 }\r
448         }\r
449         \r
450         \r
451         /**\r
452          * Map one parameter onto another\r
453          *  @param {object} o Object to map\r
454          *  @param {*} knew The new parameter name\r
455          *  @param {*} old The old parameter name\r
456          */\r
457         var _fnCompatMap = function ( o, knew, old ) {\r
458                 if ( o[ knew ] !== undefined ) {\r
459                         o[ old ] = o[ knew ];\r
460                 }\r
461         };\r
462         \r
463         \r
464         /**\r
465          * Provide backwards compatibility for the main DT options. Note that the new\r
466          * options are mapped onto the old parameters, so this is an external interface\r
467          * change only.\r
468          *  @param {object} init Object to map\r
469          */\r
470         function _fnCompatOpts ( init )\r
471         {\r
472                 _fnCompatMap( init, 'ordering',      'bSort' );\r
473                 _fnCompatMap( init, 'orderMulti',    'bSortMulti' );\r
474                 _fnCompatMap( init, 'orderClasses',  'bSortClasses' );\r
475                 _fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );\r
476                 _fnCompatMap( init, 'order',         'aaSorting' );\r
477                 _fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );\r
478                 _fnCompatMap( init, 'paging',        'bPaginate' );\r
479                 _fnCompatMap( init, 'pagingType',    'sPaginationType' );\r
480                 _fnCompatMap( init, 'pageLength',    'iDisplayLength' );\r
481                 _fnCompatMap( init, 'searching',     'bFilter' );\r
482         \r
483                 // Boolean initialisation of x-scrolling\r
484                 if ( typeof init.sScrollX === 'boolean' ) {\r
485                         init.sScrollX = init.sScrollX ? '100%' : '';\r
486                 }\r
487                 if ( typeof init.scrollX === 'boolean' ) {\r
488                         init.scrollX = init.scrollX ? '100%' : '';\r
489                 }\r
490         \r
491                 // Column search objects are in an array, so it needs to be converted\r
492                 // element by element\r
493                 var searchCols = init.aoSearchCols;\r
494         \r
495                 if ( searchCols ) {\r
496                         for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {\r
497                                 if ( searchCols[i] ) {\r
498                                         _fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );\r
499                                 }\r
500                         }\r
501                 }\r
502         }\r
503         \r
504         \r
505         /**\r
506          * Provide backwards compatibility for column options. Note that the new options\r
507          * are mapped onto the old parameters, so this is an external interface change\r
508          * only.\r
509          *  @param {object} init Object to map\r
510          */\r
511         function _fnCompatCols ( init )\r
512         {\r
513                 _fnCompatMap( init, 'orderable',     'bSortable' );\r
514                 _fnCompatMap( init, 'orderData',     'aDataSort' );\r
515                 _fnCompatMap( init, 'orderSequence', 'asSorting' );\r
516                 _fnCompatMap( init, 'orderDataType', 'sortDataType' );\r
517         \r
518                 // orderData can be given as an integer\r
519                 var dataSort = init.aDataSort;\r
520                 if ( dataSort && ! $.isArray( dataSort ) ) {\r
521                         init.aDataSort = [ dataSort ];\r
522                 }\r
523         }\r
524         \r
525         \r
526         /**\r
527          * Browser feature detection for capabilities, quirks\r
528          *  @param {object} settings dataTables settings object\r
529          *  @memberof DataTable#oApi\r
530          */\r
531         function _fnBrowserDetect( settings )\r
532         {\r
533                 // We don't need to do this every time DataTables is constructed, the values\r
534                 // calculated are specific to the browser and OS configuration which we\r
535                 // don't expect to change between initialisations\r
536                 if ( ! DataTable.__browser ) {\r
537                         var browser = {};\r
538                         DataTable.__browser = browser;\r
539         \r
540                         // Scrolling feature / quirks detection\r
541                         var n = $('<div/>')\r
542                                 .css( {\r
543                                         position: 'fixed',\r
544                                         top: 0,\r
545                                         left: 0,\r
546                                         height: 1,\r
547                                         width: 1,\r
548                                         overflow: 'hidden'\r
549                                 } )\r
550                                 .append(\r
551                                         $('<div/>')\r
552                                                 .css( {\r
553                                                         position: 'absolute',\r
554                                                         top: 1,\r
555                                                         left: 1,\r
556                                                         width: 100,\r
557                                                         overflow: 'scroll'\r
558                                                 } )\r
559                                                 .append(\r
560                                                         $('<div/>')\r
561                                                                 .css( {\r
562                                                                         width: '100%',\r
563                                                                         height: 10\r
564                                                                 } )\r
565                                                 )\r
566                                 )\r
567                                 .appendTo( 'body' );\r
568         \r
569                         var outer = n.children();\r
570                         var inner = outer.children();\r
571         \r
572                         // Numbers below, in order, are:\r
573                         // inner.offsetWidth, inner.clientWidth, outer.offsetWidth, outer.clientWidth\r
574                         //\r
575                         // IE6 XP:                           100 100 100  83\r
576                         // IE7 Vista:                        100 100 100  83\r
577                         // IE 8+ Windows:                     83  83 100  83\r
578                         // Evergreen Windows:                 83  83 100  83\r
579                         // Evergreen Mac with scrollbars:     85  85 100  85\r
580                         // Evergreen Mac without scrollbars: 100 100 100 100\r
581         \r
582                         // Get scrollbar width\r
583                         browser.barWidth = outer[0].offsetWidth - outer[0].clientWidth;\r
584         \r
585                         // IE6/7 will oversize a width 100% element inside a scrolling element, to\r
586                         // include the width of the scrollbar, while other browsers ensure the inner\r
587                         // element is contained without forcing scrolling\r
588                         browser.bScrollOversize = inner[0].offsetWidth === 100 && outer[0].clientWidth !== 100;\r
589         \r
590                         // In rtl text layout, some browsers (most, but not all) will place the\r
591                         // scrollbar on the left, rather than the right.\r
592                         browser.bScrollbarLeft = Math.round( inner.offset().left ) !== 1;\r
593         \r
594                         // IE8- don't provide height and width for getBoundingClientRect\r
595                         browser.bBounding = n[0].getBoundingClientRect().width ? true : false;\r
596         \r
597                         n.remove();\r
598                 }\r
599         \r
600                 $.extend( settings.oBrowser, DataTable.__browser );\r
601                 settings.oScroll.iBarWidth = DataTable.__browser.barWidth;\r
602         }\r
603         \r
604         \r
605         /**\r
606          * Array.prototype reduce[Right] method, used for browsers which don't support\r
607          * JS 1.6. Done this way to reduce code size, since we iterate either way\r
608          *  @param {object} settings dataTables settings object\r
609          *  @memberof DataTable#oApi\r
610          */\r
611         function _fnReduce ( that, fn, init, start, end, inc )\r
612         {\r
613                 var\r
614                         i = start,\r
615                         value,\r
616                         isSet = false;\r
617         \r
618                 if ( init !== undefined ) {\r
619                         value = init;\r
620                         isSet = true;\r
621                 }\r
622         \r
623                 while ( i !== end ) {\r
624                         if ( ! that.hasOwnProperty(i) ) {\r
625                                 continue;\r
626                         }\r
627         \r
628                         value = isSet ?\r
629                                 fn( value, that[i], i, that ) :\r
630                                 that[i];\r
631         \r
632                         isSet = true;\r
633                         i += inc;\r
634                 }\r
635         \r
636                 return value;\r
637         }\r
638         \r
639         /**\r
640          * Add a column to the list used for the table with default values\r
641          *  @param {object} oSettings dataTables settings object\r
642          *  @param {node} nTh The th element for this column\r
643          *  @memberof DataTable#oApi\r
644          */\r
645         function _fnAddColumn( oSettings, nTh )\r
646         {\r
647                 // Add column to aoColumns array\r
648                 var oDefaults = DataTable.defaults.column;\r
649                 var iCol = oSettings.aoColumns.length;\r
650                 var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {\r
651                         "nTh": nTh ? nTh : document.createElement('th'),\r
652                         "sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',\r
653                         "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],\r
654                         "mData": oDefaults.mData ? oDefaults.mData : iCol,\r
655                         idx: iCol\r
656                 } );\r
657                 oSettings.aoColumns.push( oCol );\r
658         \r
659                 // Add search object for column specific search. Note that the `searchCols[ iCol ]`\r
660                 // passed into extend can be undefined. This allows the user to give a default\r
661                 // with only some of the parameters defined, and also not give a default\r
662                 var searchCols = oSettings.aoPreSearchCols;\r
663                 searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );\r
664         \r
665                 // Use the default column options function to initialise classes etc\r
666                 _fnColumnOptions( oSettings, iCol, $(nTh).data() );\r
667         }\r
668         \r
669         \r
670         /**\r
671          * Apply options for a column\r
672          *  @param {object} oSettings dataTables settings object\r
673          *  @param {int} iCol column index to consider\r
674          *  @param {object} oOptions object with sType, bVisible and bSearchable etc\r
675          *  @memberof DataTable#oApi\r
676          */\r
677         function _fnColumnOptions( oSettings, iCol, oOptions )\r
678         {\r
679                 var oCol = oSettings.aoColumns[ iCol ];\r
680                 var oClasses = oSettings.oClasses;\r
681                 var th = $(oCol.nTh);\r
682         \r
683                 // Try to get width information from the DOM. We can't get it from CSS\r
684                 // as we'd need to parse the CSS stylesheet. `width` option can override\r
685                 if ( ! oCol.sWidthOrig ) {\r
686                         // Width attribute\r
687                         oCol.sWidthOrig = th.attr('width') || null;\r
688         \r
689                         // Style attribute\r
690                         var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);\r
691                         if ( t ) {\r
692                                 oCol.sWidthOrig = t[1];\r
693                         }\r
694                 }\r
695         \r
696                 /* User specified column options */\r
697                 if ( oOptions !== undefined && oOptions !== null )\r
698                 {\r
699                         // Backwards compatibility\r
700                         _fnCompatCols( oOptions );\r
701         \r
702                         // Map camel case parameters to their Hungarian counterparts\r
703                         _fnCamelToHungarian( DataTable.defaults.column, oOptions );\r
704         \r
705                         /* Backwards compatibility for mDataProp */\r
706                         if ( oOptions.mDataProp !== undefined && !oOptions.mData )\r
707                         {\r
708                                 oOptions.mData = oOptions.mDataProp;\r
709                         }\r
710         \r
711                         if ( oOptions.sType )\r
712                         {\r
713                                 oCol._sManualType = oOptions.sType;\r
714                         }\r
715         \r
716                         // `class` is a reserved word in Javascript, so we need to provide\r
717                         // the ability to use a valid name for the camel case input\r
718                         if ( oOptions.className && ! oOptions.sClass )\r
719                         {\r
720                                 oOptions.sClass = oOptions.className;\r
721                         }\r
722         \r
723                         $.extend( oCol, oOptions );\r
724                         _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );\r
725         \r
726                         /* iDataSort to be applied (backwards compatibility), but aDataSort will take\r
727                          * priority if defined\r
728                          */\r
729                         if ( oOptions.iDataSort !== undefined )\r
730                         {\r
731                                 oCol.aDataSort = [ oOptions.iDataSort ];\r
732                         }\r
733                         _fnMap( oCol, oOptions, "aDataSort" );\r
734                 }\r
735         \r
736                 /* Cache the data get and set functions for speed */\r
737                 var mDataSrc = oCol.mData;\r
738                 var mData = _fnGetObjectDataFn( mDataSrc );\r
739                 var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;\r
740         \r
741                 var attrTest = function( src ) {\r
742                         return typeof src === 'string' && src.indexOf('@') !== -1;\r
743                 };\r
744                 oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (\r
745                         attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)\r
746                 );\r
747                 oCol._setter = null;\r
748         \r
749                 oCol.fnGetData = function (rowData, type, meta) {\r
750                         var innerData = mData( rowData, type, undefined, meta );\r
751         \r
752                         return mRender && type ?\r
753                                 mRender( innerData, type, rowData, meta ) :\r
754                                 innerData;\r
755                 };\r
756                 oCol.fnSetData = function ( rowData, val, meta ) {\r
757                         return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );\r
758                 };\r
759         \r
760                 // Indicate if DataTables should read DOM data as an object or array\r
761                 // Used in _fnGetRowElements\r
762                 if ( typeof mDataSrc !== 'number' ) {\r
763                         oSettings._rowReadObject = true;\r
764                 }\r
765         \r
766                 /* Feature sorting overrides column specific when off */\r
767                 if ( !oSettings.oFeatures.bSort )\r
768                 {\r
769                         oCol.bSortable = false;\r
770                         th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called\r
771                 }\r
772         \r
773                 /* Check that the class assignment is correct for sorting */\r
774                 var bAsc = $.inArray('asc', oCol.asSorting) !== -1;\r
775                 var bDesc = $.inArray('desc', oCol.asSorting) !== -1;\r
776                 if ( !oCol.bSortable || (!bAsc && !bDesc) )\r
777                 {\r
778                         oCol.sSortingClass = oClasses.sSortableNone;\r
779                         oCol.sSortingClassJUI = "";\r
780                 }\r
781                 else if ( bAsc && !bDesc )\r
782                 {\r
783                         oCol.sSortingClass = oClasses.sSortableAsc;\r
784                         oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;\r
785                 }\r
786                 else if ( !bAsc && bDesc )\r
787                 {\r
788                         oCol.sSortingClass = oClasses.sSortableDesc;\r
789                         oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;\r
790                 }\r
791                 else\r
792                 {\r
793                         oCol.sSortingClass = oClasses.sSortable;\r
794                         oCol.sSortingClassJUI = oClasses.sSortJUI;\r
795                 }\r
796         }\r
797         \r
798         \r
799         /**\r
800          * Adjust the table column widths for new data. Note: you would probably want to\r
801          * do a redraw after calling this function!\r
802          *  @param {object} settings dataTables settings object\r
803          *  @memberof DataTable#oApi\r
804          */\r
805         function _fnAdjustColumnSizing ( settings )\r
806         {\r
807                 /* Not interested in doing column width calculation if auto-width is disabled */\r
808                 if ( settings.oFeatures.bAutoWidth !== false )\r
809                 {\r
810                         var columns = settings.aoColumns;\r
811         \r
812                         _fnCalculateColumnWidths( settings );\r
813                         for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )\r
814                         {\r
815                                 columns[i].nTh.style.width = columns[i].sWidth;\r
816                         }\r
817                 }\r
818         \r
819                 var scroll = settings.oScroll;\r
820                 if ( scroll.sY !== '' || scroll.sX !== '')\r
821                 {\r
822                         _fnScrollDraw( settings );\r
823                 }\r
824         \r
825                 _fnCallbackFire( settings, null, 'column-sizing', [settings] );\r
826         }\r
827         \r
828         \r
829         /**\r
830          * Covert the index of a visible column to the index in the data array (take account\r
831          * of hidden columns)\r
832          *  @param {object} oSettings dataTables settings object\r
833          *  @param {int} iMatch Visible column index to lookup\r
834          *  @returns {int} i the data index\r
835          *  @memberof DataTable#oApi\r
836          */\r
837         function _fnVisibleToColumnIndex( oSettings, iMatch )\r
838         {\r
839                 var aiVis = _fnGetColumns( oSettings, 'bVisible' );\r
840         \r
841                 return typeof aiVis[iMatch] === 'number' ?\r
842                         aiVis[iMatch] :\r
843                         null;\r
844         }\r
845         \r
846         \r
847         /**\r
848          * Covert the index of an index in the data array and convert it to the visible\r
849          *   column index (take account of hidden columns)\r
850          *  @param {int} iMatch Column index to lookup\r
851          *  @param {object} oSettings dataTables settings object\r
852          *  @returns {int} i the data index\r
853          *  @memberof DataTable#oApi\r
854          */\r
855         function _fnColumnIndexToVisible( oSettings, iMatch )\r
856         {\r
857                 var aiVis = _fnGetColumns( oSettings, 'bVisible' );\r
858                 var iPos = $.inArray( iMatch, aiVis );\r
859         \r
860                 return iPos !== -1 ? iPos : null;\r
861         }\r
862         \r
863         \r
864         /**\r
865          * Get the number of visible columns\r
866          *  @param {object} oSettings dataTables settings object\r
867          *  @returns {int} i the number of visible columns\r
868          *  @memberof DataTable#oApi\r
869          */\r
870         function _fnVisbleColumns( oSettings )\r
871         {\r
872                 return $( _pluck( oSettings.aoColumns, 'nTh' ) ).filter(':visible').length;\r
873         }\r
874         \r
875         \r
876         /**\r
877          * Get an array of column indexes that match a given property\r
878          *  @param {object} oSettings dataTables settings object\r
879          *  @param {string} sParam Parameter in aoColumns to look for - typically\r
880          *    bVisible or bSearchable\r
881          *  @returns {array} Array of indexes with matched properties\r
882          *  @memberof DataTable#oApi\r
883          */\r
884         function _fnGetColumns( oSettings, sParam )\r
885         {\r
886                 var a = [];\r
887         \r
888                 $.map( oSettings.aoColumns, function(val, i) {\r
889                         if ( val[sParam] ) {\r
890                                 a.push( i );\r
891                         }\r
892                 } );\r
893         \r
894                 return a;\r
895         }\r
896         \r
897         \r
898         /**\r
899          * Calculate the 'type' of a column\r
900          *  @param {object} settings dataTables settings object\r
901          *  @memberof DataTable#oApi\r
902          */\r
903         function _fnColumnTypes ( settings )\r
904         {\r
905                 var columns = settings.aoColumns;\r
906                 var data = settings.aoData;\r
907                 var types = DataTable.ext.type.detect;\r
908                 var i, ien, j, jen, k, ken;\r
909                 var col, cell, detectedType, cache;\r
910         \r
911                 // For each column, spin over the \r
912                 for ( i=0, ien=columns.length ; i<ien ; i++ ) {\r
913                         col = columns[i];\r
914                         cache = [];\r
915         \r
916                         if ( ! col.sType && col._sManualType ) {\r
917                                 col.sType = col._sManualType;\r
918                         }\r
919                         else if ( ! col.sType ) {\r
920                                 for ( j=0, jen=types.length ; j<jen ; j++ ) {\r
921                                         for ( k=0, ken=data.length ; k<ken ; k++ ) {\r
922                                                 // Use a cache array so we only need to get the type data\r
923                                                 // from the formatter once (when using multiple detectors)\r
924                                                 if ( cache[k] === undefined ) {\r
925                                                         cache[k] = _fnGetCellData( settings, k, i, 'type' );\r
926                                                 }\r
927         \r
928                                                 detectedType = types[j]( cache[k], settings );\r
929         \r
930                                                 // If null, then this type can't apply to this column, so\r
931                                                 // rather than testing all cells, break out. There is an\r
932                                                 // exception for the last type which is `html`. We need to\r
933                                                 // scan all rows since it is possible to mix string and HTML\r
934                                                 // types\r
935                                                 if ( ! detectedType && j !== types.length-1 ) {\r
936                                                         break;\r
937                                                 }\r
938         \r
939                                                 // Only a single match is needed for html type since it is\r
940                                                 // bottom of the pile and very similar to string\r
941                                                 if ( detectedType === 'html' ) {\r
942                                                         break;\r
943                                                 }\r
944                                         }\r
945         \r
946                                         // Type is valid for all data points in the column - use this\r
947                                         // type\r
948                                         if ( detectedType ) {\r
949                                                 col.sType = detectedType;\r
950                                                 break;\r
951                                         }\r
952                                 }\r
953         \r
954                                 // Fall back - if no type was detected, always use string\r
955                                 if ( ! col.sType ) {\r
956                                         col.sType = 'string';\r
957                                 }\r
958                         }\r
959                 }\r
960         }\r
961         \r
962         \r
963         /**\r
964          * Take the column definitions and static columns arrays and calculate how\r
965          * they relate to column indexes. The callback function will then apply the\r
966          * definition found for a column to a suitable configuration object.\r
967          *  @param {object} oSettings dataTables settings object\r
968          *  @param {array} aoColDefs The aoColumnDefs array that is to be applied\r
969          *  @param {array} aoCols The aoColumns array that defines columns individually\r
970          *  @param {function} fn Callback function - takes two parameters, the calculated\r
971          *    column index and the definition for that column.\r
972          *  @memberof DataTable#oApi\r
973          */\r
974         function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )\r
975         {\r
976                 var i, iLen, j, jLen, k, kLen, def;\r
977                 var columns = oSettings.aoColumns;\r
978         \r
979                 // Column definitions with aTargets\r
980                 if ( aoColDefs )\r
981                 {\r
982                         /* Loop over the definitions array - loop in reverse so first instance has priority */\r
983                         for ( i=aoColDefs.length-1 ; i>=0 ; i-- )\r
984                         {\r
985                                 def = aoColDefs[i];\r
986         \r
987                                 /* Each definition can target multiple columns, as it is an array */\r
988                                 var aTargets = def.targets !== undefined ?\r
989                                         def.targets :\r
990                                         def.aTargets;\r
991         \r
992                                 if ( ! $.isArray( aTargets ) )\r
993                                 {\r
994                                         aTargets = [ aTargets ];\r
995                                 }\r
996         \r
997                                 for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )\r
998                                 {\r
999                                         if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )\r
1000                                         {\r
1001                                                 /* Add columns that we don't yet know about */\r
1002                                                 while( columns.length <= aTargets[j] )\r
1003                                                 {\r
1004                                                         _fnAddColumn( oSettings );\r
1005                                                 }\r
1006         \r
1007                                                 /* Integer, basic index */\r
1008                                                 fn( aTargets[j], def );\r
1009                                         }\r
1010                                         else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )\r
1011                                         {\r
1012                                                 /* Negative integer, right to left column counting */\r
1013                                                 fn( columns.length+aTargets[j], def );\r
1014                                         }\r
1015                                         else if ( typeof aTargets[j] === 'string' )\r
1016                                         {\r
1017                                                 /* Class name matching on TH element */\r
1018                                                 for ( k=0, kLen=columns.length ; k<kLen ; k++ )\r
1019                                                 {\r
1020                                                         if ( aTargets[j] == "_all" ||\r
1021                                                              $(columns[k].nTh).hasClass( aTargets[j] ) )\r
1022                                                         {\r
1023                                                                 fn( k, def );\r
1024                                                         }\r
1025                                                 }\r
1026                                         }\r
1027                                 }\r
1028                         }\r
1029                 }\r
1030         \r
1031                 // Statically defined columns array\r
1032                 if ( aoCols )\r
1033                 {\r
1034                         for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )\r
1035                         {\r
1036                                 fn( i, aoCols[i] );\r
1037                         }\r
1038                 }\r
1039         }\r
1040         \r
1041         /**\r
1042          * Add a data array to the table, creating DOM node etc. This is the parallel to\r
1043          * _fnGatherData, but for adding rows from a Javascript source, rather than a\r
1044          * DOM source.\r
1045          *  @param {object} oSettings dataTables settings object\r
1046          *  @param {array} aData data array to be added\r
1047          *  @param {node} [nTr] TR element to add to the table - optional. If not given,\r
1048          *    DataTables will create a row automatically\r
1049          *  @param {array} [anTds] Array of TD|TH elements for the row - must be given\r
1050          *    if nTr is.\r
1051          *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed\r
1052          *  @memberof DataTable#oApi\r
1053          */\r
1054         function _fnAddData ( oSettings, aDataIn, nTr, anTds )\r
1055         {\r
1056                 /* Create the object for storing information about this new row */\r
1057                 var iRow = oSettings.aoData.length;\r
1058                 var oData = $.extend( true, {}, DataTable.models.oRow, {\r
1059                         src: nTr ? 'dom' : 'data',\r
1060                         idx: iRow\r
1061                 } );\r
1062         \r
1063                 oData._aData = aDataIn;\r
1064                 oSettings.aoData.push( oData );\r
1065         \r
1066                 /* Create the cells */\r
1067                 var nTd, sThisType;\r
1068                 var columns = oSettings.aoColumns;\r
1069         \r
1070                 // Invalidate the column types as the new data needs to be revalidated\r
1071                 for ( var i=0, iLen=columns.length ; i<iLen ; i++ )\r
1072                 {\r
1073                         columns[i].sType = null;\r
1074                 }\r
1075         \r
1076                 /* Add to the display array */\r
1077                 oSettings.aiDisplayMaster.push( iRow );\r
1078         \r
1079                 var id = oSettings.rowIdFn( aDataIn );\r
1080                 if ( id !== undefined ) {\r
1081                         oSettings.aIds[ id ] = oData;\r
1082                 }\r
1083         \r
1084                 /* Create the DOM information, or register it if already present */\r
1085                 if ( nTr || ! oSettings.oFeatures.bDeferRender )\r
1086                 {\r
1087                         _fnCreateTr( oSettings, iRow, nTr, anTds );\r
1088                 }\r
1089         \r
1090                 return iRow;\r
1091         }\r
1092         \r
1093         \r
1094         /**\r
1095          * Add one or more TR elements to the table. Generally we'd expect to\r
1096          * use this for reading data from a DOM sourced table, but it could be\r
1097          * used for an TR element. Note that if a TR is given, it is used (i.e.\r
1098          * it is not cloned).\r
1099          *  @param {object} settings dataTables settings object\r
1100          *  @param {array|node|jQuery} trs The TR element(s) to add to the table\r
1101          *  @returns {array} Array of indexes for the added rows\r
1102          *  @memberof DataTable#oApi\r
1103          */\r
1104         function _fnAddTr( settings, trs )\r
1105         {\r
1106                 var row;\r
1107         \r
1108                 // Allow an individual node to be passed in\r
1109                 if ( ! (trs instanceof $) ) {\r
1110                         trs = $(trs);\r
1111                 }\r
1112         \r
1113                 return trs.map( function (i, el) {\r
1114                         row = _fnGetRowElements( settings, el );\r
1115                         return _fnAddData( settings, row.data, el, row.cells );\r
1116                 } );\r
1117         }\r
1118         \r
1119         \r
1120         /**\r
1121          * Take a TR element and convert it to an index in aoData\r
1122          *  @param {object} oSettings dataTables settings object\r
1123          *  @param {node} n the TR element to find\r
1124          *  @returns {int} index if the node is found, null if not\r
1125          *  @memberof DataTable#oApi\r
1126          */\r
1127         function _fnNodeToDataIndex( oSettings, n )\r
1128         {\r
1129                 return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;\r
1130         }\r
1131         \r
1132         \r
1133         /**\r
1134          * Take a TD element and convert it into a column data index (not the visible index)\r
1135          *  @param {object} oSettings dataTables settings object\r
1136          *  @param {int} iRow The row number the TD/TH can be found in\r
1137          *  @param {node} n The TD/TH element to find\r
1138          *  @returns {int} index if the node is found, -1 if not\r
1139          *  @memberof DataTable#oApi\r
1140          */\r
1141         function _fnNodeToColumnIndex( oSettings, iRow, n )\r
1142         {\r
1143                 return $.inArray( n, oSettings.aoData[ iRow ].anCells );\r
1144         }\r
1145         \r
1146         \r
1147         /**\r
1148          * Get the data for a given cell from the internal cache, taking into account data mapping\r
1149          *  @param {object} settings dataTables settings object\r
1150          *  @param {int} rowIdx aoData row id\r
1151          *  @param {int} colIdx Column index\r
1152          *  @param {string} type data get type ('display', 'type' 'filter' 'sort')\r
1153          *  @returns {*} Cell data\r
1154          *  @memberof DataTable#oApi\r
1155          */\r
1156         function _fnGetCellData( settings, rowIdx, colIdx, type )\r
1157         {\r
1158                 var draw           = settings.iDraw;\r
1159                 var col            = settings.aoColumns[colIdx];\r
1160                 var rowData        = settings.aoData[rowIdx]._aData;\r
1161                 var defaultContent = col.sDefaultContent;\r
1162                 var cellData       = col.fnGetData( rowData, type, {\r
1163                         settings: settings,\r
1164                         row:      rowIdx,\r
1165                         col:      colIdx\r
1166                 } );\r
1167         \r
1168                 if ( cellData === undefined ) {\r
1169                         if ( settings.iDrawError != draw && defaultContent === null ) {\r
1170                                 _fnLog( settings, 0, "Requested unknown parameter "+\r
1171                                         (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+\r
1172                                         " for row "+rowIdx+", column "+colIdx, 4 );\r
1173                                 settings.iDrawError = draw;\r
1174                         }\r
1175                         return defaultContent;\r
1176                 }\r
1177         \r
1178                 // When the data source is null and a specific data type is requested (i.e.\r
1179                 // not the original data), we can use default column data\r
1180                 if ( (cellData === rowData || cellData === null) && defaultContent !== null && type !== undefined ) {\r
1181                         cellData = defaultContent;\r
1182                 }\r
1183                 else if ( typeof cellData === 'function' ) {\r
1184                         // If the data source is a function, then we run it and use the return,\r
1185                         // executing in the scope of the data object (for instances)\r
1186                         return cellData.call( rowData );\r
1187                 }\r
1188         \r
1189                 if ( cellData === null && type == 'display' ) {\r
1190                         return '';\r
1191                 }\r
1192                 return cellData;\r
1193         }\r
1194         \r
1195         \r
1196         /**\r
1197          * Set the value for a specific cell, into the internal data cache\r
1198          *  @param {object} settings dataTables settings object\r
1199          *  @param {int} rowIdx aoData row id\r
1200          *  @param {int} colIdx Column index\r
1201          *  @param {*} val Value to set\r
1202          *  @memberof DataTable#oApi\r
1203          */\r
1204         function _fnSetCellData( settings, rowIdx, colIdx, val )\r
1205         {\r
1206                 var col     = settings.aoColumns[colIdx];\r
1207                 var rowData = settings.aoData[rowIdx]._aData;\r
1208         \r
1209                 col.fnSetData( rowData, val, {\r
1210                         settings: settings,\r
1211                         row:      rowIdx,\r
1212                         col:      colIdx\r
1213                 }  );\r
1214         }\r
1215         \r
1216         \r
1217         // Private variable that is used to match action syntax in the data property object\r
1218         var __reArray = /\[.*?\]$/;\r
1219         var __reFn = /\(\)$/;\r
1220         \r
1221         /**\r
1222          * Split string on periods, taking into account escaped periods\r
1223          * @param  {string} str String to split\r
1224          * @return {array} Split string\r
1225          */\r
1226         function _fnSplitObjNotation( str )\r
1227         {\r
1228                 return $.map( str.match(/(\\.|[^\.])+/g) || [''], function ( s ) {\r
1229                         return s.replace(/\\./g, '.');\r
1230                 } );\r
1231         }\r
1232         \r
1233         \r
1234         /**\r
1235          * Return a function that can be used to get data from a source object, taking\r
1236          * into account the ability to use nested objects as a source\r
1237          *  @param {string|int|function} mSource The data source for the object\r
1238          *  @returns {function} Data get function\r
1239          *  @memberof DataTable#oApi\r
1240          */\r
1241         function _fnGetObjectDataFn( mSource )\r
1242         {\r
1243                 if ( $.isPlainObject( mSource ) )\r
1244                 {\r
1245                         /* Build an object of get functions, and wrap them in a single call */\r
1246                         var o = {};\r
1247                         $.each( mSource, function (key, val) {\r
1248                                 if ( val ) {\r
1249                                         o[key] = _fnGetObjectDataFn( val );\r
1250                                 }\r
1251                         } );\r
1252         \r
1253                         return function (data, type, row, meta) {\r
1254                                 var t = o[type] || o._;\r
1255                                 return t !== undefined ?\r
1256                                         t(data, type, row, meta) :\r
1257                                         data;\r
1258                         };\r
1259                 }\r
1260                 else if ( mSource === null )\r
1261                 {\r
1262                         /* Give an empty string for rendering / sorting etc */\r
1263                         return function (data) { // type, row and meta also passed, but not used\r
1264                                 return data;\r
1265                         };\r
1266                 }\r
1267                 else if ( typeof mSource === 'function' )\r
1268                 {\r
1269                         return function (data, type, row, meta) {\r
1270                                 return mSource( data, type, row, meta );\r
1271                         };\r
1272                 }\r
1273                 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||\r
1274                               mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )\r
1275                 {\r
1276                         /* If there is a . in the source string then the data source is in a\r
1277                          * nested object so we loop over the data for each level to get the next\r
1278                          * level down. On each loop we test for undefined, and if found immediately\r
1279                          * return. This allows entire objects to be missing and sDefaultContent to\r
1280                          * be used if defined, rather than throwing an error\r
1281                          */\r
1282                         var fetchData = function (data, type, src) {\r
1283                                 var arrayNotation, funcNotation, out, innerSrc;\r
1284         \r
1285                                 if ( src !== "" )\r
1286                                 {\r
1287                                         var a = _fnSplitObjNotation( src );\r
1288         \r
1289                                         for ( var i=0, iLen=a.length ; i<iLen ; i++ )\r
1290                                         {\r
1291                                                 // Check if we are dealing with special notation\r
1292                                                 arrayNotation = a[i].match(__reArray);\r
1293                                                 funcNotation = a[i].match(__reFn);\r
1294         \r
1295                                                 if ( arrayNotation )\r
1296                                                 {\r
1297                                                         // Array notation\r
1298                                                         a[i] = a[i].replace(__reArray, '');\r
1299         \r
1300                                                         // Condition allows simply [] to be passed in\r
1301                                                         if ( a[i] !== "" ) {\r
1302                                                                 data = data[ a[i] ];\r
1303                                                         }\r
1304                                                         out = [];\r
1305         \r
1306                                                         // Get the remainder of the nested object to get\r
1307                                                         a.splice( 0, i+1 );\r
1308                                                         innerSrc = a.join('.');\r
1309         \r
1310                                                         // Traverse each entry in the array getting the properties requested\r
1311                                                         if ( $.isArray( data ) ) {\r
1312                                                                 for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {\r
1313                                                                         out.push( fetchData( data[j], type, innerSrc ) );\r
1314                                                                 }\r
1315                                                         }\r
1316         \r
1317                                                         // If a string is given in between the array notation indicators, that\r
1318                                                         // is used to join the strings together, otherwise an array is returned\r
1319                                                         var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);\r
1320                                                         data = (join==="") ? out : out.join(join);\r
1321         \r
1322                                                         // The inner call to fetchData has already traversed through the remainder\r
1323                                                         // of the source requested, so we exit from the loop\r
1324                                                         break;\r
1325                                                 }\r
1326                                                 else if ( funcNotation )\r
1327                                                 {\r
1328                                                         // Function call\r
1329                                                         a[i] = a[i].replace(__reFn, '');\r
1330                                                         data = data[ a[i] ]();\r
1331                                                         continue;\r
1332                                                 }\r
1333         \r
1334                                                 if ( data === null || data[ a[i] ] === undefined )\r
1335                                                 {\r
1336                                                         return undefined;\r
1337                                                 }\r
1338                                                 data = data[ a[i] ];\r
1339                                         }\r
1340                                 }\r
1341         \r
1342                                 return data;\r
1343                         };\r
1344         \r
1345                         return function (data, type) { // row and meta also passed, but not used\r
1346                                 return fetchData( data, type, mSource );\r
1347                         };\r
1348                 }\r
1349                 else\r
1350                 {\r
1351                         /* Array or flat object mapping */\r
1352                         return function (data, type) { // row and meta also passed, but not used\r
1353                                 return data[mSource];\r
1354                         };\r
1355                 }\r
1356         }\r
1357         \r
1358         \r
1359         /**\r
1360          * Return a function that can be used to set data from a source object, taking\r
1361          * into account the ability to use nested objects as a source\r
1362          *  @param {string|int|function} mSource The data source for the object\r
1363          *  @returns {function} Data set function\r
1364          *  @memberof DataTable#oApi\r
1365          */\r
1366         function _fnSetObjectDataFn( mSource )\r
1367         {\r
1368                 if ( $.isPlainObject( mSource ) )\r
1369                 {\r
1370                         /* Unlike get, only the underscore (global) option is used for for\r
1371                          * setting data since we don't know the type here. This is why an object\r
1372                          * option is not documented for `mData` (which is read/write), but it is\r
1373                          * for `mRender` which is read only.\r
1374                          */\r
1375                         return _fnSetObjectDataFn( mSource._ );\r
1376                 }\r
1377                 else if ( mSource === null )\r
1378                 {\r
1379                         /* Nothing to do when the data source is null */\r
1380                         return function () {};\r
1381                 }\r
1382                 else if ( typeof mSource === 'function' )\r
1383                 {\r
1384                         return function (data, val, meta) {\r
1385                                 mSource( data, 'set', val, meta );\r
1386                         };\r
1387                 }\r
1388                 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||\r
1389                               mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )\r
1390                 {\r
1391                         /* Like the get, we need to get data from a nested object */\r
1392                         var setData = function (data, val, src) {\r
1393                                 var a = _fnSplitObjNotation( src ), b;\r
1394                                 var aLast = a[a.length-1];\r
1395                                 var arrayNotation, funcNotation, o, innerSrc;\r
1396         \r
1397                                 for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )\r
1398                                 {\r
1399                                         // Check if we are dealing with an array notation request\r
1400                                         arrayNotation = a[i].match(__reArray);\r
1401                                         funcNotation = a[i].match(__reFn);\r
1402         \r
1403                                         if ( arrayNotation )\r
1404                                         {\r
1405                                                 a[i] = a[i].replace(__reArray, '');\r
1406                                                 data[ a[i] ] = [];\r
1407         \r
1408                                                 // Get the remainder of the nested object to set so we can recurse\r
1409                                                 b = a.slice();\r
1410                                                 b.splice( 0, i+1 );\r
1411                                                 innerSrc = b.join('.');\r
1412         \r
1413                                                 // Traverse each entry in the array setting the properties requested\r
1414                                                 if ( $.isArray( val ) )\r
1415                                                 {\r
1416                                                         for ( var j=0, jLen=val.length ; j<jLen ; j++ )\r
1417                                                         {\r
1418                                                                 o = {};\r
1419                                                                 setData( o, val[j], innerSrc );\r
1420                                                                 data[ a[i] ].push( o );\r
1421                                                         }\r
1422                                                 }\r
1423                                                 else\r
1424                                                 {\r
1425                                                         // We've been asked to save data to an array, but it\r
1426                                                         // isn't array data to be saved. Best that can be done\r
1427                                                         // is to just save the value.\r
1428                                                         data[ a[i] ] = val;\r
1429                                                 }\r
1430         \r
1431                                                 // The inner call to setData has already traversed through the remainder\r
1432                                                 // of the source and has set the data, thus we can exit here\r
1433                                                 return;\r
1434                                         }\r
1435                                         else if ( funcNotation )\r
1436                                         {\r
1437                                                 // Function call\r
1438                                                 a[i] = a[i].replace(__reFn, '');\r
1439                                                 data = data[ a[i] ]( val );\r
1440                                         }\r
1441         \r
1442                                         // If the nested object doesn't currently exist - since we are\r
1443                                         // trying to set the value - create it\r
1444                                         if ( data[ a[i] ] === null || data[ a[i] ] === undefined )\r
1445                                         {\r
1446                                                 data[ a[i] ] = {};\r
1447                                         }\r
1448                                         data = data[ a[i] ];\r
1449                                 }\r
1450         \r
1451                                 // Last item in the input - i.e, the actual set\r
1452                                 if ( aLast.match(__reFn ) )\r
1453                                 {\r
1454                                         // Function call\r
1455                                         data = data[ aLast.replace(__reFn, '') ]( val );\r
1456                                 }\r
1457                                 else\r
1458                                 {\r
1459                                         // If array notation is used, we just want to strip it and use the property name\r
1460                                         // and assign the value. If it isn't used, then we get the result we want anyway\r
1461                                         data[ aLast.replace(__reArray, '') ] = val;\r
1462                                 }\r
1463                         };\r
1464         \r
1465                         return function (data, val) { // meta is also passed in, but not used\r
1466                                 return setData( data, val, mSource );\r
1467                         };\r
1468                 }\r
1469                 else\r
1470                 {\r
1471                         /* Array or flat object mapping */\r
1472                         return function (data, val) { // meta is also passed in, but not used\r
1473                                 data[mSource] = val;\r
1474                         };\r
1475                 }\r
1476         }\r
1477         \r
1478         \r
1479         /**\r
1480          * Return an array with the full table data\r
1481          *  @param {object} oSettings dataTables settings object\r
1482          *  @returns array {array} aData Master data array\r
1483          *  @memberof DataTable#oApi\r
1484          */\r
1485         function _fnGetDataMaster ( settings )\r
1486         {\r
1487                 return _pluck( settings.aoData, '_aData' );\r
1488         }\r
1489         \r
1490         \r
1491         /**\r
1492          * Nuke the table\r
1493          *  @param {object} oSettings dataTables settings object\r
1494          *  @memberof DataTable#oApi\r
1495          */\r
1496         function _fnClearTable( settings )\r
1497         {\r
1498                 settings.aoData.length = 0;\r
1499                 settings.aiDisplayMaster.length = 0;\r
1500                 settings.aiDisplay.length = 0;\r
1501                 settings.aIds = {};\r
1502         }\r
1503         \r
1504         \r
1505          /**\r
1506          * Take an array of integers (index array) and remove a target integer (value - not\r
1507          * the key!)\r
1508          *  @param {array} a Index array to target\r
1509          *  @param {int} iTarget value to find\r
1510          *  @memberof DataTable#oApi\r
1511          */\r
1512         function _fnDeleteIndex( a, iTarget, splice )\r
1513         {\r
1514                 var iTargetIndex = -1;\r
1515         \r
1516                 for ( var i=0, iLen=a.length ; i<iLen ; i++ )\r
1517                 {\r
1518                         if ( a[i] == iTarget )\r
1519                         {\r
1520                                 iTargetIndex = i;\r
1521                         }\r
1522                         else if ( a[i] > iTarget )\r
1523                         {\r
1524                                 a[i]--;\r
1525                         }\r
1526                 }\r
1527         \r
1528                 if ( iTargetIndex != -1 && splice === undefined )\r
1529                 {\r
1530                         a.splice( iTargetIndex, 1 );\r
1531                 }\r
1532         }\r
1533         \r
1534         \r
1535         /**\r
1536          * Mark cached data as invalid such that a re-read of the data will occur when\r
1537          * the cached data is next requested. Also update from the data source object.\r
1538          *\r
1539          * @param {object} settings DataTables settings object\r
1540          * @param {int}    rowIdx   Row index to invalidate\r
1541          * @param {string} [src]    Source to invalidate from: undefined, 'auto', 'dom'\r
1542          *     or 'data'\r
1543          * @param {int}    [colIdx] Column index to invalidate. If undefined the whole\r
1544          *     row will be invalidated\r
1545          * @memberof DataTable#oApi\r
1546          *\r
1547          * @todo For the modularisation of v1.11 this will need to become a callback, so\r
1548          *   the sort and filter methods can subscribe to it. That will required\r
1549          *   initialisation options for sorting, which is why it is not already baked in\r
1550          */\r
1551         function _fnInvalidate( settings, rowIdx, src, colIdx )\r
1552         {\r
1553                 var row = settings.aoData[ rowIdx ];\r
1554                 var i, ien;\r
1555                 var cellWrite = function ( cell, col ) {\r
1556                         // This is very frustrating, but in IE if you just write directly\r
1557                         // to innerHTML, and elements that are overwritten are GC'ed,\r
1558                         // even if there is a reference to them elsewhere\r
1559                         while ( cell.childNodes.length ) {\r
1560                                 cell.removeChild( cell.firstChild );\r
1561                         }\r
1562         \r
1563                         cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' );\r
1564                 };\r
1565         \r
1566                 // Are we reading last data from DOM or the data object?\r
1567                 if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {\r
1568                         // Read the data from the DOM\r
1569                         row._aData = _fnGetRowElements(\r
1570                                         settings, row, colIdx, colIdx === undefined ? undefined : row._aData\r
1571                                 )\r
1572                                 .data;\r
1573                 }\r
1574                 else {\r
1575                         // Reading from data object, update the DOM\r
1576                         var cells = row.anCells;\r
1577         \r
1578                         if ( cells ) {\r
1579                                 if ( colIdx !== undefined ) {\r
1580                                         cellWrite( cells[colIdx], colIdx );\r
1581                                 }\r
1582                                 else {\r
1583                                         for ( i=0, ien=cells.length ; i<ien ; i++ ) {\r
1584                                                 cellWrite( cells[i], i );\r
1585                                         }\r
1586                                 }\r
1587                         }\r
1588                 }\r
1589         \r
1590                 // For both row and cell invalidation, the cached data for sorting and\r
1591                 // filtering is nulled out\r
1592                 row._aSortData = null;\r
1593                 row._aFilterData = null;\r
1594         \r
1595                 // Invalidate the type for a specific column (if given) or all columns since\r
1596                 // the data might have changed\r
1597                 var cols = settings.aoColumns;\r
1598                 if ( colIdx !== undefined ) {\r
1599                         cols[ colIdx ].sType = null;\r
1600                 }\r
1601                 else {\r
1602                         for ( i=0, ien=cols.length ; i<ien ; i++ ) {\r
1603                                 cols[i].sType = null;\r
1604                         }\r
1605         \r
1606                         // Update DataTables special `DT_*` attributes for the row\r
1607                         _fnRowAttributes( settings, row );\r
1608                 }\r
1609         }\r
1610         \r
1611         \r
1612         /**\r
1613          * Build a data source object from an HTML row, reading the contents of the\r
1614          * cells that are in the row.\r
1615          *\r
1616          * @param {object} settings DataTables settings object\r
1617          * @param {node|object} TR element from which to read data or existing row\r
1618          *   object from which to re-read the data from the cells\r
1619          * @param {int} [colIdx] Optional column index\r
1620          * @param {array|object} [d] Data source object. If `colIdx` is given then this\r
1621          *   parameter should also be given and will be used to write the data into.\r
1622          *   Only the column in question will be written\r
1623          * @returns {object} Object with two parameters: `data` the data read, in\r
1624          *   document order, and `cells` and array of nodes (they can be useful to the\r
1625          *   caller, so rather than needing a second traversal to get them, just return\r
1626          *   them from here).\r
1627          * @memberof DataTable#oApi\r
1628          */\r
1629         function _fnGetRowElements( settings, row, colIdx, d )\r
1630         {\r
1631                 var\r
1632                         tds = [],\r
1633                         td = row.firstChild,\r
1634                         name, col, o, i=0, contents,\r
1635                         columns = settings.aoColumns,\r
1636                         objectRead = settings._rowReadObject;\r
1637         \r
1638                 // Allow the data object to be passed in, or construct\r
1639                 d = d !== undefined ?\r
1640                         d :\r
1641                         objectRead ?\r
1642                                 {} :\r
1643                                 [];\r
1644         \r
1645                 var attr = function ( str, td  ) {\r
1646                         if ( typeof str === 'string' ) {\r
1647                                 var idx = str.indexOf('@');\r
1648         \r
1649                                 if ( idx !== -1 ) {\r
1650                                         var attr = str.substring( idx+1 );\r
1651                                         var setter = _fnSetObjectDataFn( str );\r
1652                                         setter( d, td.getAttribute( attr ) );\r
1653                                 }\r
1654                         }\r
1655                 };\r
1656         \r
1657                 // Read data from a cell and store into the data object\r
1658                 var cellProcess = function ( cell ) {\r
1659                         if ( colIdx === undefined || colIdx === i ) {\r
1660                                 col = columns[i];\r
1661                                 contents = $.trim(cell.innerHTML);\r
1662         \r
1663                                 if ( col && col._bAttrSrc ) {\r
1664                                         var setter = _fnSetObjectDataFn( col.mData._ );\r
1665                                         setter( d, contents );\r
1666         \r
1667                                         attr( col.mData.sort, cell );\r
1668                                         attr( col.mData.type, cell );\r
1669                                         attr( col.mData.filter, cell );\r
1670                                 }\r
1671                                 else {\r
1672                                         // Depending on the `data` option for the columns the data can\r
1673                                         // be read to either an object or an array.\r
1674                                         if ( objectRead ) {\r
1675                                                 if ( ! col._setter ) {\r
1676                                                         // Cache the setter function\r
1677                                                         col._setter = _fnSetObjectDataFn( col.mData );\r
1678                                                 }\r
1679                                                 col._setter( d, contents );\r
1680                                         }\r
1681                                         else {\r
1682                                                 d[i] = contents;\r
1683                                         }\r
1684                                 }\r
1685                         }\r
1686         \r
1687                         i++;\r
1688                 };\r
1689         \r
1690                 if ( td ) {\r
1691                         // `tr` element was passed in\r
1692                         while ( td ) {\r
1693                                 name = td.nodeName.toUpperCase();\r
1694         \r
1695                                 if ( name == "TD" || name == "TH" ) {\r
1696                                         cellProcess( td );\r
1697                                         tds.push( td );\r
1698                                 }\r
1699         \r
1700                                 td = td.nextSibling;\r
1701                         }\r
1702                 }\r
1703                 else {\r
1704                         // Existing row object passed in\r
1705                         tds = row.anCells;\r
1706         \r
1707                         for ( var j=0, jen=tds.length ; j<jen ; j++ ) {\r
1708                                 cellProcess( tds[j] );\r
1709                         }\r
1710                 }\r
1711         \r
1712                 // Read the ID from the DOM if present\r
1713                 var rowNode = row.firstChild ? row : row.nTr;\r
1714         \r
1715                 if ( rowNode ) {\r
1716                         var id = rowNode.getAttribute( 'id' );\r
1717         \r
1718                         if ( id ) {\r
1719                                 _fnSetObjectDataFn( settings.rowId )( d, id );\r
1720                         }\r
1721                 }\r
1722         \r
1723                 return {\r
1724                         data: d,\r
1725                         cells: tds\r
1726                 };\r
1727         }\r
1728         /**\r
1729          * Create a new TR element (and it's TD children) for a row\r
1730          *  @param {object} oSettings dataTables settings object\r
1731          *  @param {int} iRow Row to consider\r
1732          *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,\r
1733          *    DataTables will create a row automatically\r
1734          *  @param {array} [anTds] Array of TD|TH elements for the row - must be given\r
1735          *    if nTr is.\r
1736          *  @memberof DataTable#oApi\r
1737          */\r
1738         function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )\r
1739         {\r
1740                 var\r
1741                         row = oSettings.aoData[iRow],\r
1742                         rowData = row._aData,\r
1743                         cells = [],\r
1744                         nTr, nTd, oCol,\r
1745                         i, iLen;\r
1746         \r
1747                 if ( row.nTr === null )\r
1748                 {\r
1749                         nTr = nTrIn || document.createElement('tr');\r
1750         \r
1751                         row.nTr = nTr;\r
1752                         row.anCells = cells;\r
1753         \r
1754                         /* Use a private property on the node to allow reserve mapping from the node\r
1755                          * to the aoData array for fast look up\r
1756                          */\r
1757                         nTr._DT_RowIndex = iRow;\r
1758         \r
1759                         /* Special parameters can be given by the data source to be used on the row */\r
1760                         _fnRowAttributes( oSettings, row );\r
1761         \r
1762                         /* Process each column */\r
1763                         for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )\r
1764                         {\r
1765                                 oCol = oSettings.aoColumns[i];\r
1766         \r
1767                                 nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );\r
1768                                 nTd._DT_CellIndex = {\r
1769                                         row: iRow,\r
1770                                         column: i\r
1771                                 };\r
1772                                 \r
1773                                 cells.push( nTd );\r
1774         \r
1775                                 // Need to create the HTML if new, or if a rendering function is defined\r
1776                                 if ( (!nTrIn || oCol.mRender || oCol.mData !== i) &&\r
1777                                          (!$.isPlainObject(oCol.mData) || oCol.mData._ !== i+'.display')\r
1778                                 ) {\r
1779                                         nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );\r
1780                                 }\r
1781         \r
1782                                 /* Add user defined class */\r
1783                                 if ( oCol.sClass )\r
1784                                 {\r
1785                                         nTd.className += ' '+oCol.sClass;\r
1786                                 }\r
1787         \r
1788                                 // Visibility - add or remove as required\r
1789                                 if ( oCol.bVisible && ! nTrIn )\r
1790                                 {\r
1791                                         nTr.appendChild( nTd );\r
1792                                 }\r
1793                                 else if ( ! oCol.bVisible && nTrIn )\r
1794                                 {\r
1795                                         nTd.parentNode.removeChild( nTd );\r
1796                                 }\r
1797         \r
1798                                 if ( oCol.fnCreatedCell )\r
1799                                 {\r
1800                                         oCol.fnCreatedCell.call( oSettings.oInstance,\r
1801                                                 nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i\r
1802                                         );\r
1803                                 }\r
1804                         }\r
1805         \r
1806                         _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );\r
1807                 }\r
1808         \r
1809                 // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved\r
1810                 // and deployed\r
1811                 row.nTr.setAttribute( 'role', 'row' );\r
1812         }\r
1813         \r
1814         \r
1815         /**\r
1816          * Add attributes to a row based on the special `DT_*` parameters in a data\r
1817          * source object.\r
1818          *  @param {object} settings DataTables settings object\r
1819          *  @param {object} DataTables row object for the row to be modified\r
1820          *  @memberof DataTable#oApi\r
1821          */\r
1822         function _fnRowAttributes( settings, row )\r
1823         {\r
1824                 var tr = row.nTr;\r
1825                 var data = row._aData;\r
1826         \r
1827                 if ( tr ) {\r
1828                         var id = settings.rowIdFn( data );\r
1829         \r
1830                         if ( id ) {\r
1831                                 tr.id = id;\r
1832                         }\r
1833         \r
1834                         if ( data.DT_RowClass ) {\r
1835                                 // Remove any classes added by DT_RowClass before\r
1836                                 var a = data.DT_RowClass.split(' ');\r
1837                                 row.__rowc = row.__rowc ?\r
1838                                         _unique( row.__rowc.concat( a ) ) :\r
1839                                         a;\r
1840         \r
1841                                 $(tr)\r
1842                                         .removeClass( row.__rowc.join(' ') )\r
1843                                         .addClass( data.DT_RowClass );\r
1844                         }\r
1845         \r
1846                         if ( data.DT_RowAttr ) {\r
1847                                 $(tr).attr( data.DT_RowAttr );\r
1848                         }\r
1849         \r
1850                         if ( data.DT_RowData ) {\r
1851                                 $(tr).data( data.DT_RowData );\r
1852                         }\r
1853                 }\r
1854         }\r
1855         \r
1856         \r
1857         /**\r
1858          * Create the HTML header for the table\r
1859          *  @param {object} oSettings dataTables settings object\r
1860          *  @memberof DataTable#oApi\r
1861          */\r
1862         function _fnBuildHead( oSettings )\r
1863         {\r
1864                 var i, ien, cell, row, column;\r
1865                 var thead = oSettings.nTHead;\r
1866                 var tfoot = oSettings.nTFoot;\r
1867                 var createHeader = $('th, td', thead).length === 0;\r
1868                 var classes = oSettings.oClasses;\r
1869                 var columns = oSettings.aoColumns;\r
1870         \r
1871                 if ( createHeader ) {\r
1872                         row = $('<tr/>').appendTo( thead );\r
1873                 }\r
1874         \r
1875                 for ( i=0, ien=columns.length ; i<ien ; i++ ) {\r
1876                         column = columns[i];\r
1877                         cell = $( column.nTh ).addClass( column.sClass );\r
1878         \r
1879                         if ( createHeader ) {\r
1880                                 cell.appendTo( row );\r
1881                         }\r
1882         \r
1883                         // 1.11 move into sorting\r
1884                         if ( oSettings.oFeatures.bSort ) {\r
1885                                 cell.addClass( column.sSortingClass );\r
1886         \r
1887                                 if ( column.bSortable !== false ) {\r
1888                                         cell\r
1889                                                 .attr( 'tabindex', oSettings.iTabIndex )\r
1890                                                 .attr( 'aria-controls', oSettings.sTableId );\r
1891         \r
1892                                         _fnSortAttachListener( oSettings, column.nTh, i );\r
1893                                 }\r
1894                         }\r
1895         \r
1896                         if ( column.sTitle != cell[0].innerHTML ) {\r
1897                                 cell.html( column.sTitle );\r
1898                         }\r
1899         \r
1900                         _fnRenderer( oSettings, 'header' )(\r
1901                                 oSettings, cell, column, classes\r
1902                         );\r
1903                 }\r
1904         \r
1905                 if ( createHeader ) {\r
1906                         _fnDetectHeader( oSettings.aoHeader, thead );\r
1907                 }\r
1908                 \r
1909                 /* ARIA role for the rows */\r
1910                 $(thead).find('>tr').attr('role', 'row');\r
1911         \r
1912                 /* Deal with the footer - add classes if required */\r
1913                 $(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );\r
1914                 $(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );\r
1915         \r
1916                 // Cache the footer cells. Note that we only take the cells from the first\r
1917                 // row in the footer. If there is more than one row the user wants to\r
1918                 // interact with, they need to use the table().foot() method. Note also this\r
1919                 // allows cells to be used for multiple columns using colspan\r
1920                 if ( tfoot !== null ) {\r
1921                         var cells = oSettings.aoFooter[0];\r
1922         \r
1923                         for ( i=0, ien=cells.length ; i<ien ; i++ ) {\r
1924                                 column = columns[i];\r
1925                                 column.nTf = cells[i].cell;\r
1926         \r
1927                                 if ( column.sClass ) {\r
1928                                         $(column.nTf).addClass( column.sClass );\r
1929                                 }\r
1930                         }\r
1931                 }\r
1932         }\r
1933         \r
1934         \r
1935         /**\r
1936          * Draw the header (or footer) element based on the column visibility states. The\r
1937          * methodology here is to use the layout array from _fnDetectHeader, modified for\r
1938          * the instantaneous column visibility, to construct the new layout. The grid is\r
1939          * traversed over cell at a time in a rows x columns grid fashion, although each\r
1940          * cell insert can cover multiple elements in the grid - which is tracks using the\r
1941          * aApplied array. Cell inserts in the grid will only occur where there isn't\r
1942          * already a cell in that position.\r
1943          *  @param {object} oSettings dataTables settings object\r
1944          *  @param array {objects} aoSource Layout array from _fnDetectHeader\r
1945          *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,\r
1946          *  @memberof DataTable#oApi\r
1947          */\r
1948         function _fnDrawHead( oSettings, aoSource, bIncludeHidden )\r
1949         {\r
1950                 var i, iLen, j, jLen, k, kLen, n, nLocalTr;\r
1951                 var aoLocal = [];\r
1952                 var aApplied = [];\r
1953                 var iColumns = oSettings.aoColumns.length;\r
1954                 var iRowspan, iColspan;\r
1955         \r
1956                 if ( ! aoSource )\r
1957                 {\r
1958                         return;\r
1959                 }\r
1960         \r
1961                 if (  bIncludeHidden === undefined )\r
1962                 {\r
1963                         bIncludeHidden = false;\r
1964                 }\r
1965         \r
1966                 /* Make a copy of the master layout array, but without the visible columns in it */\r
1967                 for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )\r
1968                 {\r
1969                         aoLocal[i] = aoSource[i].slice();\r
1970                         aoLocal[i].nTr = aoSource[i].nTr;\r
1971         \r
1972                         /* Remove any columns which are currently hidden */\r
1973                         for ( j=iColumns-1 ; j>=0 ; j-- )\r
1974                         {\r
1975                                 if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )\r
1976                                 {\r
1977                                         aoLocal[i].splice( j, 1 );\r
1978                                 }\r
1979                         }\r
1980         \r
1981                         /* Prep the applied array - it needs an element for each row */\r
1982                         aApplied.push( [] );\r
1983                 }\r
1984         \r
1985                 for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )\r
1986                 {\r
1987                         nLocalTr = aoLocal[i].nTr;\r
1988         \r
1989                         /* All cells are going to be replaced, so empty out the row */\r
1990                         if ( nLocalTr )\r
1991                         {\r
1992                                 while( (n = nLocalTr.firstChild) )\r
1993                                 {\r
1994                                         nLocalTr.removeChild( n );\r
1995                                 }\r
1996                         }\r
1997         \r
1998                         for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )\r
1999                         {\r
2000                                 iRowspan = 1;\r
2001                                 iColspan = 1;\r
2002         \r
2003                                 /* Check to see if there is already a cell (row/colspan) covering our target\r
2004                                  * insert point. If there is, then there is nothing to do.\r
2005                                  */\r
2006                                 if ( aApplied[i][j] === undefined )\r
2007                                 {\r
2008                                         nLocalTr.appendChild( aoLocal[i][j].cell );\r
2009                                         aApplied[i][j] = 1;\r
2010         \r
2011                                         /* Expand the cell to cover as many rows as needed */\r
2012                                         while ( aoLocal[i+iRowspan] !== undefined &&\r
2013                                                 aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )\r
2014                                         {\r
2015                                                 aApplied[i+iRowspan][j] = 1;\r
2016                                                 iRowspan++;\r
2017                                         }\r
2018         \r
2019                                         /* Expand the cell to cover as many columns as needed */\r
2020                                         while ( aoLocal[i][j+iColspan] !== undefined &&\r
2021                                                 aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )\r
2022                                         {\r
2023                                                 /* Must update the applied array over the rows for the columns */\r
2024                                                 for ( k=0 ; k<iRowspan ; k++ )\r
2025                                                 {\r
2026                                                         aApplied[i+k][j+iColspan] = 1;\r
2027                                                 }\r
2028                                                 iColspan++;\r
2029                                         }\r
2030         \r
2031                                         /* Do the actual expansion in the DOM */\r
2032                                         $(aoLocal[i][j].cell)\r
2033                                                 .attr('rowspan', iRowspan)\r
2034                                                 .attr('colspan', iColspan);\r
2035                                 }\r
2036                         }\r
2037                 }\r
2038         }\r
2039         \r
2040         \r
2041         /**\r
2042          * Insert the required TR nodes into the table for display\r
2043          *  @param {object} oSettings dataTables settings object\r
2044          *  @memberof DataTable#oApi\r
2045          */\r
2046         function _fnDraw( oSettings )\r
2047         {\r
2048                 /* Provide a pre-callback function which can be used to cancel the draw is false is returned */\r
2049                 var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );\r
2050                 if ( $.inArray( false, aPreDraw ) !== -1 )\r
2051                 {\r
2052                         _fnProcessingDisplay( oSettings, false );\r
2053                         return;\r
2054                 }\r
2055         \r
2056                 var i, iLen, n;\r
2057                 var anRows = [];\r
2058                 var iRowCount = 0;\r
2059                 var asStripeClasses = oSettings.asStripeClasses;\r
2060                 var iStripes = asStripeClasses.length;\r
2061                 var iOpenRows = oSettings.aoOpenRows.length;\r
2062                 var oLang = oSettings.oLanguage;\r
2063                 var iInitDisplayStart = oSettings.iInitDisplayStart;\r
2064                 var bServerSide = _fnDataSource( oSettings ) == 'ssp';\r
2065                 var aiDisplay = oSettings.aiDisplay;\r
2066         \r
2067                 oSettings.bDrawing = true;\r
2068         \r
2069                 /* Check and see if we have an initial draw position from state saving */\r
2070                 if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )\r
2071                 {\r
2072                         oSettings._iDisplayStart = bServerSide ?\r
2073                                 iInitDisplayStart :\r
2074                                 iInitDisplayStart >= oSettings.fnRecordsDisplay() ?\r
2075                                         0 :\r
2076                                         iInitDisplayStart;\r
2077         \r
2078                         oSettings.iInitDisplayStart = -1;\r
2079                 }\r
2080         \r
2081                 var iDisplayStart = oSettings._iDisplayStart;\r
2082                 var iDisplayEnd = oSettings.fnDisplayEnd();\r
2083         \r
2084                 /* Server-side processing draw intercept */\r
2085                 if ( oSettings.bDeferLoading )\r
2086                 {\r
2087                         oSettings.bDeferLoading = false;\r
2088                         oSettings.iDraw++;\r
2089                         _fnProcessingDisplay( oSettings, false );\r
2090                 }\r
2091                 else if ( !bServerSide )\r
2092                 {\r
2093                         oSettings.iDraw++;\r
2094                 }\r
2095                 else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )\r
2096                 {\r
2097                         return;\r
2098                 }\r
2099         \r
2100                 if ( aiDisplay.length !== 0 )\r
2101                 {\r
2102                         var iStart = bServerSide ? 0 : iDisplayStart;\r
2103                         var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;\r
2104         \r
2105                         for ( var j=iStart ; j<iEnd ; j++ )\r
2106                         {\r
2107                                 var iDataIndex = aiDisplay[j];\r
2108                                 var aoData = oSettings.aoData[ iDataIndex ];\r
2109                                 if ( aoData.nTr === null )\r
2110                                 {\r
2111                                         _fnCreateTr( oSettings, iDataIndex );\r
2112                                 }\r
2113         \r
2114                                 var nRow = aoData.nTr;\r
2115         \r
2116                                 /* Remove the old striping classes and then add the new one */\r
2117                                 if ( iStripes !== 0 )\r
2118                                 {\r
2119                                         var sStripe = asStripeClasses[ iRowCount % iStripes ];\r
2120                                         if ( aoData._sRowStripe != sStripe )\r
2121                                         {\r
2122                                                 $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );\r
2123                                                 aoData._sRowStripe = sStripe;\r
2124                                         }\r
2125                                 }\r
2126         \r
2127                                 // Row callback functions - might want to manipulate the row\r
2128                                 // iRowCount and j are not currently documented. Are they at all\r
2129                                 // useful?\r
2130                                 _fnCallbackFire( oSettings, 'aoRowCallback', null,\r
2131                                         [nRow, aoData._aData, iRowCount, j] );\r
2132         \r
2133                                 anRows.push( nRow );\r
2134                                 iRowCount++;\r
2135                         }\r
2136                 }\r
2137                 else\r
2138                 {\r
2139                         /* Table is empty - create a row with an empty message in it */\r
2140                         var sZero = oLang.sZeroRecords;\r
2141                         if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )\r
2142                         {\r
2143                                 sZero = oLang.sLoadingRecords;\r
2144                         }\r
2145                         else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )\r
2146                         {\r
2147                                 sZero = oLang.sEmptyTable;\r
2148                         }\r
2149         \r
2150                         anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )\r
2151                                 .append( $('<td />', {\r
2152                                         'valign':  'top',\r
2153                                         'colSpan': _fnVisbleColumns( oSettings ),\r
2154                                         'class':   oSettings.oClasses.sRowEmpty\r
2155                                 } ).html( sZero ) )[0];\r
2156                 }\r
2157         \r
2158                 /* Header and footer callbacks */\r
2159                 _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],\r
2160                         _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );\r
2161         \r
2162                 _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],\r
2163                         _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );\r
2164         \r
2165                 var body = $(oSettings.nTBody);\r
2166         \r
2167                 body.children().detach();\r
2168                 body.append( $(anRows) );\r
2169         \r
2170                 /* Call all required callback functions for the end of a draw */\r
2171                 _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );\r
2172         \r
2173                 /* Draw is complete, sorting and filtering must be as well */\r
2174                 oSettings.bSorted = false;\r
2175                 oSettings.bFiltered = false;\r
2176                 oSettings.bDrawing = false;\r
2177         }\r
2178         \r
2179         \r
2180         /**\r
2181          * Redraw the table - taking account of the various features which are enabled\r
2182          *  @param {object} oSettings dataTables settings object\r
2183          *  @param {boolean} [holdPosition] Keep the current paging position. By default\r
2184          *    the paging is reset to the first page\r
2185          *  @memberof DataTable#oApi\r
2186          */\r
2187         function _fnReDraw( settings, holdPosition )\r
2188         {\r
2189                 var\r
2190                         features = settings.oFeatures,\r
2191                         sort     = features.bSort,\r
2192                         filter   = features.bFilter;\r
2193         \r
2194                 if ( sort ) {\r
2195                         _fnSort( settings );\r
2196                 }\r
2197         \r
2198                 if ( filter ) {\r
2199                         _fnFilterComplete( settings, settings.oPreviousSearch );\r
2200                 }\r
2201                 else {\r
2202                         // No filtering, so we want to just use the display master\r
2203                         settings.aiDisplay = settings.aiDisplayMaster.slice();\r
2204                 }\r
2205         \r
2206                 if ( holdPosition !== true ) {\r
2207                         settings._iDisplayStart = 0;\r
2208                 }\r
2209         \r
2210                 // Let any modules know about the draw hold position state (used by\r
2211                 // scrolling internally)\r
2212                 settings._drawHold = holdPosition;\r
2213         \r
2214                 _fnDraw( settings );\r
2215         \r
2216                 settings._drawHold = false;\r
2217         }\r
2218         \r
2219         \r
2220         /**\r
2221          * Add the options to the page HTML for the table\r
2222          *  @param {object} oSettings dataTables settings object\r
2223          *  @memberof DataTable#oApi\r
2224          */\r
2225         function _fnAddOptionsHtml ( oSettings )\r
2226         {\r
2227                 var classes = oSettings.oClasses;\r
2228                 var table = $(oSettings.nTable);\r
2229                 var holding = $('<div/>').insertBefore( table ); // Holding element for speed\r
2230                 var features = oSettings.oFeatures;\r
2231         \r
2232                 // All DataTables are wrapped in a div\r
2233                 var insert = $('<div/>', {\r
2234                         id:      oSettings.sTableId+'_wrapper',\r
2235                         'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)\r
2236                 } );\r
2237         \r
2238                 oSettings.nHolding = holding[0];\r
2239                 oSettings.nTableWrapper = insert[0];\r
2240                 oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;\r
2241         \r
2242                 /* Loop over the user set positioning and place the elements as needed */\r
2243                 var aDom = oSettings.sDom.split('');\r
2244                 var featureNode, cOption, nNewNode, cNext, sAttr, j;\r
2245                 for ( var i=0 ; i<aDom.length ; i++ )\r
2246                 {\r
2247                         featureNode = null;\r
2248                         cOption = aDom[i];\r
2249         \r
2250                         if ( cOption == '<' )\r
2251                         {\r
2252                                 /* New container div */\r
2253                                 nNewNode = $('<div/>')[0];\r
2254         \r
2255                                 /* Check to see if we should append an id and/or a class name to the container */\r
2256                                 cNext = aDom[i+1];\r
2257                                 if ( cNext == "'" || cNext == '"' )\r
2258                                 {\r
2259                                         sAttr = "";\r
2260                                         j = 2;\r
2261                                         while ( aDom[i+j] != cNext )\r
2262                                         {\r
2263                                                 sAttr += aDom[i+j];\r
2264                                                 j++;\r
2265                                         }\r
2266         \r
2267                                         /* Replace jQuery UI constants @todo depreciated */\r
2268                                         if ( sAttr == "H" )\r
2269                                         {\r
2270                                                 sAttr = classes.sJUIHeader;\r
2271                                         }\r
2272                                         else if ( sAttr == "F" )\r
2273                                         {\r
2274                                                 sAttr = classes.sJUIFooter;\r
2275                                         }\r
2276         \r
2277                                         /* The attribute can be in the format of "#id.class", "#id" or "class" This logic\r
2278                                          * breaks the string into parts and applies them as needed\r
2279                                          */\r
2280                                         if ( sAttr.indexOf('.') != -1 )\r
2281                                         {\r
2282                                                 var aSplit = sAttr.split('.');\r
2283                                                 nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);\r
2284                                                 nNewNode.className = aSplit[1];\r
2285                                         }\r
2286                                         else if ( sAttr.charAt(0) == "#" )\r
2287                                         {\r
2288                                                 nNewNode.id = sAttr.substr(1, sAttr.length-1);\r
2289                                         }\r
2290                                         else\r
2291                                         {\r
2292                                                 nNewNode.className = sAttr;\r
2293                                         }\r
2294         \r
2295                                         i += j; /* Move along the position array */\r
2296                                 }\r
2297         \r
2298                                 insert.append( nNewNode );\r
2299                                 insert = $(nNewNode);\r
2300                         }\r
2301                         else if ( cOption == '>' )\r
2302                         {\r
2303                                 /* End container div */\r
2304                                 insert = insert.parent();\r
2305                         }\r
2306                         // @todo Move options into their own plugins?\r
2307                         else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )\r
2308                         {\r
2309                                 /* Length */\r
2310                                 featureNode = _fnFeatureHtmlLength( oSettings );\r
2311                         }\r
2312                         else if ( cOption == 'f' && features.bFilter )\r
2313                         {\r
2314                                 /* Filter */\r
2315                                 featureNode = _fnFeatureHtmlFilter( oSettings );\r
2316                         }\r
2317                         else if ( cOption == 'r' && features.bProcessing )\r
2318                         {\r
2319                                 /* pRocessing */\r
2320                                 featureNode = _fnFeatureHtmlProcessing( oSettings );\r
2321                         }\r
2322                         else if ( cOption == 't' )\r
2323                         {\r
2324                                 /* Table */\r
2325                                 featureNode = _fnFeatureHtmlTable( oSettings );\r
2326                         }\r
2327                         else if ( cOption ==  'i' && features.bInfo )\r
2328                         {\r
2329                                 /* Info */\r
2330                                 featureNode = _fnFeatureHtmlInfo( oSettings );\r
2331                         }\r
2332                         else if ( cOption == 'p' && features.bPaginate )\r
2333                         {\r
2334                                 /* Pagination */\r
2335                                 featureNode = _fnFeatureHtmlPaginate( oSettings );\r
2336                         }\r
2337                         else if ( DataTable.ext.feature.length !== 0 )\r
2338                         {\r
2339                                 /* Plug-in features */\r
2340                                 var aoFeatures = DataTable.ext.feature;\r
2341                                 for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )\r
2342                                 {\r
2343                                         if ( cOption == aoFeatures[k].cFeature )\r
2344                                         {\r
2345                                                 featureNode = aoFeatures[k].fnInit( oSettings );\r
2346                                                 break;\r
2347                                         }\r
2348                                 }\r
2349                         }\r
2350         \r
2351                         /* Add to the 2D features array */\r
2352                         if ( featureNode )\r
2353                         {\r
2354                                 var aanFeatures = oSettings.aanFeatures;\r
2355         \r
2356                                 if ( ! aanFeatures[cOption] )\r
2357                                 {\r
2358                                         aanFeatures[cOption] = [];\r
2359                                 }\r
2360         \r
2361                                 aanFeatures[cOption].push( featureNode );\r
2362                                 insert.append( featureNode );\r
2363                         }\r
2364                 }\r
2365         \r
2366                 /* Built our DOM structure - replace the holding div with what we want */\r
2367                 holding.replaceWith( insert );\r
2368                 oSettings.nHolding = null;\r
2369         }\r
2370         \r
2371         \r
2372         /**\r
2373          * Use the DOM source to create up an array of header cells. The idea here is to\r
2374          * create a layout grid (array) of rows x columns, which contains a reference\r
2375          * to the cell that that point in the grid (regardless of col/rowspan), such that\r
2376          * any column / row could be removed and the new grid constructed\r
2377          *  @param array {object} aLayout Array to store the calculated layout in\r
2378          *  @param {node} nThead The header/footer element for the table\r
2379          *  @memberof DataTable#oApi\r
2380          */\r
2381         function _fnDetectHeader ( aLayout, nThead )\r
2382         {\r
2383                 var nTrs = $(nThead).children('tr');\r
2384                 var nTr, nCell;\r
2385                 var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;\r
2386                 var bUnique;\r
2387                 var fnShiftCol = function ( a, i, j ) {\r
2388                         var k = a[i];\r
2389                         while ( k[j] ) {\r
2390                                 j++;\r
2391                         }\r
2392                         return j;\r
2393                 };\r
2394         \r
2395                 aLayout.splice( 0, aLayout.length );\r
2396         \r
2397                 /* We know how many rows there are in the layout - so prep it */\r
2398                 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )\r
2399                 {\r
2400                         aLayout.push( [] );\r
2401                 }\r
2402         \r
2403                 /* Calculate a layout array */\r
2404                 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )\r
2405                 {\r
2406                         nTr = nTrs[i];\r
2407                         iColumn = 0;\r
2408         \r
2409                         /* For every cell in the row... */\r
2410                         nCell = nTr.firstChild;\r
2411                         while ( nCell ) {\r
2412                                 if ( nCell.nodeName.toUpperCase() == "TD" ||\r
2413                                      nCell.nodeName.toUpperCase() == "TH" )\r
2414                                 {\r
2415                                         /* Get the col and rowspan attributes from the DOM and sanitise them */\r
2416                                         iColspan = nCell.getAttribute('colspan') * 1;\r
2417                                         iRowspan = nCell.getAttribute('rowspan') * 1;\r
2418                                         iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;\r
2419                                         iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;\r
2420         \r
2421                                         /* There might be colspan cells already in this row, so shift our target\r
2422                                          * accordingly\r
2423                                          */\r
2424                                         iColShifted = fnShiftCol( aLayout, i, iColumn );\r
2425         \r
2426                                         /* Cache calculation for unique columns */\r
2427                                         bUnique = iColspan === 1 ? true : false;\r
2428         \r
2429                                         /* If there is col / rowspan, copy the information into the layout grid */\r
2430                                         for ( l=0 ; l<iColspan ; l++ )\r
2431                                         {\r
2432                                                 for ( k=0 ; k<iRowspan ; k++ )\r
2433                                                 {\r
2434                                                         aLayout[i+k][iColShifted+l] = {\r
2435                                                                 "cell": nCell,\r
2436                                                                 "unique": bUnique\r
2437                                                         };\r
2438                                                         aLayout[i+k].nTr = nTr;\r
2439                                                 }\r
2440                                         }\r
2441                                 }\r
2442                                 nCell = nCell.nextSibling;\r
2443                         }\r
2444                 }\r
2445         }\r
2446         \r
2447         \r
2448         /**\r
2449          * Get an array of unique th elements, one for each column\r
2450          *  @param {object} oSettings dataTables settings object\r
2451          *  @param {node} nHeader automatically detect the layout from this node - optional\r
2452          *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional\r
2453          *  @returns array {node} aReturn list of unique th's\r
2454          *  @memberof DataTable#oApi\r
2455          */\r
2456         function _fnGetUniqueThs ( oSettings, nHeader, aLayout )\r
2457         {\r
2458                 var aReturn = [];\r
2459                 if ( !aLayout )\r
2460                 {\r
2461                         aLayout = oSettings.aoHeader;\r
2462                         if ( nHeader )\r
2463                         {\r
2464                                 aLayout = [];\r
2465                                 _fnDetectHeader( aLayout, nHeader );\r
2466                         }\r
2467                 }\r
2468         \r
2469                 for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )\r
2470                 {\r
2471                         for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )\r
2472                         {\r
2473                                 if ( aLayout[i][j].unique &&\r
2474                                          (!aReturn[j] || !oSettings.bSortCellsTop) )\r
2475                                 {\r
2476                                         aReturn[j] = aLayout[i][j].cell;\r
2477                                 }\r
2478                         }\r
2479                 }\r
2480         \r
2481                 return aReturn;\r
2482         }\r
2483         \r
2484         /**\r
2485          * Create an Ajax call based on the table's settings, taking into account that\r
2486          * parameters can have multiple forms, and backwards compatibility.\r
2487          *\r
2488          * @param {object} oSettings dataTables settings object\r
2489          * @param {array} data Data to send to the server, required by\r
2490          *     DataTables - may be augmented by developer callbacks\r
2491          * @param {function} fn Callback function to run when data is obtained\r
2492          */\r
2493         function _fnBuildAjax( oSettings, data, fn )\r
2494         {\r
2495                 // Compatibility with 1.9-, allow fnServerData and event to manipulate\r
2496                 _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );\r
2497         \r
2498                 // Convert to object based for 1.10+ if using the old array scheme which can\r
2499                 // come from server-side processing or serverParams\r
2500                 if ( data && $.isArray(data) ) {\r
2501                         var tmp = {};\r
2502                         var rbracket = /(.*?)\[\]$/;\r
2503         \r
2504                         $.each( data, function (key, val) {\r
2505                                 var match = val.name.match(rbracket);\r
2506         \r
2507                                 if ( match ) {\r
2508                                         // Support for arrays\r
2509                                         var name = match[0];\r
2510         \r
2511                                         if ( ! tmp[ name ] ) {\r
2512                                                 tmp[ name ] = [];\r
2513                                         }\r
2514                                         tmp[ name ].push( val.value );\r
2515                                 }\r
2516                                 else {\r
2517                                         tmp[val.name] = val.value;\r
2518                                 }\r
2519                         } );\r
2520                         data = tmp;\r
2521                 }\r
2522         \r
2523                 var ajaxData;\r
2524                 var ajax = oSettings.ajax;\r
2525                 var instance = oSettings.oInstance;\r
2526                 var callback = function ( json ) {\r
2527                         _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] );\r
2528                         fn( json );\r
2529                 };\r
2530         \r
2531                 if ( $.isPlainObject( ajax ) && ajax.data )\r
2532                 {\r
2533                         ajaxData = ajax.data;\r
2534         \r
2535                         var newData = $.isFunction( ajaxData ) ?\r
2536                                 ajaxData( data, oSettings ) :  // fn can manipulate data or return\r
2537                                 ajaxData;                      // an object object or array to merge\r
2538         \r
2539                         // If the function returned something, use that alone\r
2540                         data = $.isFunction( ajaxData ) && newData ?\r
2541                                 newData :\r
2542                                 $.extend( true, data, newData );\r
2543         \r
2544                         // Remove the data property as we've resolved it already and don't want\r
2545                         // jQuery to do it again (it is restored at the end of the function)\r
2546                         delete ajax.data;\r
2547                 }\r
2548         \r
2549                 var baseAjax = {\r
2550                         "data": data,\r
2551                         "success": function (json) {\r
2552                                 var error = json.error || json.sError;\r
2553                                 if ( error ) {\r
2554                                         _fnLog( oSettings, 0, error );\r
2555                                 }\r
2556         \r
2557                                 oSettings.json = json;\r
2558                                 callback( json );\r
2559                         },\r
2560                         "dataType": "json",\r
2561                         "cache": false,\r
2562                         "type": oSettings.sServerMethod,\r
2563                         "error": function (xhr, error, thrown) {\r
2564                                 var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] );\r
2565         \r
2566                                 if ( $.inArray( true, ret ) === -1 ) {\r
2567                                         if ( error == "parsererror" ) {\r
2568                                                 _fnLog( oSettings, 0, 'Invalid JSON response', 1 );\r
2569                                         }\r
2570                                         else if ( xhr.readyState === 4 ) {\r
2571                                                 _fnLog( oSettings, 0, 'Ajax error', 7 );\r
2572                                         }\r
2573                                 }\r
2574         \r
2575                                 _fnProcessingDisplay( oSettings, false );\r
2576                         }\r
2577                 };\r
2578         \r
2579                 // Store the data submitted for the API\r
2580                 oSettings.oAjaxData = data;\r
2581         \r
2582                 // Allow plug-ins and external processes to modify the data\r
2583                 _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );\r
2584         \r
2585                 if ( oSettings.fnServerData )\r
2586                 {\r
2587                         // DataTables 1.9- compatibility\r
2588                         oSettings.fnServerData.call( instance,\r
2589                                 oSettings.sAjaxSource,\r
2590                                 $.map( data, function (val, key) { // Need to convert back to 1.9 trad format\r
2591                                         return { name: key, value: val };\r
2592                                 } ),\r
2593                                 callback,\r
2594                                 oSettings\r
2595                         );\r
2596                 }\r
2597                 else if ( oSettings.sAjaxSource || typeof ajax === 'string' )\r
2598                 {\r
2599                         // DataTables 1.9- compatibility\r
2600                         oSettings.jqXHR = $.ajax( $.extend( baseAjax, {\r
2601                                 url: ajax || oSettings.sAjaxSource\r
2602                         } ) );\r
2603                 }\r
2604                 else if ( $.isFunction( ajax ) )\r
2605                 {\r
2606                         // Is a function - let the caller define what needs to be done\r
2607                         oSettings.jqXHR = ajax.call( instance, data, callback, oSettings );\r
2608                 }\r
2609                 else\r
2610                 {\r
2611                         // Object to extend the base settings\r
2612                         oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );\r
2613         \r
2614                         // Restore for next time around\r
2615                         ajax.data = ajaxData;\r
2616                 }\r
2617         }\r
2618         \r
2619         \r
2620         /**\r
2621          * Update the table using an Ajax call\r
2622          *  @param {object} settings dataTables settings object\r
2623          *  @returns {boolean} Block the table drawing or not\r
2624          *  @memberof DataTable#oApi\r
2625          */\r
2626         function _fnAjaxUpdate( settings )\r
2627         {\r
2628                 if ( settings.bAjaxDataGet ) {\r
2629                         settings.iDraw++;\r
2630                         _fnProcessingDisplay( settings, true );\r
2631         \r
2632                         _fnBuildAjax(\r
2633                                 settings,\r
2634                                 _fnAjaxParameters( settings ),\r
2635                                 function(json) {\r
2636                                         _fnAjaxUpdateDraw( settings, json );\r
2637                                 }\r
2638                         );\r
2639         \r
2640                         return false;\r
2641                 }\r
2642                 return true;\r
2643         }\r
2644         \r
2645         \r
2646         /**\r
2647          * Build up the parameters in an object needed for a server-side processing\r
2648          * request. Note that this is basically done twice, is different ways - a modern\r
2649          * method which is used by default in DataTables 1.10 which uses objects and\r
2650          * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if\r
2651          * the sAjaxSource option is used in the initialisation, or the legacyAjax\r
2652          * option is set.\r
2653          *  @param {object} oSettings dataTables settings object\r
2654          *  @returns {bool} block the table drawing or not\r
2655          *  @memberof DataTable#oApi\r
2656          */\r
2657         function _fnAjaxParameters( settings )\r
2658         {\r
2659                 var\r
2660                         columns = settings.aoColumns,\r
2661                         columnCount = columns.length,\r
2662                         features = settings.oFeatures,\r
2663                         preSearch = settings.oPreviousSearch,\r
2664                         preColSearch = settings.aoPreSearchCols,\r
2665                         i, data = [], dataProp, column, columnSearch,\r
2666                         sort = _fnSortFlatten( settings ),\r
2667                         displayStart = settings._iDisplayStart,\r
2668                         displayLength = features.bPaginate !== false ?\r
2669                                 settings._iDisplayLength :\r
2670                                 -1;\r
2671         \r
2672                 var param = function ( name, value ) {\r
2673                         data.push( { 'name': name, 'value': value } );\r
2674                 };\r
2675         \r
2676                 // DataTables 1.9- compatible method\r
2677                 param( 'sEcho',          settings.iDraw );\r
2678                 param( 'iColumns',       columnCount );\r
2679                 param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );\r
2680                 param( 'iDisplayStart',  displayStart );\r
2681                 param( 'iDisplayLength', displayLength );\r
2682         \r
2683                 // DataTables 1.10+ method\r
2684                 var d = {\r
2685                         draw:    settings.iDraw,\r
2686                         columns: [],\r
2687                         order:   [],\r
2688                         start:   displayStart,\r
2689                         length:  displayLength,\r
2690                         search:  {\r
2691                                 value: preSearch.sSearch,\r
2692                                 regex: preSearch.bRegex\r
2693                         }\r
2694                 };\r
2695         \r
2696                 for ( i=0 ; i<columnCount ; i++ ) {\r
2697                         column = columns[i];\r
2698                         columnSearch = preColSearch[i];\r
2699                         dataProp = typeof column.mData=="function" ? 'function' : column.mData ;\r
2700         \r
2701                         d.columns.push( {\r
2702                                 data:       dataProp,\r
2703                                 name:       column.sName,\r
2704                                 searchable: column.bSearchable,\r
2705                                 orderable:  column.bSortable,\r
2706                                 search:     {\r
2707                                         value: columnSearch.sSearch,\r
2708                                         regex: columnSearch.bRegex\r
2709                                 }\r
2710                         } );\r
2711         \r
2712                         param( "mDataProp_"+i, dataProp );\r
2713         \r
2714                         if ( features.bFilter ) {\r
2715                                 param( 'sSearch_'+i,     columnSearch.sSearch );\r
2716                                 param( 'bRegex_'+i,      columnSearch.bRegex );\r
2717                                 param( 'bSearchable_'+i, column.bSearchable );\r
2718                         }\r
2719         \r
2720                         if ( features.bSort ) {\r
2721                                 param( 'bSortable_'+i, column.bSortable );\r
2722                         }\r
2723                 }\r
2724         \r
2725                 if ( features.bFilter ) {\r
2726                         param( 'sSearch', preSearch.sSearch );\r
2727                         param( 'bRegex', preSearch.bRegex );\r
2728                 }\r
2729         \r
2730                 if ( features.bSort ) {\r
2731                         $.each( sort, function ( i, val ) {\r
2732                                 d.order.push( { column: val.col, dir: val.dir } );\r
2733         \r
2734                                 param( 'iSortCol_'+i, val.col );\r
2735                                 param( 'sSortDir_'+i, val.dir );\r
2736                         } );\r
2737         \r
2738                         param( 'iSortingCols', sort.length );\r
2739                 }\r
2740         \r
2741                 // If the legacy.ajax parameter is null, then we automatically decide which\r
2742                 // form to use, based on sAjaxSource\r
2743                 var legacy = DataTable.ext.legacy.ajax;\r
2744                 if ( legacy === null ) {\r
2745                         return settings.sAjaxSource ? data : d;\r
2746                 }\r
2747         \r
2748                 // Otherwise, if legacy has been specified then we use that to decide on the\r
2749                 // form\r
2750                 return legacy ? data : d;\r
2751         }\r
2752         \r
2753         \r
2754         /**\r
2755          * Data the data from the server (nuking the old) and redraw the table\r
2756          *  @param {object} oSettings dataTables settings object\r
2757          *  @param {object} json json data return from the server.\r
2758          *  @param {string} json.sEcho Tracking flag for DataTables to match requests\r
2759          *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering\r
2760          *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering\r
2761          *  @param {array} json.aaData The data to display on this page\r
2762          *  @param {string} [json.sColumns] Column ordering (sName, comma separated)\r
2763          *  @memberof DataTable#oApi\r
2764          */\r
2765         function _fnAjaxUpdateDraw ( settings, json )\r
2766         {\r
2767                 // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.\r
2768                 // Support both\r
2769                 var compat = function ( old, modern ) {\r
2770                         return json[old] !== undefined ? json[old] : json[modern];\r
2771                 };\r
2772         \r
2773                 var data = _fnAjaxDataSrc( settings, json );\r
2774                 var draw            = compat( 'sEcho',                'draw' );\r
2775                 var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );\r
2776                 var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );\r
2777         \r
2778                 if ( draw ) {\r
2779                         // Protect against out of sequence returns\r
2780                         if ( draw*1 < settings.iDraw ) {\r
2781                                 return;\r
2782                         }\r
2783                         settings.iDraw = draw * 1;\r
2784                 }\r
2785         \r
2786                 _fnClearTable( settings );\r
2787                 settings._iRecordsTotal   = parseInt(recordsTotal, 10);\r
2788                 settings._iRecordsDisplay = parseInt(recordsFiltered, 10);\r
2789         \r
2790                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {\r
2791                         _fnAddData( settings, data[i] );\r
2792                 }\r
2793                 settings.aiDisplay = settings.aiDisplayMaster.slice();\r
2794         \r
2795                 settings.bAjaxDataGet = false;\r
2796                 _fnDraw( settings );\r
2797         \r
2798                 if ( ! settings._bInitComplete ) {\r
2799                         _fnInitComplete( settings, json );\r
2800                 }\r
2801         \r
2802                 settings.bAjaxDataGet = true;\r
2803                 _fnProcessingDisplay( settings, false );\r
2804         }\r
2805         \r
2806         \r
2807         /**\r
2808          * Get the data from the JSON data source to use for drawing a table. Using\r
2809          * `_fnGetObjectDataFn` allows the data to be sourced from a property of the\r
2810          * source object, or from a processing function.\r
2811          *  @param {object} oSettings dataTables settings object\r
2812          *  @param  {object} json Data source object / array from the server\r
2813          *  @return {array} Array of data to use\r
2814          */\r
2815         function _fnAjaxDataSrc ( oSettings, json )\r
2816         {\r
2817                 var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?\r
2818                         oSettings.ajax.dataSrc :\r
2819                         oSettings.sAjaxDataProp; // Compatibility with 1.9-.\r
2820         \r
2821                 // Compatibility with 1.9-. In order to read from aaData, check if the\r
2822                 // default has been changed, if not, check for aaData\r
2823                 if ( dataSrc === 'data' ) {\r
2824                         return json.aaData || json[dataSrc];\r
2825                 }\r
2826         \r
2827                 return dataSrc !== "" ?\r
2828                         _fnGetObjectDataFn( dataSrc )( json ) :\r
2829                         json;\r
2830         }\r
2831         \r
2832         /**\r
2833          * Generate the node required for filtering text\r
2834          *  @returns {node} Filter control element\r
2835          *  @param {object} oSettings dataTables settings object\r
2836          *  @memberof DataTable#oApi\r
2837          */\r
2838         function _fnFeatureHtmlFilter ( settings )\r
2839         {\r
2840                 var classes = settings.oClasses;\r
2841                 var tableId = settings.sTableId;\r
2842                 var language = settings.oLanguage;\r
2843                 var previousSearch = settings.oPreviousSearch;\r
2844                 var features = settings.aanFeatures;\r
2845                 var input = '<input type="search" class="'+classes.sFilterInput+'"/>';\r
2846         \r
2847                 var str = language.sSearch;\r
2848                 str = str.match(/_INPUT_/) ?\r
2849                         str.replace('_INPUT_', input) :\r
2850                         str+input;\r
2851         \r
2852                 var filter = $('<div/>', {\r
2853                                 'id': ! features.f ? tableId+'_filter' : null,\r
2854                                 'class': classes.sFilter\r
2855                         } )\r
2856                         .append( $('<label/>' ).append( str ) );\r
2857         \r
2858                 var searchFn = function() {\r
2859                         /* Update all other filter input elements for the new display */\r
2860                         var n = features.f;\r
2861                         var val = !this.value ? "" : this.value; // mental IE8 fix :-(\r
2862         \r
2863                         /* Now do the filter */\r
2864                         if ( val != previousSearch.sSearch ) {\r
2865                                 _fnFilterComplete( settings, {\r
2866                                         "sSearch": val,\r
2867                                         "bRegex": previousSearch.bRegex,\r
2868                                         "bSmart": previousSearch.bSmart ,\r
2869                                         "bCaseInsensitive": previousSearch.bCaseInsensitive\r
2870                                 } );\r
2871         \r
2872                                 // Need to redraw, without resorting\r
2873                                 settings._iDisplayStart = 0;\r
2874                                 _fnDraw( settings );\r
2875                         }\r
2876                 };\r
2877         \r
2878                 var searchDelay = settings.searchDelay !== null ?\r
2879                         settings.searchDelay :\r
2880                         _fnDataSource( settings ) === 'ssp' ?\r
2881                                 400 :\r
2882                                 0;\r
2883         \r
2884                 var jqFilter = $('input', filter)\r
2885                         .val( previousSearch.sSearch )\r
2886                         .attr( 'placeholder', language.sSearchPlaceholder )\r
2887                         .bind(\r
2888                                 'keyup.DT search.DT input.DT paste.DT cut.DT',\r
2889                                 searchDelay ?\r
2890                                         _fnThrottle( searchFn, searchDelay ) :\r
2891                                         searchFn\r
2892                         )\r
2893                         .bind( 'keypress.DT', function(e) {\r
2894                                 /* Prevent form submission */\r
2895                                 if ( e.keyCode == 13 ) {\r
2896                                         return false;\r
2897                                 }\r
2898                         } )\r
2899                         .attr('aria-controls', tableId);\r
2900         \r
2901                 // Update the input elements whenever the table is filtered\r
2902                 $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {\r
2903                         if ( settings === s ) {\r
2904                                 // IE9 throws an 'unknown error' if document.activeElement is used\r
2905                                 // inside an iframe or frame...\r
2906                                 try {\r
2907                                         if ( jqFilter[0] !== document.activeElement ) {\r
2908                                                 jqFilter.val( previousSearch.sSearch );\r
2909                                         }\r
2910                                 }\r
2911                                 catch ( e ) {}\r
2912                         }\r
2913                 } );\r
2914         \r
2915                 return filter[0];\r
2916         }\r
2917         \r
2918         \r
2919         /**\r
2920          * Filter the table using both the global filter and column based filtering\r
2921          *  @param {object} oSettings dataTables settings object\r
2922          *  @param {object} oSearch search information\r
2923          *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)\r
2924          *  @memberof DataTable#oApi\r
2925          */\r
2926         function _fnFilterComplete ( oSettings, oInput, iForce )\r
2927         {\r
2928                 var oPrevSearch = oSettings.oPreviousSearch;\r
2929                 var aoPrevSearch = oSettings.aoPreSearchCols;\r
2930                 var fnSaveFilter = function ( oFilter ) {\r
2931                         /* Save the filtering values */\r
2932                         oPrevSearch.sSearch = oFilter.sSearch;\r
2933                         oPrevSearch.bRegex = oFilter.bRegex;\r
2934                         oPrevSearch.bSmart = oFilter.bSmart;\r
2935                         oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;\r
2936                 };\r
2937                 var fnRegex = function ( o ) {\r
2938                         // Backwards compatibility with the bEscapeRegex option\r
2939                         return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;\r
2940                 };\r
2941         \r
2942                 // Resolve any column types that are unknown due to addition or invalidation\r
2943                 // @todo As per sort - can this be moved into an event handler?\r
2944                 _fnColumnTypes( oSettings );\r
2945         \r
2946                 /* In server-side processing all filtering is done by the server, so no point hanging around here */\r
2947                 if ( _fnDataSource( oSettings ) != 'ssp' )\r
2948                 {\r
2949                         /* Global filter */\r
2950                         _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );\r
2951                         fnSaveFilter( oInput );\r
2952         \r
2953                         /* Now do the individual column filter */\r
2954                         for ( var i=0 ; i<aoPrevSearch.length ; i++ )\r
2955                         {\r
2956                                 _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),\r
2957                                         aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );\r
2958                         }\r
2959         \r
2960                         /* Custom filtering */\r
2961                         _fnFilterCustom( oSettings );\r
2962                 }\r
2963                 else\r
2964                 {\r
2965                         fnSaveFilter( oInput );\r
2966                 }\r
2967         \r
2968                 /* Tell the draw function we have been filtering */\r
2969                 oSettings.bFiltered = true;\r
2970                 _fnCallbackFire( oSettings, null, 'search', [oSettings] );\r
2971         }\r
2972         \r
2973         \r
2974         /**\r
2975          * Apply custom filtering functions\r
2976          *  @param {object} oSettings dataTables settings object\r
2977          *  @memberof DataTable#oApi\r
2978          */\r
2979         function _fnFilterCustom( settings )\r
2980         {\r
2981                 var filters = DataTable.ext.search;\r
2982                 var displayRows = settings.aiDisplay;\r
2983                 var row, rowIdx;\r
2984         \r
2985                 for ( var i=0, ien=filters.length ; i<ien ; i++ ) {\r
2986                         var rows = [];\r
2987         \r
2988                         // Loop over each row and see if it should be included\r
2989                         for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {\r
2990                                 rowIdx = displayRows[ j ];\r
2991                                 row = settings.aoData[ rowIdx ];\r
2992         \r
2993                                 if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {\r
2994                                         rows.push( rowIdx );\r
2995                                 }\r
2996                         }\r
2997         \r
2998                         // So the array reference doesn't break set the results into the\r
2999                         // existing array\r
3000                         displayRows.length = 0;\r
3001                         $.merge( displayRows, rows );\r
3002                 }\r
3003         }\r
3004         \r
3005         \r
3006         /**\r
3007          * Filter the table on a per-column basis\r
3008          *  @param {object} oSettings dataTables settings object\r
3009          *  @param {string} sInput string to filter on\r
3010          *  @param {int} iColumn column to filter\r
3011          *  @param {bool} bRegex treat search string as a regular expression or not\r
3012          *  @param {bool} bSmart use smart filtering or not\r
3013          *  @param {bool} bCaseInsensitive Do case insenstive matching or not\r
3014          *  @memberof DataTable#oApi\r
3015          */\r
3016         function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )\r
3017         {\r
3018                 if ( searchStr === '' ) {\r
3019                         return;\r
3020                 }\r
3021         \r
3022                 var data;\r
3023                 var display = settings.aiDisplay;\r
3024                 var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );\r
3025         \r
3026                 for ( var i=display.length-1 ; i>=0 ; i-- ) {\r
3027                         data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];\r
3028         \r
3029                         if ( ! rpSearch.test( data ) ) {\r
3030                                 display.splice( i, 1 );\r
3031                         }\r
3032                 }\r
3033         }\r
3034         \r
3035         \r
3036         /**\r
3037          * Filter the data table based on user input and draw the table\r
3038          *  @param {object} settings dataTables settings object\r
3039          *  @param {string} input string to filter on\r
3040          *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)\r
3041          *  @param {bool} regex treat as a regular expression or not\r
3042          *  @param {bool} smart perform smart filtering or not\r
3043          *  @param {bool} caseInsensitive Do case insenstive matching or not\r
3044          *  @memberof DataTable#oApi\r
3045          */\r
3046         function _fnFilter( settings, input, force, regex, smart, caseInsensitive )\r
3047         {\r
3048                 var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );\r
3049                 var prevSearch = settings.oPreviousSearch.sSearch;\r
3050                 var displayMaster = settings.aiDisplayMaster;\r
3051                 var display, invalidated, i;\r
3052         \r
3053                 // Need to take account of custom filtering functions - always filter\r
3054                 if ( DataTable.ext.search.length !== 0 ) {\r
3055                         force = true;\r
3056                 }\r
3057         \r
3058                 // Check if any of the rows were invalidated\r
3059                 invalidated = _fnFilterData( settings );\r
3060         \r
3061                 // If the input is blank - we just want the full data set\r
3062                 if ( input.length <= 0 ) {\r
3063                         settings.aiDisplay = displayMaster.slice();\r
3064                 }\r
3065                 else {\r
3066                         // New search - start from the master array\r
3067                         if ( invalidated ||\r
3068                                  force ||\r
3069                                  prevSearch.length > input.length ||\r
3070                                  input.indexOf(prevSearch) !== 0 ||\r
3071                                  settings.bSorted // On resort, the display master needs to be\r
3072                                                   // re-filtered since indexes will have changed\r
3073                         ) {\r
3074                                 settings.aiDisplay = displayMaster.slice();\r
3075                         }\r
3076         \r
3077                         // Search the display array\r
3078                         display = settings.aiDisplay;\r
3079         \r
3080                         for ( i=display.length-1 ; i>=0 ; i-- ) {\r
3081                                 if ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {\r
3082                                         display.splice( i, 1 );\r
3083                                 }\r
3084                         }\r
3085                 }\r
3086         }\r
3087         \r
3088         \r
3089         /**\r
3090          * Build a regular expression object suitable for searching a table\r
3091          *  @param {string} sSearch string to search for\r
3092          *  @param {bool} bRegex treat as a regular expression or not\r
3093          *  @param {bool} bSmart perform smart filtering or not\r
3094          *  @param {bool} bCaseInsensitive Do case insensitive matching or not\r
3095          *  @returns {RegExp} constructed object\r
3096          *  @memberof DataTable#oApi\r
3097          */\r
3098         function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )\r
3099         {\r
3100                 search = regex ?\r
3101                         search :\r
3102                         _fnEscapeRegex( search );\r
3103                 \r
3104                 if ( smart ) {\r
3105                         /* For smart filtering we want to allow the search to work regardless of\r
3106                          * word order. We also want double quoted text to be preserved, so word\r
3107                          * order is important - a la google. So this is what we want to\r
3108                          * generate:\r
3109                          * \r
3110                          * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$\r
3111                          */\r
3112                         var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) {\r
3113                                 if ( word.charAt(0) === '"' ) {\r
3114                                         var m = word.match( /^"(.*)"$/ );\r
3115                                         word = m ? m[1] : word;\r
3116                                 }\r
3117         \r
3118                                 return word.replace('"', '');\r
3119                         } );\r
3120         \r
3121                         search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';\r
3122                 }\r
3123         \r
3124                 return new RegExp( search, caseInsensitive ? 'i' : '' );\r
3125         }\r
3126         \r
3127         \r
3128         /**\r
3129          * Escape a string such that it can be used in a regular expression\r
3130          *  @param {string} sVal string to escape\r
3131          *  @returns {string} escaped string\r
3132          *  @memberof DataTable#oApi\r
3133          */\r
3134         function _fnEscapeRegex ( sVal )\r
3135         {\r
3136                 return sVal.replace( _re_escape_regex, '\\$1' );\r
3137         }\r
3138         \r
3139         \r
3140         \r
3141         var __filter_div = $('<div>')[0];\r
3142         var __filter_div_textContent = __filter_div.textContent !== undefined;\r
3143         \r
3144         // Update the filtering data for each row if needed (by invalidation or first run)\r
3145         function _fnFilterData ( settings )\r
3146         {\r
3147                 var columns = settings.aoColumns;\r
3148                 var column;\r
3149                 var i, j, ien, jen, filterData, cellData, row;\r
3150                 var fomatters = DataTable.ext.type.search;\r
3151                 var wasInvalidated = false;\r
3152         \r
3153                 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {\r
3154                         row = settings.aoData[i];\r
3155         \r
3156                         if ( ! row._aFilterData ) {\r
3157                                 filterData = [];\r
3158         \r
3159                                 for ( j=0, jen=columns.length ; j<jen ; j++ ) {\r
3160                                         column = columns[j];\r
3161         \r
3162                                         if ( column.bSearchable ) {\r
3163                                                 cellData = _fnGetCellData( settings, i, j, 'filter' );\r
3164         \r
3165                                                 if ( fomatters[ column.sType ] ) {\r
3166                                                         cellData = fomatters[ column.sType ]( cellData );\r
3167                                                 }\r
3168         \r
3169                                                 // Search in DataTables 1.10 is string based. In 1.11 this\r
3170                                                 // should be altered to also allow strict type checking.\r
3171                                                 if ( cellData === null ) {\r
3172                                                         cellData = '';\r
3173                                                 }\r
3174         \r
3175                                                 if ( typeof cellData !== 'string' && cellData.toString ) {\r
3176                                                         cellData = cellData.toString();\r
3177                                                 }\r
3178                                         }\r
3179                                         else {\r
3180                                                 cellData = '';\r
3181                                         }\r
3182         \r
3183                                         // If it looks like there is an HTML entity in the string,\r
3184                                         // attempt to decode it so sorting works as expected. Note that\r
3185                                         // we could use a single line of jQuery to do this, but the DOM\r
3186                                         // method used here is much faster http://jsperf.com/html-decode\r
3187                                         if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {\r
3188                                                 __filter_div.innerHTML = cellData;\r
3189                                                 cellData = __filter_div_textContent ?\r
3190                                                         __filter_div.textContent :\r
3191                                                         __filter_div.innerText;\r
3192                                         }\r
3193         \r
3194                                         if ( cellData.replace ) {\r
3195                                                 cellData = cellData.replace(/[\r\n]/g, '');\r
3196                                         }\r
3197         \r
3198                                         filterData.push( cellData );\r
3199                                 }\r
3200         \r
3201                                 row._aFilterData = filterData;\r
3202                                 row._sFilterRow = filterData.join('  ');\r
3203                                 wasInvalidated = true;\r
3204                         }\r
3205                 }\r
3206         \r
3207                 return wasInvalidated;\r
3208         }\r
3209         \r
3210         \r
3211         /**\r
3212          * Convert from the internal Hungarian notation to camelCase for external\r
3213          * interaction\r
3214          *  @param {object} obj Object to convert\r
3215          *  @returns {object} Inverted object\r
3216          *  @memberof DataTable#oApi\r
3217          */\r
3218         function _fnSearchToCamel ( obj )\r
3219         {\r
3220                 return {\r
3221                         search:          obj.sSearch,\r
3222                         smart:           obj.bSmart,\r
3223                         regex:           obj.bRegex,\r
3224                         caseInsensitive: obj.bCaseInsensitive\r
3225                 };\r
3226         }\r
3227         \r
3228         \r
3229         \r
3230         /**\r
3231          * Convert from camelCase notation to the internal Hungarian. We could use the\r
3232          * Hungarian convert function here, but this is cleaner\r
3233          *  @param {object} obj Object to convert\r
3234          *  @returns {object} Inverted object\r
3235          *  @memberof DataTable#oApi\r
3236          */\r
3237         function _fnSearchToHung ( obj )\r
3238         {\r
3239                 return {\r
3240                         sSearch:          obj.search,\r
3241                         bSmart:           obj.smart,\r
3242                         bRegex:           obj.regex,\r
3243                         bCaseInsensitive: obj.caseInsensitive\r
3244                 };\r
3245         }\r
3246         \r
3247         /**\r
3248          * Generate the node required for the info display\r
3249          *  @param {object} oSettings dataTables settings object\r
3250          *  @returns {node} Information element\r
3251          *  @memberof DataTable#oApi\r
3252          */\r
3253         function _fnFeatureHtmlInfo ( settings )\r
3254         {\r
3255                 var\r
3256                         tid = settings.sTableId,\r
3257                         nodes = settings.aanFeatures.i,\r
3258                         n = $('<div/>', {\r
3259                                 'class': settings.oClasses.sInfo,\r
3260                                 'id': ! nodes ? tid+'_info' : null\r
3261                         } );\r
3262         \r
3263                 if ( ! nodes ) {\r
3264                         // Update display on each draw\r
3265                         settings.aoDrawCallback.push( {\r
3266                                 "fn": _fnUpdateInfo,\r
3267                                 "sName": "information"\r
3268                         } );\r
3269         \r
3270                         n\r
3271                                 .attr( 'role', 'status' )\r
3272                                 .attr( 'aria-live', 'polite' );\r
3273         \r
3274                         // Table is described by our info div\r
3275                         $(settings.nTable).attr( 'aria-describedby', tid+'_info' );\r
3276                 }\r
3277         \r
3278                 return n[0];\r
3279         }\r
3280         \r
3281         \r
3282         /**\r
3283          * Update the information elements in the display\r
3284          *  @param {object} settings dataTables settings object\r
3285          *  @memberof DataTable#oApi\r
3286          */\r
3287         function _fnUpdateInfo ( settings )\r
3288         {\r
3289                 /* Show information about the table */\r
3290                 var nodes = settings.aanFeatures.i;\r
3291                 if ( nodes.length === 0 ) {\r
3292                         return;\r
3293                 }\r
3294         \r
3295                 var\r
3296                         lang  = settings.oLanguage,\r
3297                         start = settings._iDisplayStart+1,\r
3298                         end   = settings.fnDisplayEnd(),\r
3299                         max   = settings.fnRecordsTotal(),\r
3300                         total = settings.fnRecordsDisplay(),\r
3301                         out   = total ?\r
3302                                 lang.sInfo :\r
3303                                 lang.sInfoEmpty;\r
3304         \r
3305                 if ( total !== max ) {\r
3306                         /* Record set after filtering */\r
3307                         out += ' ' + lang.sInfoFiltered;\r
3308                 }\r
3309         \r
3310                 // Convert the macros\r
3311                 out += lang.sInfoPostFix;\r
3312                 out = _fnInfoMacros( settings, out );\r
3313         \r
3314                 var callback = lang.fnInfoCallback;\r
3315                 if ( callback !== null ) {\r
3316                         out = callback.call( settings.oInstance,\r
3317                                 settings, start, end, max, total, out\r
3318                         );\r
3319                 }\r
3320         \r
3321                 $(nodes).html( out );\r
3322         }\r
3323         \r
3324         \r
3325         function _fnInfoMacros ( settings, str )\r
3326         {\r
3327                 // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only\r
3328                 // internally\r
3329                 var\r
3330                         formatter  = settings.fnFormatNumber,\r
3331                         start      = settings._iDisplayStart+1,\r
3332                         len        = settings._iDisplayLength,\r
3333                         vis        = settings.fnRecordsDisplay(),\r
3334                         all        = len === -1;\r
3335         \r
3336                 return str.\r
3337                         replace(/_START_/g, formatter.call( settings, start ) ).\r
3338                         replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).\r
3339                         replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).\r
3340                         replace(/_TOTAL_/g, formatter.call( settings, vis ) ).\r
3341                         replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).\r
3342                         replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );\r
3343         }\r
3344         \r
3345         \r
3346         \r
3347         /**\r
3348          * Draw the table for the first time, adding all required features\r
3349          *  @param {object} settings dataTables settings object\r
3350          *  @memberof DataTable#oApi\r
3351          */\r
3352         function _fnInitialise ( settings )\r
3353         {\r
3354                 var i, iLen, iAjaxStart=settings.iInitDisplayStart;\r
3355                 var columns = settings.aoColumns, column;\r
3356                 var features = settings.oFeatures;\r
3357                 var deferLoading = settings.bDeferLoading; // value modified by the draw\r
3358         \r
3359                 /* Ensure that the table data is fully initialised */\r
3360                 if ( ! settings.bInitialised ) {\r
3361                         setTimeout( function(){ _fnInitialise( settings ); }, 200 );\r
3362                         return;\r
3363                 }\r
3364         \r
3365                 /* Show the display HTML options */\r
3366                 _fnAddOptionsHtml( settings );\r
3367         \r
3368                 /* Build and draw the header / footer for the table */\r
3369                 _fnBuildHead( settings );\r
3370                 _fnDrawHead( settings, settings.aoHeader );\r
3371                 _fnDrawHead( settings, settings.aoFooter );\r
3372         \r
3373                 /* Okay to show that something is going on now */\r
3374                 _fnProcessingDisplay( settings, true );\r
3375         \r
3376                 /* Calculate sizes for columns */\r
3377                 if ( features.bAutoWidth ) {\r
3378                         _fnCalculateColumnWidths( settings );\r
3379                 }\r
3380         \r
3381                 for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {\r
3382                         column = columns[i];\r
3383         \r
3384                         if ( column.sWidth ) {\r
3385                                 column.nTh.style.width = _fnStringToCss( column.sWidth );\r
3386                         }\r
3387                 }\r
3388         \r
3389                 _fnCallbackFire( settings, null, 'preInit', [settings] );\r
3390         \r
3391                 // If there is default sorting required - let's do it. The sort function\r
3392                 // will do the drawing for us. Otherwise we draw the table regardless of the\r
3393                 // Ajax source - this allows the table to look initialised for Ajax sourcing\r
3394                 // data (show 'loading' message possibly)\r
3395                 _fnReDraw( settings );\r
3396         \r
3397                 // Server-side processing init complete is done by _fnAjaxUpdateDraw\r
3398                 var dataSrc = _fnDataSource( settings );\r
3399                 if ( dataSrc != 'ssp' || deferLoading ) {\r
3400                         // if there is an ajax source load the data\r
3401                         if ( dataSrc == 'ajax' ) {\r
3402                                 _fnBuildAjax( settings, [], function(json) {\r
3403                                         var aData = _fnAjaxDataSrc( settings, json );\r
3404         \r
3405                                         // Got the data - add it to the table\r
3406                                         for ( i=0 ; i<aData.length ; i++ ) {\r
3407                                                 _fnAddData( settings, aData[i] );\r
3408                                         }\r
3409         \r
3410                                         // Reset the init display for cookie saving. We've already done\r
3411                                         // a filter, and therefore cleared it before. So we need to make\r
3412                                         // it appear 'fresh'\r
3413                                         settings.iInitDisplayStart = iAjaxStart;\r
3414         \r
3415                                         _fnReDraw( settings );\r
3416         \r
3417                                         _fnProcessingDisplay( settings, false );\r
3418                                         _fnInitComplete( settings, json );\r
3419                                 }, settings );\r
3420                         }\r
3421                         else {\r
3422                                 _fnProcessingDisplay( settings, false );\r
3423                                 _fnInitComplete( settings );\r
3424                         }\r
3425                 }\r
3426         }\r
3427         \r
3428         \r
3429         /**\r
3430          * Draw the table for the first time, adding all required features\r
3431          *  @param {object} oSettings dataTables settings object\r
3432          *  @param {object} [json] JSON from the server that completed the table, if using Ajax source\r
3433          *    with client-side processing (optional)\r
3434          *  @memberof DataTable#oApi\r
3435          */\r
3436         function _fnInitComplete ( settings, json )\r
3437         {\r
3438                 settings._bInitComplete = true;\r
3439         \r
3440                 // When data was added after the initialisation (data or Ajax) we need to\r
3441                 // calculate the column sizing\r
3442                 if ( json || settings.oInit.aaData ) {\r
3443                         _fnAdjustColumnSizing( settings );\r
3444                 }\r
3445         \r
3446                 _fnCallbackFire( settings, null, 'plugin-init', [settings, json] );\r
3447                 _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );\r
3448         }\r
3449         \r
3450         \r
3451         function _fnLengthChange ( settings, val )\r
3452         {\r
3453                 var len = parseInt( val, 10 );\r
3454                 settings._iDisplayLength = len;\r
3455         \r
3456                 _fnLengthOverflow( settings );\r
3457         \r
3458                 // Fire length change event\r
3459                 _fnCallbackFire( settings, null, 'length', [settings, len] );\r
3460         }\r
3461         \r
3462         \r
3463         /**\r
3464          * Generate the node required for user display length changing\r
3465          *  @param {object} settings dataTables settings object\r
3466          *  @returns {node} Display length feature node\r
3467          *  @memberof DataTable#oApi\r
3468          */\r
3469         function _fnFeatureHtmlLength ( settings )\r
3470         {\r
3471                 var\r
3472                         classes  = settings.oClasses,\r
3473                         tableId  = settings.sTableId,\r
3474                         menu     = settings.aLengthMenu,\r
3475                         d2       = $.isArray( menu[0] ),\r
3476                         lengths  = d2 ? menu[0] : menu,\r
3477                         language = d2 ? menu[1] : menu;\r
3478         \r
3479                 var select = $('<select/>', {\r
3480                         'name':          tableId+'_length',\r
3481                         'aria-controls': tableId,\r
3482                         'class':         classes.sLengthSelect\r
3483                 } );\r
3484         \r
3485                 for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {\r
3486                         select[0][ i ] = new Option( language[i], lengths[i] );\r
3487                 }\r
3488         \r
3489                 var div = $('<div><label/></div>').addClass( classes.sLength );\r
3490                 if ( ! settings.aanFeatures.l ) {\r
3491                         div[0].id = tableId+'_length';\r
3492                 }\r
3493         \r
3494                 div.children().append(\r
3495                         settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )\r
3496                 );\r
3497         \r
3498                 // Can't use `select` variable as user might provide their own and the\r
3499                 // reference is broken by the use of outerHTML\r
3500                 $('select', div)\r
3501                         .val( settings._iDisplayLength )\r
3502                         .bind( 'change.DT', function(e) {\r
3503                                 _fnLengthChange( settings, $(this).val() );\r
3504                                 _fnDraw( settings );\r
3505                         } );\r
3506         \r
3507                 // Update node value whenever anything changes the table's length\r
3508                 $(settings.nTable).bind( 'length.dt.DT', function (e, s, len) {\r
3509                         if ( settings === s ) {\r
3510                                 $('select', div).val( len );\r
3511                         }\r
3512                 } );\r
3513         \r
3514                 return div[0];\r
3515         }\r
3516         \r
3517         \r
3518         \r
3519         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\r
3520          * Note that most of the paging logic is done in\r
3521          * DataTable.ext.pager\r
3522          */\r
3523         \r
3524         /**\r
3525          * Generate the node required for default pagination\r
3526          *  @param {object} oSettings dataTables settings object\r
3527          *  @returns {node} Pagination feature node\r
3528          *  @memberof DataTable#oApi\r
3529          */\r
3530         function _fnFeatureHtmlPaginate ( settings )\r
3531         {\r
3532                 var\r
3533                         type   = settings.sPaginationType,\r
3534                         plugin = DataTable.ext.pager[ type ],\r
3535                         modern = typeof plugin === 'function',\r
3536                         redraw = function( settings ) {\r
3537                                 _fnDraw( settings );\r
3538                         },\r
3539                         node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],\r
3540                         features = settings.aanFeatures;\r
3541         \r
3542                 if ( ! modern ) {\r
3543                         plugin.fnInit( settings, node, redraw );\r
3544                 }\r
3545         \r
3546                 /* Add a draw callback for the pagination on first instance, to update the paging display */\r
3547                 if ( ! features.p )\r
3548                 {\r
3549                         node.id = settings.sTableId+'_paginate';\r
3550         \r
3551                         settings.aoDrawCallback.push( {\r
3552                                 "fn": function( settings ) {\r
3553                                         if ( modern ) {\r
3554                                                 var\r
3555                                                         start      = settings._iDisplayStart,\r
3556                                                         len        = settings._iDisplayLength,\r
3557                                                         visRecords = settings.fnRecordsDisplay(),\r
3558                                                         all        = len === -1,\r
3559                                                         page = all ? 0 : Math.ceil( start / len ),\r
3560                                                         pages = all ? 1 : Math.ceil( visRecords / len ),\r
3561                                                         buttons = plugin(page, pages),\r
3562                                                         i, ien;\r
3563         \r
3564                                                 for ( i=0, ien=features.p.length ; i<ien ; i++ ) {\r
3565                                                         _fnRenderer( settings, 'pageButton' )(\r
3566                                                                 settings, features.p[i], i, buttons, page, pages\r
3567                                                         );\r
3568                                                 }\r
3569                                         }\r
3570                                         else {\r
3571                                                 plugin.fnUpdate( settings, redraw );\r
3572                                         }\r
3573                                 },\r
3574                                 "sName": "pagination"\r
3575                         } );\r
3576                 }\r
3577         \r
3578                 return node;\r
3579         }\r
3580         \r
3581         \r
3582         /**\r
3583          * Alter the display settings to change the page\r
3584          *  @param {object} settings DataTables settings object\r
3585          *  @param {string|int} action Paging action to take: "first", "previous",\r
3586          *    "next" or "last" or page number to jump to (integer)\r
3587          *  @param [bool] redraw Automatically draw the update or not\r
3588          *  @returns {bool} true page has changed, false - no change\r
3589          *  @memberof DataTable#oApi\r
3590          */\r
3591         function _fnPageChange ( settings, action, redraw )\r
3592         {\r
3593                 var\r
3594                         start     = settings._iDisplayStart,\r
3595                         len       = settings._iDisplayLength,\r
3596                         records   = settings.fnRecordsDisplay();\r
3597         \r
3598                 if ( records === 0 || len === -1 )\r
3599                 {\r
3600                         start = 0;\r
3601                 }\r
3602                 else if ( typeof action === "number" )\r
3603                 {\r
3604                         start = action * len;\r
3605         \r
3606                         if ( start > records )\r
3607                         {\r
3608                                 start = 0;\r
3609                         }\r
3610                 }\r
3611                 else if ( action == "first" )\r
3612                 {\r
3613                         start = 0;\r
3614                 }\r
3615                 else if ( action == "previous" )\r
3616                 {\r
3617                         start = len >= 0 ?\r
3618                                 start - len :\r
3619                                 0;\r
3620         \r
3621                         if ( start < 0 )\r
3622                         {\r
3623                           start = 0;\r
3624                         }\r
3625                 }\r
3626                 else if ( action == "next" )\r
3627                 {\r
3628                         if ( start + len < records )\r
3629                         {\r
3630                                 start += len;\r
3631                         }\r
3632                 }\r
3633                 else if ( action == "last" )\r
3634                 {\r
3635                         start = Math.floor( (records-1) / len) * len;\r
3636                 }\r
3637                 else\r
3638                 {\r
3639                         _fnLog( settings, 0, "Unknown paging action: "+action, 5 );\r
3640                 }\r
3641         \r
3642                 var changed = settings._iDisplayStart !== start;\r
3643                 settings._iDisplayStart = start;\r
3644         \r
3645                 if ( changed ) {\r
3646                         _fnCallbackFire( settings, null, 'page', [settings] );\r
3647         \r
3648                         if ( redraw ) {\r
3649                                 _fnDraw( settings );\r
3650                         }\r
3651                 }\r
3652         \r
3653                 return changed;\r
3654         }\r
3655         \r
3656         \r
3657         \r
3658         /**\r
3659          * Generate the node required for the processing node\r
3660          *  @param {object} settings dataTables settings object\r
3661          *  @returns {node} Processing element\r
3662          *  @memberof DataTable#oApi\r
3663          */\r
3664         function _fnFeatureHtmlProcessing ( settings )\r
3665         {\r
3666                 return $('<div/>', {\r
3667                                 'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,\r
3668                                 'class': settings.oClasses.sProcessing\r
3669                         } )\r
3670                         .html( settings.oLanguage.sProcessing )\r
3671                         .insertBefore( settings.nTable )[0];\r
3672         }\r
3673         \r
3674         \r
3675         /**\r
3676          * Display or hide the processing indicator\r
3677          *  @param {object} settings dataTables settings object\r
3678          *  @param {bool} show Show the processing indicator (true) or not (false)\r
3679          *  @memberof DataTable#oApi\r
3680          */\r
3681         function _fnProcessingDisplay ( settings, show )\r
3682         {\r
3683                 if ( settings.oFeatures.bProcessing ) {\r
3684                         $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );\r
3685                 }\r
3686         \r
3687                 _fnCallbackFire( settings, null, 'processing', [settings, show] );\r
3688         }\r
3689         \r
3690         /**\r
3691          * Add any control elements for the table - specifically scrolling\r
3692          *  @param {object} settings dataTables settings object\r
3693          *  @returns {node} Node to add to the DOM\r
3694          *  @memberof DataTable#oApi\r
3695          */\r
3696         function _fnFeatureHtmlTable ( settings )\r
3697         {\r
3698                 var table = $(settings.nTable);\r
3699         \r
3700                 // Add the ARIA grid role to the table\r
3701                 table.attr( 'role', 'grid' );\r
3702         \r
3703                 // Scrolling from here on in\r
3704                 var scroll = settings.oScroll;\r
3705         \r
3706                 if ( scroll.sX === '' && scroll.sY === '' ) {\r
3707                         return settings.nTable;\r
3708                 }\r
3709         \r
3710                 var scrollX = scroll.sX;\r
3711                 var scrollY = scroll.sY;\r
3712                 var classes = settings.oClasses;\r
3713                 var caption = table.children('caption');\r
3714                 var captionSide = caption.length ? caption[0]._captionSide : null;\r
3715                 var headerClone = $( table[0].cloneNode(false) );\r
3716                 var footerClone = $( table[0].cloneNode(false) );\r
3717                 var footer = table.children('tfoot');\r
3718                 var _div = '<div/>';\r
3719                 var size = function ( s ) {\r
3720                         return !s ? null : _fnStringToCss( s );\r
3721                 };\r
3722         \r
3723                 if ( ! footer.length ) {\r
3724                         footer = null;\r
3725                 }\r
3726         \r
3727                 /*\r
3728                  * The HTML structure that we want to generate in this function is:\r
3729                  *  div - scroller\r
3730                  *    div - scroll head\r
3731                  *      div - scroll head inner\r
3732                  *        table - scroll head table\r
3733                  *          thead - thead\r
3734                  *    div - scroll body\r
3735                  *      table - table (master table)\r
3736                  *        thead - thead clone for sizing\r
3737                  *        tbody - tbody\r
3738                  *    div - scroll foot\r
3739                  *      div - scroll foot inner\r
3740                  *        table - scroll foot table\r
3741                  *          tfoot - tfoot\r
3742                  */\r
3743                 var scroller = $( _div, { 'class': classes.sScrollWrapper } )\r
3744                         .append(\r
3745                                 $(_div, { 'class': classes.sScrollHead } )\r
3746                                         .css( {\r
3747                                                 overflow: 'hidden',\r
3748                                                 position: 'relative',\r
3749                                                 border: 0,\r
3750                                                 width: scrollX ? size(scrollX) : '100%'\r
3751                                         } )\r
3752                                         .append(\r
3753                                                 $(_div, { 'class': classes.sScrollHeadInner } )\r
3754                                                         .css( {\r
3755                                                                 'box-sizing': 'content-box',\r
3756                                                                 width: scroll.sXInner || '100%'\r
3757                                                         } )\r
3758                                                         .append(\r
3759                                                                 headerClone\r
3760                                                                         .removeAttr('id')\r
3761                                                                         .css( 'margin-left', 0 )\r
3762                                                                         .append( captionSide === 'top' ? caption : null )\r
3763                                                                         .append(\r
3764                                                                                 table.children('thead')\r
3765                                                                         )\r
3766                                                         )\r
3767                                         )\r
3768                         )\r
3769                         .append(\r
3770                                 $(_div, { 'class': classes.sScrollBody } )\r
3771                                         .css( {\r
3772                                                 position: 'relative',\r
3773                                                 overflow: 'auto',\r
3774                                                 width: size( scrollX )\r
3775                                         } )\r
3776                                         .append( table )\r
3777                         );\r
3778         \r
3779                 if ( footer ) {\r
3780                         scroller.append(\r
3781                                 $(_div, { 'class': classes.sScrollFoot } )\r
3782                                         .css( {\r
3783                                                 overflow: 'hidden',\r
3784                                                 border: 0,\r
3785                                                 width: scrollX ? size(scrollX) : '100%'\r
3786                                         } )\r
3787                                         .append(\r
3788                                                 $(_div, { 'class': classes.sScrollFootInner } )\r
3789                                                         .append(\r
3790                                                                 footerClone\r
3791                                                                         .removeAttr('id')\r
3792                                                                         .css( 'margin-left', 0 )\r
3793                                                                         .append( captionSide === 'bottom' ? caption : null )\r
3794                                                                         .append(\r
3795                                                                                 table.children('tfoot')\r
3796                                                                         )\r
3797                                                         )\r
3798                                         )\r
3799                         );\r
3800                 }\r
3801         \r
3802                 var children = scroller.children();\r
3803                 var scrollHead = children[0];\r
3804                 var scrollBody = children[1];\r
3805                 var scrollFoot = footer ? children[2] : null;\r
3806         \r
3807                 // When the body is scrolled, then we also want to scroll the headers\r
3808                 if ( scrollX ) {\r
3809                         $(scrollBody).on( 'scroll.DT', function (e) {\r
3810                                 var scrollLeft = this.scrollLeft;\r
3811         \r
3812                                 scrollHead.scrollLeft = scrollLeft;\r
3813         \r
3814                                 if ( footer ) {\r
3815                                         scrollFoot.scrollLeft = scrollLeft;\r
3816                                 }\r
3817                         } );\r
3818                 }\r
3819         \r
3820                 $(scrollBody).css(\r
3821                         scrollY && scroll.bCollapse ? 'max-height' : 'height', \r
3822                         scrollY\r
3823                 );\r
3824         \r
3825                 settings.nScrollHead = scrollHead;\r
3826                 settings.nScrollBody = scrollBody;\r
3827                 settings.nScrollFoot = scrollFoot;\r
3828         \r
3829                 // On redraw - align columns\r
3830                 settings.aoDrawCallback.push( {\r
3831                         "fn": _fnScrollDraw,\r
3832                         "sName": "scrolling"\r
3833                 } );\r
3834         \r
3835                 return scroller[0];\r
3836         }\r
3837         \r
3838         \r
3839         \r
3840         /**\r
3841          * Update the header, footer and body tables for resizing - i.e. column\r
3842          * alignment.\r
3843          *\r
3844          * Welcome to the most horrible function DataTables. The process that this\r
3845          * function follows is basically:\r
3846          *   1. Re-create the table inside the scrolling div\r
3847          *   2. Take live measurements from the DOM\r
3848          *   3. Apply the measurements to align the columns\r
3849          *   4. Clean up\r
3850          *\r
3851          *  @param {object} settings dataTables settings object\r
3852          *  @memberof DataTable#oApi\r
3853          */\r
3854         function _fnScrollDraw ( settings )\r
3855         {\r
3856                 // Given that this is such a monster function, a lot of variables are use\r
3857                 // to try and keep the minimised size as small as possible\r
3858                 var\r
3859                         scroll         = settings.oScroll,\r
3860                         scrollX        = scroll.sX,\r
3861                         scrollXInner   = scroll.sXInner,\r
3862                         scrollY        = scroll.sY,\r
3863                         barWidth       = scroll.iBarWidth,\r
3864                         divHeader      = $(settings.nScrollHead),\r
3865                         divHeaderStyle = divHeader[0].style,\r
3866                         divHeaderInner = divHeader.children('div'),\r
3867                         divHeaderInnerStyle = divHeaderInner[0].style,\r
3868                         divHeaderTable = divHeaderInner.children('table'),\r
3869                         divBodyEl      = settings.nScrollBody,\r
3870                         divBody        = $(divBodyEl),\r
3871                         divBodyStyle   = divBodyEl.style,\r
3872                         divFooter      = $(settings.nScrollFoot),\r
3873                         divFooterInner = divFooter.children('div'),\r
3874                         divFooterTable = divFooterInner.children('table'),\r
3875                         header         = $(settings.nTHead),\r
3876                         table          = $(settings.nTable),\r
3877                         tableEl        = table[0],\r
3878                         tableStyle     = tableEl.style,\r
3879                         footer         = settings.nTFoot ? $(settings.nTFoot) : null,\r
3880                         browser        = settings.oBrowser,\r
3881                         ie67           = browser.bScrollOversize,\r
3882                         dtHeaderCells  = _pluck( settings.aoColumns, 'nTh' ),\r
3883                         headerTrgEls, footerTrgEls,\r
3884                         headerSrcEls, footerSrcEls,\r
3885                         headerCopy, footerCopy,\r
3886                         headerWidths=[], footerWidths=[],\r
3887                         headerContent=[], footerContent=[],\r
3888                         idx, correction, sanityWidth,\r
3889                         zeroOut = function(nSizer) {\r
3890                                 var style = nSizer.style;\r
3891                                 style.paddingTop = "0";\r
3892                                 style.paddingBottom = "0";\r
3893                                 style.borderTopWidth = "0";\r
3894                                 style.borderBottomWidth = "0";\r
3895                                 style.height = 0;\r
3896                         };\r
3897         \r
3898                 // If the scrollbar visibility has changed from the last draw, we need to\r
3899                 // adjust the column sizes as the table width will have changed to account\r
3900                 // for the scrollbar\r
3901                 var scrollBarVis = divBodyEl.scrollHeight > divBodyEl.clientHeight;\r
3902                 \r
3903                 if ( settings.scrollBarVis !== scrollBarVis && settings.scrollBarVis !== undefined ) {\r
3904                         settings.scrollBarVis = scrollBarVis;\r
3905                         _fnAdjustColumnSizing( settings );\r
3906                         return; // adjust column sizing will call this function again\r
3907                 }\r
3908                 else {\r
3909                         settings.scrollBarVis = scrollBarVis;\r
3910                 }\r
3911         \r
3912                 /*\r
3913                  * 1. Re-create the table inside the scrolling div\r
3914                  */\r
3915         \r
3916                 // Remove the old minimised thead and tfoot elements in the inner table\r
3917                 table.children('thead, tfoot').remove();\r
3918         \r
3919                 if ( footer ) {\r
3920                         footerCopy = footer.clone().prependTo( table );\r
3921                         footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized\r
3922                         footerSrcEls = footerCopy.find('tr');\r
3923                 }\r
3924         \r
3925                 // Clone the current header and footer elements and then place it into the inner table\r
3926                 headerCopy = header.clone().prependTo( table );\r
3927                 headerTrgEls = header.find('tr'); // original header is in its own table\r
3928                 headerSrcEls = headerCopy.find('tr');\r
3929                 headerCopy.find('th, td').removeAttr('tabindex');\r
3930         \r
3931         \r
3932                 /*\r
3933                  * 2. Take live measurements from the DOM - do not alter the DOM itself!\r
3934                  */\r
3935         \r
3936                 // Remove old sizing and apply the calculated column widths\r
3937                 // Get the unique column headers in the newly created (cloned) header. We want to apply the\r
3938                 // calculated sizes to this header\r
3939                 if ( ! scrollX )\r
3940                 {\r
3941                         divBodyStyle.width = '100%';\r
3942                         divHeader[0].style.width = '100%';\r
3943                 }\r
3944         \r
3945                 $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {\r
3946                         idx = _fnVisibleToColumnIndex( settings, i );\r
3947                         el.style.width = settings.aoColumns[idx].sWidth;\r
3948                 } );\r
3949         \r
3950                 if ( footer ) {\r
3951                         _fnApplyToChildren( function(n) {\r
3952                                 n.style.width = "";\r
3953                         }, footerSrcEls );\r
3954                 }\r
3955         \r
3956                 // Size the table as a whole\r
3957                 sanityWidth = table.outerWidth();\r
3958                 if ( scrollX === "" ) {\r
3959                         // No x scrolling\r
3960                         tableStyle.width = "100%";\r
3961         \r
3962                         // IE7 will make the width of the table when 100% include the scrollbar\r
3963                         // - which is shouldn't. When there is a scrollbar we need to take this\r
3964                         // into account.\r
3965                         if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||\r
3966                                 divBody.css('overflow-y') == "scroll")\r
3967                         ) {\r
3968                                 tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);\r
3969                         }\r
3970         \r
3971                         // Recalculate the sanity width\r
3972                         sanityWidth = table.outerWidth();\r
3973                 }\r
3974                 else if ( scrollXInner !== "" ) {\r
3975                         // legacy x scroll inner has been given - use it\r
3976                         tableStyle.width = _fnStringToCss(scrollXInner);\r
3977         \r
3978                         // Recalculate the sanity width\r
3979                         sanityWidth = table.outerWidth();\r
3980                 }\r
3981         \r
3982                 // Hidden header should have zero height, so remove padding and borders. Then\r
3983                 // set the width based on the real headers\r
3984         \r
3985                 // Apply all styles in one pass\r
3986                 _fnApplyToChildren( zeroOut, headerSrcEls );\r
3987         \r
3988                 // Read all widths in next pass\r
3989                 _fnApplyToChildren( function(nSizer) {\r
3990                         headerContent.push( nSizer.innerHTML );\r
3991                         headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );\r
3992                 }, headerSrcEls );\r
3993         \r
3994                 // Apply all widths in final pass\r
3995                 _fnApplyToChildren( function(nToSize, i) {\r
3996                         // Only apply widths to the DataTables detected header cells - this\r
3997                         // prevents complex headers from having contradictory sizes applied\r
3998                         if ( $.inArray( nToSize, dtHeaderCells ) !== -1 ) {\r
3999                                 nToSize.style.width = headerWidths[i];\r
4000                         }\r
4001                 }, headerTrgEls );\r
4002         \r
4003                 $(headerSrcEls).height(0);\r
4004         \r
4005                 /* Same again with the footer if we have one */\r
4006                 if ( footer )\r
4007                 {\r
4008                         _fnApplyToChildren( zeroOut, footerSrcEls );\r
4009         \r
4010                         _fnApplyToChildren( function(nSizer) {\r
4011                                 footerContent.push( nSizer.innerHTML );\r
4012                                 footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );\r
4013                         }, footerSrcEls );\r
4014         \r
4015                         _fnApplyToChildren( function(nToSize, i) {\r
4016                                 nToSize.style.width = footerWidths[i];\r
4017                         }, footerTrgEls );\r
4018         \r
4019                         $(footerSrcEls).height(0);\r
4020                 }\r
4021         \r
4022         \r
4023                 /*\r
4024                  * 3. Apply the measurements\r
4025                  */\r
4026         \r
4027                 // "Hide" the header and footer that we used for the sizing. We need to keep\r
4028                 // the content of the cell so that the width applied to the header and body\r
4029                 // both match, but we want to hide it completely. We want to also fix their\r
4030                 // width to what they currently are\r
4031                 _fnApplyToChildren( function(nSizer, i) {\r
4032                         nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';\r
4033                         nSizer.style.width = headerWidths[i];\r
4034                 }, headerSrcEls );\r
4035         \r
4036                 if ( footer )\r
4037                 {\r
4038                         _fnApplyToChildren( function(nSizer, i) {\r
4039                                 nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+footerContent[i]+'</div>';\r
4040                                 nSizer.style.width = footerWidths[i];\r
4041                         }, footerSrcEls );\r
4042                 }\r
4043         \r
4044                 // Sanity check that the table is of a sensible width. If not then we are going to get\r
4045                 // misalignment - try to prevent this by not allowing the table to shrink below its min width\r
4046                 if ( table.outerWidth() < sanityWidth )\r
4047                 {\r
4048                         // The min width depends upon if we have a vertical scrollbar visible or not */\r
4049                         correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||\r
4050                                 divBody.css('overflow-y') == "scroll")) ?\r
4051                                         sanityWidth+barWidth :\r
4052                                         sanityWidth;\r
4053         \r
4054                         // IE6/7 are a law unto themselves...\r
4055                         if ( ie67 && (divBodyEl.scrollHeight >\r
4056                                 divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")\r
4057                         ) {\r
4058                                 tableStyle.width = _fnStringToCss( correction-barWidth );\r
4059                         }\r
4060         \r
4061                         // And give the user a warning that we've stopped the table getting too small\r
4062                         if ( scrollX === "" || scrollXInner !== "" ) {\r
4063                                 _fnLog( settings, 1, 'Possible column misalignment', 6 );\r
4064                         }\r
4065                 }\r
4066                 else\r
4067                 {\r
4068                         correction = '100%';\r
4069                 }\r
4070         \r
4071                 // Apply to the container elements\r
4072                 divBodyStyle.width = _fnStringToCss( correction );\r
4073                 divHeaderStyle.width = _fnStringToCss( correction );\r
4074         \r
4075                 if ( footer ) {\r
4076                         settings.nScrollFoot.style.width = _fnStringToCss( correction );\r
4077                 }\r
4078         \r
4079         \r
4080                 /*\r
4081                  * 4. Clean up\r
4082                  */\r
4083                 if ( ! scrollY ) {\r
4084                         /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting\r
4085                          * the scrollbar height from the visible display, rather than adding it on. We need to\r
4086                          * set the height in order to sort this. Don't want to do it in any other browsers.\r
4087                          */\r
4088                         if ( ie67 ) {\r
4089                                 divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );\r
4090                         }\r
4091                 }\r
4092         \r
4093                 /* Finally set the width's of the header and footer tables */\r
4094                 var iOuterWidth = table.outerWidth();\r
4095                 divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );\r
4096                 divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );\r
4097         \r
4098                 // Figure out if there are scrollbar present - if so then we need a the header and footer to\r
4099                 // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)\r
4100                 var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";\r
4101                 var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );\r
4102                 divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";\r
4103         \r
4104                 if ( footer ) {\r
4105                         divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );\r
4106                         divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );\r
4107                         divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";\r
4108                 }\r
4109         \r
4110                 // Correct DOM ordering for colgroup - comes before the thead\r
4111                 table.children('colgroup').insertBefore( table.children('thead') );\r
4112         \r
4113                 /* Adjust the position of the header in case we loose the y-scrollbar */\r
4114                 divBody.scroll();\r
4115         \r
4116                 // If sorting or filtering has occurred, jump the scrolling back to the top\r
4117                 // only if we aren't holding the position\r
4118                 if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {\r
4119                         divBodyEl.scrollTop = 0;\r
4120                 }\r
4121         }\r
4122         \r
4123         \r
4124         \r
4125         /**\r
4126          * Apply a given function to the display child nodes of an element array (typically\r
4127          * TD children of TR rows\r
4128          *  @param {function} fn Method to apply to the objects\r
4129          *  @param array {nodes} an1 List of elements to look through for display children\r
4130          *  @param array {nodes} an2 Another list (identical structure to the first) - optional\r
4131          *  @memberof DataTable#oApi\r
4132          */\r
4133         function _fnApplyToChildren( fn, an1, an2 )\r
4134         {\r
4135                 var index=0, i=0, iLen=an1.length;\r
4136                 var nNode1, nNode2;\r
4137         \r
4138                 while ( i < iLen ) {\r
4139                         nNode1 = an1[i].firstChild;\r
4140                         nNode2 = an2 ? an2[i].firstChild : null;\r
4141         \r
4142                         while ( nNode1 ) {\r
4143                                 if ( nNode1.nodeType === 1 ) {\r
4144                                         if ( an2 ) {\r
4145                                                 fn( nNode1, nNode2, index );\r
4146                                         }\r
4147                                         else {\r
4148                                                 fn( nNode1, index );\r
4149                                         }\r
4150         \r
4151                                         index++;\r
4152                                 }\r
4153         \r
4154                                 nNode1 = nNode1.nextSibling;\r
4155                                 nNode2 = an2 ? nNode2.nextSibling : null;\r
4156                         }\r
4157         \r
4158                         i++;\r
4159                 }\r
4160         }\r
4161         \r
4162         \r
4163         \r
4164         var __re_html_remove = /<.*?>/g;\r
4165         \r
4166         \r
4167         /**\r
4168          * Calculate the width of columns for the table\r
4169          *  @param {object} oSettings dataTables settings object\r
4170          *  @memberof DataTable#oApi\r
4171          */\r
4172         function _fnCalculateColumnWidths ( oSettings )\r
4173         {\r
4174                 var\r
4175                         table = oSettings.nTable,\r
4176                         columns = oSettings.aoColumns,\r
4177                         scroll = oSettings.oScroll,\r
4178                         scrollY = scroll.sY,\r
4179                         scrollX = scroll.sX,\r
4180                         scrollXInner = scroll.sXInner,\r
4181                         columnCount = columns.length,\r
4182                         visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),\r
4183                         headerCells = $('th', oSettings.nTHead),\r
4184                         tableWidthAttr = table.getAttribute('width'), // from DOM element\r
4185                         tableContainer = table.parentNode,\r
4186                         userInputs = false,\r
4187                         i, column, columnIdx, width, outerWidth,\r
4188                         browser = oSettings.oBrowser,\r
4189                         ie67 = browser.bScrollOversize;\r
4190         \r
4191                 var styleWidth = table.style.width;\r
4192                 if ( styleWidth && styleWidth.indexOf('%') !== -1 ) {\r
4193                         tableWidthAttr = styleWidth;\r
4194                 }\r
4195         \r
4196                 /* Convert any user input sizes into pixel sizes */\r
4197                 for ( i=0 ; i<visibleColumns.length ; i++ ) {\r
4198                         column = columns[ visibleColumns[i] ];\r
4199         \r
4200                         if ( column.sWidth !== null ) {\r
4201                                 column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );\r
4202         \r
4203                                 userInputs = true;\r
4204                         }\r
4205                 }\r
4206         \r
4207                 /* If the number of columns in the DOM equals the number that we have to\r
4208                  * process in DataTables, then we can use the offsets that are created by\r
4209                  * the web- browser. No custom sizes can be set in order for this to happen,\r
4210                  * nor scrolling used\r
4211                  */\r
4212                 if ( ie67 || ! userInputs && ! scrollX && ! scrollY &&\r
4213                      columnCount == _fnVisbleColumns( oSettings ) &&\r
4214                      columnCount == headerCells.length\r
4215                 ) {\r
4216                         for ( i=0 ; i<columnCount ; i++ ) {\r
4217                                 var colIdx = _fnVisibleToColumnIndex( oSettings, i );\r
4218         \r
4219                                 if ( colIdx !== null ) {\r
4220                                         columns[ colIdx ].sWidth = _fnStringToCss( headerCells.eq(i).width() );\r
4221                                 }\r
4222                         }\r
4223                 }\r
4224                 else\r
4225                 {\r
4226                         // Otherwise construct a single row, worst case, table with the widest\r
4227                         // node in the data, assign any user defined widths, then insert it into\r
4228                         // the DOM and allow the browser to do all the hard work of calculating\r
4229                         // table widths\r
4230                         var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table\r
4231                                 .css( 'visibility', 'hidden' )\r
4232                                 .removeAttr( 'id' );\r
4233         \r
4234                         // Clean up the table body\r
4235                         tmpTable.find('tbody tr').remove();\r
4236                         var tr = $('<tr/>').appendTo( tmpTable.find('tbody') );\r
4237         \r
4238                         // Clone the table header and footer - we can't use the header / footer\r
4239                         // from the cloned table, since if scrolling is active, the table's\r
4240                         // real header and footer are contained in different table tags\r
4241                         tmpTable.find('thead, tfoot').remove();\r
4242                         tmpTable\r
4243                                 .append( $(oSettings.nTHead).clone() )\r
4244                                 .append( $(oSettings.nTFoot).clone() );\r
4245         \r
4246                         // Remove any assigned widths from the footer (from scrolling)\r
4247                         tmpTable.find('tfoot th, tfoot td').css('width', '');\r
4248         \r
4249                         // Apply custom sizing to the cloned header\r
4250                         headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );\r
4251         \r
4252                         for ( i=0 ; i<visibleColumns.length ; i++ ) {\r
4253                                 column = columns[ visibleColumns[i] ];\r
4254         \r
4255                                 headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?\r
4256                                         _fnStringToCss( column.sWidthOrig ) :\r
4257                                         '';\r
4258         \r
4259                                 // For scrollX we need to force the column width otherwise the\r
4260                                 // browser will collapse it. If this width is smaller than the\r
4261                                 // width the column requires, then it will have no effect\r
4262                                 if ( column.sWidthOrig && scrollX ) {\r
4263                                         $( headerCells[i] ).append( $('<div/>').css( {\r
4264                                                 width: column.sWidthOrig,\r
4265                                                 margin: 0,\r
4266                                                 padding: 0,\r
4267                                                 border: 0,\r
4268                                                 height: 1\r
4269                                         } ) );\r
4270                                 }\r
4271                         }\r
4272         \r
4273                         // Find the widest cell for each column and put it into the table\r
4274                         if ( oSettings.aoData.length ) {\r
4275                                 for ( i=0 ; i<visibleColumns.length ; i++ ) {\r
4276                                         columnIdx = visibleColumns[i];\r
4277                                         column = columns[ columnIdx ];\r
4278         \r
4279                                         $( _fnGetWidestNode( oSettings, columnIdx ) )\r
4280                                                 .clone( false )\r
4281                                                 .append( column.sContentPadding )\r
4282                                                 .appendTo( tr );\r
4283                                 }\r
4284                         }\r
4285         \r
4286                         // Tidy the temporary table - remove name attributes so there aren't\r
4287                         // duplicated in the dom (radio elements for example)\r
4288                         $('[name]', tmpTable).removeAttr('name');\r
4289         \r
4290                         // Table has been built, attach to the document so we can work with it.\r
4291                         // A holding element is used, positioned at the top of the container\r
4292                         // with minimal height, so it has no effect on if the container scrolls\r
4293                         // or not. Otherwise it might trigger scrolling when it actually isn't\r
4294                         // needed\r
4295                         var holder = $('<div/>').css( scrollX || scrollY ?\r
4296                                         {\r
4297                                                 position: 'absolute',\r
4298                                                 top: 0,\r
4299                                                 left: 0,\r
4300                                                 height: 1,\r
4301                                                 right: 0,\r
4302                                                 overflow: 'hidden'\r
4303                                         } :\r
4304                                         {}\r
4305                                 )\r
4306                                 .append( tmpTable )\r
4307                                 .appendTo( tableContainer );\r
4308         \r
4309                         // When scrolling (X or Y) we want to set the width of the table as \r
4310                         // appropriate. However, when not scrolling leave the table width as it\r
4311                         // is. This results in slightly different, but I think correct behaviour\r
4312                         if ( scrollX && scrollXInner ) {\r
4313                                 tmpTable.width( scrollXInner );\r
4314                         }\r
4315                         else if ( scrollX ) {\r
4316                                 tmpTable.css( 'width', 'auto' );\r
4317                                 tmpTable.removeAttr('width');\r
4318         \r
4319                                 // If there is no width attribute or style, then allow the table to\r
4320                                 // collapse\r
4321                                 if ( tmpTable.width() < tableContainer.clientWidth && tableWidthAttr ) {\r
4322                                         tmpTable.width( tableContainer.clientWidth );\r
4323                                 }\r
4324                         }\r
4325                         else if ( scrollY ) {\r
4326                                 tmpTable.width( tableContainer.clientWidth );\r
4327                         }\r
4328                         else if ( tableWidthAttr ) {\r
4329                                 tmpTable.width( tableWidthAttr );\r
4330                         }\r
4331         \r
4332                         // Get the width of each column in the constructed table - we need to\r
4333                         // know the inner width (so it can be assigned to the other table's\r
4334                         // cells) and the outer width so we can calculate the full width of the\r
4335                         // table. This is safe since DataTables requires a unique cell for each\r
4336                         // column, but if ever a header can span multiple columns, this will\r
4337                         // need to be modified.\r
4338                         var total = 0;\r
4339                         for ( i=0 ; i<visibleColumns.length ; i++ ) {\r
4340                                 var cell = $(headerCells[i]);\r
4341                                 var border = cell.outerWidth() - cell.width();\r
4342         \r
4343                                 // Use getBounding... where possible (not IE8-) because it can give\r
4344                                 // sub-pixel accuracy, which we then want to round up!\r
4345                                 var bounding = browser.bBounding ?\r
4346                                         Math.ceil( headerCells[i].getBoundingClientRect().width ) :\r
4347                                         cell.outerWidth();\r
4348         \r
4349                                 // Total is tracked to remove any sub-pixel errors as the outerWidth\r
4350                                 // of the table might not equal the total given here (IE!).\r
4351                                 total += bounding;\r
4352         \r
4353                                 // Width for each column to use\r
4354                                 columns[ visibleColumns[i] ].sWidth = _fnStringToCss( bounding - border );\r
4355                         }\r
4356         \r
4357                         table.style.width = _fnStringToCss( total );\r
4358         \r
4359                         // Finished with the table - ditch it\r
4360                         holder.remove();\r
4361                 }\r
4362         \r
4363                 // If there is a width attr, we want to attach an event listener which\r
4364                 // allows the table sizing to automatically adjust when the window is\r
4365                 // resized. Use the width attr rather than CSS, since we can't know if the\r
4366                 // CSS is a relative value or absolute - DOM read is always px.\r
4367                 if ( tableWidthAttr ) {\r
4368                         table.style.width = _fnStringToCss( tableWidthAttr );\r
4369                 }\r
4370         \r
4371                 if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {\r
4372                         var bindResize = function () {\r
4373                                 $(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {\r
4374                                         _fnAdjustColumnSizing( oSettings );\r
4375                                 } ) );\r
4376                         };\r
4377         \r
4378                         // IE6/7 will crash if we bind a resize event handler on page load.\r
4379                         // To be removed in 1.11 which drops IE6/7 support\r
4380                         if ( ie67 ) {\r
4381                                 setTimeout( bindResize, 1000 );\r
4382                         }\r
4383                         else {\r
4384                                 bindResize();\r
4385                         }\r
4386         \r
4387                         oSettings._reszEvt = true;\r
4388                 }\r
4389         }\r
4390         \r
4391         \r
4392         /**\r
4393          * Throttle the calls to a function. Arguments and context are maintained for\r
4394          * the throttled function\r
4395          *  @param {function} fn Function to be called\r
4396          *  @param {int} [freq=200] call frequency in mS\r
4397          *  @returns {function} wrapped function\r
4398          *  @memberof DataTable#oApi\r
4399          */\r
4400         function _fnThrottle( fn, freq ) {\r
4401                 var\r
4402                         frequency = freq !== undefined ? freq : 200,\r
4403                         last,\r
4404                         timer;\r
4405         \r
4406                 return function () {\r
4407                         var\r
4408                                 that = this,\r
4409                                 now  = +new Date(),\r
4410                                 args = arguments;\r
4411         \r
4412                         if ( last && now < last + frequency ) {\r
4413                                 clearTimeout( timer );\r
4414         \r
4415                                 timer = setTimeout( function () {\r
4416                                         last = undefined;\r
4417                                         fn.apply( that, args );\r
4418                                 }, frequency );\r
4419                         }\r
4420                         else {\r
4421                                 last = now;\r
4422                                 fn.apply( that, args );\r
4423                         }\r
4424                 };\r
4425         }\r
4426         \r
4427         \r
4428         /**\r
4429          * Convert a CSS unit width to pixels (e.g. 2em)\r
4430          *  @param {string} width width to be converted\r
4431          *  @param {node} parent parent to get the with for (required for relative widths) - optional\r
4432          *  @returns {int} width in pixels\r
4433          *  @memberof DataTable#oApi\r
4434          */\r
4435         function _fnConvertToWidth ( width, parent )\r
4436         {\r
4437                 if ( ! width ) {\r
4438                         return 0;\r
4439                 }\r
4440         \r
4441                 var n = $('<div/>')\r
4442                         .css( 'width', _fnStringToCss( width ) )\r
4443                         .appendTo( parent || document.body );\r
4444         \r
4445                 var val = n[0].offsetWidth;\r
4446                 n.remove();\r
4447         \r
4448                 return val;\r
4449         }\r
4450         \r
4451         \r
4452         /**\r
4453          * Get the widest node\r
4454          *  @param {object} settings dataTables settings object\r
4455          *  @param {int} colIdx column of interest\r
4456          *  @returns {node} widest table node\r
4457          *  @memberof DataTable#oApi\r
4458          */\r
4459         function _fnGetWidestNode( settings, colIdx )\r
4460         {\r
4461                 var idx = _fnGetMaxLenString( settings, colIdx );\r
4462                 if ( idx < 0 ) {\r
4463                         return null;\r
4464                 }\r
4465         \r
4466                 var data = settings.aoData[ idx ];\r
4467                 return ! data.nTr ? // Might not have been created when deferred rendering\r
4468                         $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :\r
4469                         data.anCells[ colIdx ];\r
4470         }\r
4471         \r
4472         \r
4473         /**\r
4474          * Get the maximum strlen for each data column\r
4475          *  @param {object} settings dataTables settings object\r
4476          *  @param {int} colIdx column of interest\r
4477          *  @returns {string} max string length for each column\r
4478          *  @memberof DataTable#oApi\r
4479          */\r
4480         function _fnGetMaxLenString( settings, colIdx )\r
4481         {\r
4482                 var s, max=-1, maxIdx = -1;\r
4483         \r
4484                 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {\r
4485                         s = _fnGetCellData( settings, i, colIdx, 'display' )+'';\r
4486                         s = s.replace( __re_html_remove, '' );\r
4487                         s = s.replace( /&nbsp;/g, ' ' );\r
4488         \r
4489                         if ( s.length > max ) {\r
4490                                 max = s.length;\r
4491                                 maxIdx = i;\r
4492                         }\r
4493                 }\r
4494         \r
4495                 return maxIdx;\r
4496         }\r
4497         \r
4498         \r
4499         /**\r
4500          * Append a CSS unit (only if required) to a string\r
4501          *  @param {string} value to css-ify\r
4502          *  @returns {string} value with css unit\r
4503          *  @memberof DataTable#oApi\r
4504          */\r
4505         function _fnStringToCss( s )\r
4506         {\r
4507                 if ( s === null ) {\r
4508                         return '0px';\r
4509                 }\r
4510         \r
4511                 if ( typeof s == 'number' ) {\r
4512                         return s < 0 ?\r
4513                                 '0px' :\r
4514                                 s+'px';\r
4515                 }\r
4516         \r
4517                 // Check it has a unit character already\r
4518                 return s.match(/\d$/) ?\r
4519                         s+'px' :\r
4520                         s;\r
4521         }\r
4522         \r
4523         \r
4524         \r
4525         function _fnSortFlatten ( settings )\r
4526         {\r
4527                 var\r
4528                         i, iLen, k, kLen,\r
4529                         aSort = [],\r
4530                         aiOrig = [],\r
4531                         aoColumns = settings.aoColumns,\r
4532                         aDataSort, iCol, sType, srcCol,\r
4533                         fixed = settings.aaSortingFixed,\r
4534                         fixedObj = $.isPlainObject( fixed ),\r
4535                         nestedSort = [],\r
4536                         add = function ( a ) {\r
4537                                 if ( a.length && ! $.isArray( a[0] ) ) {\r
4538                                         // 1D array\r
4539                                         nestedSort.push( a );\r
4540                                 }\r
4541                                 else {\r
4542                                         // 2D array\r
4543                                         $.merge( nestedSort, a );\r
4544                                 }\r
4545                         };\r
4546         \r
4547                 // Build the sort array, with pre-fix and post-fix options if they have been\r
4548                 // specified\r
4549                 if ( $.isArray( fixed ) ) {\r
4550                         add( fixed );\r
4551                 }\r
4552         \r
4553                 if ( fixedObj && fixed.pre ) {\r
4554                         add( fixed.pre );\r
4555                 }\r
4556         \r
4557                 add( settings.aaSorting );\r
4558         \r
4559                 if (fixedObj && fixed.post ) {\r
4560                         add( fixed.post );\r
4561                 }\r
4562         \r
4563                 for ( i=0 ; i<nestedSort.length ; i++ )\r
4564                 {\r
4565                         srcCol = nestedSort[i][0];\r
4566                         aDataSort = aoColumns[ srcCol ].aDataSort;\r
4567         \r
4568                         for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )\r
4569                         {\r
4570                                 iCol = aDataSort[k];\r
4571                                 sType = aoColumns[ iCol ].sType || 'string';\r
4572         \r
4573                                 if ( nestedSort[i]._idx === undefined ) {\r
4574                                         nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting );\r
4575                                 }\r
4576         \r
4577                                 aSort.push( {\r
4578                                         src:       srcCol,\r
4579                                         col:       iCol,\r
4580                                         dir:       nestedSort[i][1],\r
4581                                         index:     nestedSort[i]._idx,\r
4582                                         type:      sType,\r
4583                                         formatter: DataTable.ext.type.order[ sType+"-pre" ]\r
4584                                 } );\r
4585                         }\r
4586                 }\r
4587         \r
4588                 return aSort;\r
4589         }\r
4590         \r
4591         /**\r
4592          * Change the order of the table\r
4593          *  @param {object} oSettings dataTables settings object\r
4594          *  @memberof DataTable#oApi\r
4595          *  @todo This really needs split up!\r
4596          */\r
4597         function _fnSort ( oSettings )\r
4598         {\r
4599                 var\r
4600                         i, ien, iLen, j, jLen, k, kLen,\r
4601                         sDataType, nTh,\r
4602                         aiOrig = [],\r
4603                         oExtSort = DataTable.ext.type.order,\r
4604                         aoData = oSettings.aoData,\r
4605                         aoColumns = oSettings.aoColumns,\r
4606                         aDataSort, data, iCol, sType, oSort,\r
4607                         formatters = 0,\r
4608                         sortCol,\r
4609                         displayMaster = oSettings.aiDisplayMaster,\r
4610                         aSort;\r
4611         \r
4612                 // Resolve any column types that are unknown due to addition or invalidation\r
4613                 // @todo Can this be moved into a 'data-ready' handler which is called when\r
4614                 //   data is going to be used in the table?\r
4615                 _fnColumnTypes( oSettings );\r
4616         \r
4617                 aSort = _fnSortFlatten( oSettings );\r
4618         \r
4619                 for ( i=0, ien=aSort.length ; i<ien ; i++ ) {\r
4620                         sortCol = aSort[i];\r
4621         \r
4622                         // Track if we can use the fast sort algorithm\r
4623                         if ( sortCol.formatter ) {\r
4624                                 formatters++;\r
4625                         }\r
4626         \r
4627                         // Load the data needed for the sort, for each cell\r
4628                         _fnSortData( oSettings, sortCol.col );\r
4629                 }\r
4630         \r
4631                 /* No sorting required if server-side or no sorting array */\r
4632                 if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )\r
4633                 {\r
4634                         // Create a value - key array of the current row positions such that we can use their\r
4635                         // current position during the sort, if values match, in order to perform stable sorting\r
4636                         for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {\r
4637                                 aiOrig[ displayMaster[i] ] = i;\r
4638                         }\r
4639         \r
4640                         /* Do the sort - here we want multi-column sorting based on a given data source (column)\r
4641                          * and sorting function (from oSort) in a certain direction. It's reasonably complex to\r
4642                          * follow on it's own, but this is what we want (example two column sorting):\r
4643                          *  fnLocalSorting = function(a,b){\r
4644                          *    var iTest;\r
4645                          *    iTest = oSort['string-asc']('data11', 'data12');\r
4646                          *      if (iTest !== 0)\r
4647                          *        return iTest;\r
4648                          *    iTest = oSort['numeric-desc']('data21', 'data22');\r
4649                          *    if (iTest !== 0)\r
4650                          *      return iTest;\r
4651                          *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );\r
4652                          *  }\r
4653                          * Basically we have a test for each sorting column, if the data in that column is equal,\r
4654                          * test the next column. If all columns match, then we use a numeric sort on the row\r
4655                          * positions in the original data array to provide a stable sort.\r
4656                          *\r
4657                          * Note - I know it seems excessive to have two sorting methods, but the first is around\r
4658                          * 15% faster, so the second is only maintained for backwards compatibility with sorting\r
4659                          * methods which do not have a pre-sort formatting function.\r
4660                          */\r
4661                         if ( formatters === aSort.length ) {\r
4662                                 // All sort types have formatting functions\r
4663                                 displayMaster.sort( function ( a, b ) {\r
4664                                         var\r
4665                                                 x, y, k, test, sort,\r
4666                                                 len=aSort.length,\r
4667                                                 dataA = aoData[a]._aSortData,\r
4668                                                 dataB = aoData[b]._aSortData;\r
4669         \r
4670                                         for ( k=0 ; k<len ; k++ ) {\r
4671                                                 sort = aSort[k];\r
4672         \r
4673                                                 x = dataA[ sort.col ];\r
4674                                                 y = dataB[ sort.col ];\r
4675         \r
4676                                                 test = x<y ? -1 : x>y ? 1 : 0;\r
4677                                                 if ( test !== 0 ) {\r
4678                                                         return sort.dir === 'asc' ? test : -test;\r
4679                                                 }\r
4680                                         }\r
4681         \r
4682                                         x = aiOrig[a];\r
4683                                         y = aiOrig[b];\r
4684                                         return x<y ? -1 : x>y ? 1 : 0;\r
4685                                 } );\r
4686                         }\r
4687                         else {\r
4688                                 // Depreciated - remove in 1.11 (providing a plug-in option)\r
4689                                 // Not all sort types have formatting methods, so we have to call their sorting\r
4690                                 // methods.\r
4691                                 displayMaster.sort( function ( a, b ) {\r
4692                                         var\r
4693                                                 x, y, k, l, test, sort, fn,\r
4694                                                 len=aSort.length,\r
4695                                                 dataA = aoData[a]._aSortData,\r
4696                                                 dataB = aoData[b]._aSortData;\r
4697         \r
4698                                         for ( k=0 ; k<len ; k++ ) {\r
4699                                                 sort = aSort[k];\r
4700         \r
4701                                                 x = dataA[ sort.col ];\r
4702                                                 y = dataB[ sort.col ];\r
4703         \r
4704                                                 fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];\r
4705                                                 test = fn( x, y );\r
4706                                                 if ( test !== 0 ) {\r
4707                                                         return test;\r
4708                                                 }\r
4709                                         }\r
4710         \r
4711                                         x = aiOrig[a];\r
4712                                         y = aiOrig[b];\r
4713                                         return x<y ? -1 : x>y ? 1 : 0;\r
4714                                 } );\r
4715                         }\r
4716                 }\r
4717         \r
4718                 /* Tell the draw function that we have sorted the data */\r
4719                 oSettings.bSorted = true;\r
4720         }\r
4721         \r
4722         \r
4723         function _fnSortAria ( settings )\r
4724         {\r
4725                 var label;\r
4726                 var nextSort;\r
4727                 var columns = settings.aoColumns;\r
4728                 var aSort = _fnSortFlatten( settings );\r
4729                 var oAria = settings.oLanguage.oAria;\r
4730         \r
4731                 // ARIA attributes - need to loop all columns, to update all (removing old\r
4732                 // attributes as needed)\r
4733                 for ( var i=0, iLen=columns.length ; i<iLen ; i++ )\r
4734                 {\r
4735                         var col = columns[i];\r
4736                         var asSorting = col.asSorting;\r
4737                         var sTitle = col.sTitle.replace( /<.*?>/g, "" );\r
4738                         var th = col.nTh;\r
4739         \r
4740                         // IE7 is throwing an error when setting these properties with jQuery's\r
4741                         // attr() and removeAttr() methods...\r
4742                         th.removeAttribute('aria-sort');\r
4743         \r
4744                         /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */\r
4745                         if ( col.bSortable ) {\r
4746                                 if ( aSort.length > 0 && aSort[0].col == i ) {\r
4747                                         th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );\r
4748                                         nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];\r
4749                                 }\r
4750                                 else {\r
4751                                         nextSort = asSorting[0];\r
4752                                 }\r
4753         \r
4754                                 label = sTitle + ( nextSort === "asc" ?\r
4755                                         oAria.sSortAscending :\r
4756                                         oAria.sSortDescending\r
4757                                 );\r
4758                         }\r
4759                         else {\r
4760                                 label = sTitle;\r
4761                         }\r
4762         \r
4763                         th.setAttribute('aria-label', label);\r
4764                 }\r
4765         }\r
4766         \r
4767         \r
4768         /**\r
4769          * Function to run on user sort request\r
4770          *  @param {object} settings dataTables settings object\r
4771          *  @param {node} attachTo node to attach the handler to\r
4772          *  @param {int} colIdx column sorting index\r
4773          *  @param {boolean} [append=false] Append the requested sort to the existing\r
4774          *    sort if true (i.e. multi-column sort)\r
4775          *  @param {function} [callback] callback function\r
4776          *  @memberof DataTable#oApi\r
4777          */\r
4778         function _fnSortListener ( settings, colIdx, append, callback )\r
4779         {\r
4780                 var col = settings.aoColumns[ colIdx ];\r
4781                 var sorting = settings.aaSorting;\r
4782                 var asSorting = col.asSorting;\r
4783                 var nextSortIdx;\r
4784                 var next = function ( a, overflow ) {\r
4785                         var idx = a._idx;\r
4786                         if ( idx === undefined ) {\r
4787                                 idx = $.inArray( a[1], asSorting );\r
4788                         }\r
4789         \r
4790                         return idx+1 < asSorting.length ?\r
4791                                 idx+1 :\r
4792                                 overflow ?\r
4793                                         null :\r
4794                                         0;\r
4795                 };\r
4796         \r
4797                 // Convert to 2D array if needed\r
4798                 if ( typeof sorting[0] === 'number' ) {\r
4799                         sorting = settings.aaSorting = [ sorting ];\r
4800                 }\r
4801         \r
4802                 // If appending the sort then we are multi-column sorting\r
4803                 if ( append && settings.oFeatures.bSortMulti ) {\r
4804                         // Are we already doing some kind of sort on this column?\r
4805                         var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );\r
4806         \r
4807                         if ( sortIdx !== -1 ) {\r
4808                                 // Yes, modify the sort\r
4809                                 nextSortIdx = next( sorting[sortIdx], true );\r
4810         \r
4811                                 if ( nextSortIdx === null && sorting.length === 1 ) {\r
4812                                         nextSortIdx = 0; // can't remove sorting completely\r
4813                                 }\r
4814         \r
4815                                 if ( nextSortIdx === null ) {\r
4816                                         sorting.splice( sortIdx, 1 );\r
4817                                 }\r
4818                                 else {\r
4819                                         sorting[sortIdx][1] = asSorting[ nextSortIdx ];\r
4820                                         sorting[sortIdx]._idx = nextSortIdx;\r
4821                                 }\r
4822                         }\r
4823                         else {\r
4824                                 // No sort on this column yet\r
4825                                 sorting.push( [ colIdx, asSorting[0], 0 ] );\r
4826                                 sorting[sorting.length-1]._idx = 0;\r
4827                         }\r
4828                 }\r
4829                 else if ( sorting.length && sorting[0][0] == colIdx ) {\r
4830                         // Single column - already sorting on this column, modify the sort\r
4831                         nextSortIdx = next( sorting[0] );\r
4832         \r
4833                         sorting.length = 1;\r
4834                         sorting[0][1] = asSorting[ nextSortIdx ];\r
4835                         sorting[0]._idx = nextSortIdx;\r
4836                 }\r
4837                 else {\r
4838                         // Single column - sort only on this column\r
4839                         sorting.length = 0;\r
4840                         sorting.push( [ colIdx, asSorting[0] ] );\r
4841                         sorting[0]._idx = 0;\r
4842                 }\r
4843         \r
4844                 // Run the sort by calling a full redraw\r
4845                 _fnReDraw( settings );\r
4846         \r
4847                 // callback used for async user interaction\r
4848                 if ( typeof callback == 'function' ) {\r
4849                         callback( settings );\r
4850                 }\r
4851         }\r
4852         \r
4853         \r
4854         /**\r
4855          * Attach a sort handler (click) to a node\r
4856          *  @param {object} settings dataTables settings object\r
4857          *  @param {node} attachTo node to attach the handler to\r
4858          *  @param {int} colIdx column sorting index\r
4859          *  @param {function} [callback] callback function\r
4860          *  @memberof DataTable#oApi\r
4861          */\r
4862         function _fnSortAttachListener ( settings, attachTo, colIdx, callback )\r
4863         {\r
4864                 var col = settings.aoColumns[ colIdx ];\r
4865         \r
4866                 _fnBindAction( attachTo, {}, function (e) {\r
4867                         /* If the column is not sortable - don't to anything */\r
4868                         if ( col.bSortable === false ) {\r
4869                                 return;\r
4870                         }\r
4871         \r
4872                         // If processing is enabled use a timeout to allow the processing\r
4873                         // display to be shown - otherwise to it synchronously\r
4874                         if ( settings.oFeatures.bProcessing ) {\r
4875                                 _fnProcessingDisplay( settings, true );\r
4876         \r
4877                                 setTimeout( function() {\r
4878                                         _fnSortListener( settings, colIdx, e.shiftKey, callback );\r
4879         \r
4880                                         // In server-side processing, the draw callback will remove the\r
4881                                         // processing display\r
4882                                         if ( _fnDataSource( settings ) !== 'ssp' ) {\r
4883                                                 _fnProcessingDisplay( settings, false );\r
4884                                         }\r
4885                                 }, 0 );\r
4886                         }\r
4887                         else {\r
4888                                 _fnSortListener( settings, colIdx, e.shiftKey, callback );\r
4889                         }\r
4890                 } );\r
4891         }\r
4892         \r
4893         \r
4894         /**\r
4895          * Set the sorting classes on table's body, Note: it is safe to call this function\r
4896          * when bSort and bSortClasses are false\r
4897          *  @param {object} oSettings dataTables settings object\r
4898          *  @memberof DataTable#oApi\r
4899          */\r
4900         function _fnSortingClasses( settings )\r
4901         {\r
4902                 var oldSort = settings.aLastSort;\r
4903                 var sortClass = settings.oClasses.sSortColumn;\r
4904                 var sort = _fnSortFlatten( settings );\r
4905                 var features = settings.oFeatures;\r
4906                 var i, ien, colIdx;\r
4907         \r
4908                 if ( features.bSort && features.bSortClasses ) {\r
4909                         // Remove old sorting classes\r
4910                         for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {\r
4911                                 colIdx = oldSort[i].src;\r
4912         \r
4913                                 // Remove column sorting\r
4914                                 $( _pluck( settings.aoData, 'anCells', colIdx ) )\r
4915                                         .removeClass( sortClass + (i<2 ? i+1 : 3) );\r
4916                         }\r
4917         \r
4918                         // Add new column sorting\r
4919                         for ( i=0, ien=sort.length ; i<ien ; i++ ) {\r
4920                                 colIdx = sort[i].src;\r
4921         \r
4922                                 $( _pluck( settings.aoData, 'anCells', colIdx ) )\r
4923                                         .addClass( sortClass + (i<2 ? i+1 : 3) );\r
4924                         }\r
4925                 }\r
4926         \r
4927                 settings.aLastSort = sort;\r
4928         }\r
4929         \r
4930         \r
4931         // Get the data to sort a column, be it from cache, fresh (populating the\r
4932         // cache), or from a sort formatter\r
4933         function _fnSortData( settings, idx )\r
4934         {\r
4935                 // Custom sorting function - provided by the sort data type\r
4936                 var column = settings.aoColumns[ idx ];\r
4937                 var customSort = DataTable.ext.order[ column.sSortDataType ];\r
4938                 var customData;\r
4939         \r
4940                 if ( customSort ) {\r
4941                         customData = customSort.call( settings.oInstance, settings, idx,\r
4942                                 _fnColumnIndexToVisible( settings, idx )\r
4943                         );\r
4944                 }\r
4945         \r
4946                 // Use / populate cache\r
4947                 var row, cellData;\r
4948                 var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];\r
4949         \r
4950                 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {\r
4951                         row = settings.aoData[i];\r
4952         \r
4953                         if ( ! row._aSortData ) {\r
4954                                 row._aSortData = [];\r
4955                         }\r
4956         \r
4957                         if ( ! row._aSortData[idx] || customSort ) {\r
4958                                 cellData = customSort ?\r
4959                                         customData[i] : // If there was a custom sort function, use data from there\r
4960                                         _fnGetCellData( settings, i, idx, 'sort' );\r
4961         \r
4962                                 row._aSortData[ idx ] = formatter ?\r
4963                                         formatter( cellData ) :\r
4964                                         cellData;\r
4965                         }\r
4966                 }\r
4967         }\r
4968         \r
4969         \r
4970         \r
4971         /**\r
4972          * Save the state of a table\r
4973          *  @param {object} oSettings dataTables settings object\r
4974          *  @memberof DataTable#oApi\r
4975          */\r
4976         function _fnSaveState ( settings )\r
4977         {\r
4978                 if ( !settings.oFeatures.bStateSave || settings.bDestroying )\r
4979                 {\r
4980                         return;\r
4981                 }\r
4982         \r
4983                 /* Store the interesting variables */\r
4984                 var state = {\r
4985                         time:    +new Date(),\r
4986                         start:   settings._iDisplayStart,\r
4987                         length:  settings._iDisplayLength,\r
4988                         order:   $.extend( true, [], settings.aaSorting ),\r
4989                         search:  _fnSearchToCamel( settings.oPreviousSearch ),\r
4990                         columns: $.map( settings.aoColumns, function ( col, i ) {\r
4991                                 return {\r
4992                                         visible: col.bVisible,\r
4993                                         search: _fnSearchToCamel( settings.aoPreSearchCols[i] )\r
4994                                 };\r
4995                         } )\r
4996                 };\r
4997         \r
4998                 _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );\r
4999         \r
5000                 settings.oSavedState = state;\r
5001                 settings.fnStateSaveCallback.call( settings.oInstance, settings, state );\r
5002         }\r
5003         \r
5004         \r
5005         /**\r
5006          * Attempt to load a saved table state\r
5007          *  @param {object} oSettings dataTables settings object\r
5008          *  @param {object} oInit DataTables init object so we can override settings\r
5009          *  @memberof DataTable#oApi\r
5010          */\r
5011         function _fnLoadState ( settings, oInit )\r
5012         {\r
5013                 var i, ien;\r
5014                 var columns = settings.aoColumns;\r
5015         \r
5016                 if ( ! settings.oFeatures.bStateSave ) {\r
5017                         return;\r
5018                 }\r
5019         \r
5020                 var state = settings.fnStateLoadCallback.call( settings.oInstance, settings );\r
5021                 if ( ! state || ! state.time ) {\r
5022                         return;\r
5023                 }\r
5024         \r
5025                 /* Allow custom and plug-in manipulation functions to alter the saved data set and\r
5026                  * cancelling of loading by returning false\r
5027                  */\r
5028                 var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, state] );\r
5029                 if ( $.inArray( false, abStateLoad ) !== -1 ) {\r
5030                         return;\r
5031                 }\r
5032         \r
5033                 /* Reject old data */\r
5034                 var duration = settings.iStateDuration;\r
5035                 if ( duration > 0 && state.time < +new Date() - (duration*1000) ) {\r
5036                         return;\r
5037                 }\r
5038         \r
5039                 // Number of columns have changed - all bets are off, no restore of settings\r
5040                 if ( columns.length !== state.columns.length ) {\r
5041                         return;\r
5042                 }\r
5043         \r
5044                 // Store the saved state so it might be accessed at any time\r
5045                 settings.oLoadedState = $.extend( true, {}, state );\r
5046         \r
5047                 // Restore key features - todo - for 1.11 this needs to be done by\r
5048                 // subscribed events\r
5049                 if ( state.start !== undefined ) {\r
5050                         settings._iDisplayStart    = state.start;\r
5051                         settings.iInitDisplayStart = state.start;\r
5052                 }\r
5053                 if ( state.length !== undefined ) {\r
5054                         settings._iDisplayLength   = state.length;\r
5055                 }\r
5056         \r
5057                 // Order\r
5058                 if ( state.order !== undefined ) {\r
5059                         settings.aaSorting = [];\r
5060                         $.each( state.order, function ( i, col ) {\r
5061                                 settings.aaSorting.push( col[0] >= columns.length ?\r
5062                                         [ 0, col[1] ] :\r
5063                                         col\r
5064                                 );\r
5065                         } );\r
5066                 }\r
5067         \r
5068                 // Search\r
5069                 if ( state.search !== undefined ) {\r
5070                         $.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );\r
5071                 }\r
5072         \r
5073                 // Columns\r
5074                 for ( i=0, ien=state.columns.length ; i<ien ; i++ ) {\r
5075                         var col = state.columns[i];\r
5076         \r
5077                         // Visibility\r
5078                         if ( col.visible !== undefined ) {\r
5079                                 columns[i].bVisible = col.visible;\r
5080                         }\r
5081         \r
5082                         // Search\r
5083                         if ( col.search !== undefined ) {\r
5084                                 $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );\r
5085                         }\r
5086                 }\r
5087         \r
5088                 _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] );\r
5089         }\r
5090         \r
5091         \r
5092         /**\r
5093          * Return the settings object for a particular table\r
5094          *  @param {node} table table we are using as a dataTable\r
5095          *  @returns {object} Settings object - or null if not found\r
5096          *  @memberof DataTable#oApi\r
5097          */\r
5098         function _fnSettingsFromNode ( table )\r
5099         {\r
5100                 var settings = DataTable.settings;\r
5101                 var idx = $.inArray( table, _pluck( settings, 'nTable' ) );\r
5102         \r
5103                 return idx !== -1 ?\r
5104                         settings[ idx ] :\r
5105                         null;\r
5106         }\r
5107         \r
5108         \r
5109         /**\r
5110          * Log an error message\r
5111          *  @param {object} settings dataTables settings object\r
5112          *  @param {int} level log error messages, or display them to the user\r
5113          *  @param {string} msg error message\r
5114          *  @param {int} tn Technical note id to get more information about the error.\r
5115          *  @memberof DataTable#oApi\r
5116          */\r
5117         function _fnLog( settings, level, msg, tn )\r
5118         {\r
5119                 msg = 'DataTables warning: '+\r
5120                         (settings ? 'table id='+settings.sTableId+' - ' : '')+msg;\r
5121         \r
5122                 if ( tn ) {\r
5123                         msg += '. For more information about this error, please see '+\r
5124                         'http://datatables.net/tn/'+tn;\r
5125                 }\r
5126         \r
5127                 if ( ! level  ) {\r
5128                         // Backwards compatibility pre 1.10\r
5129                         var ext = DataTable.ext;\r
5130                         var type = ext.sErrMode || ext.errMode;\r
5131         \r
5132                         if ( settings ) {\r
5133                                 _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] );\r
5134                         }\r
5135         \r
5136                         if ( type == 'alert' ) {\r
5137                                 alert( msg );\r
5138                         }\r
5139                         else if ( type == 'throw' ) {\r
5140                                 throw new Error(msg);\r
5141                         }\r
5142                         else if ( typeof type == 'function' ) {\r
5143                                 type( settings, tn, msg );\r
5144                         }\r
5145                 }\r
5146                 else if ( window.console && console.log ) {\r
5147                         console.log( msg );\r
5148                 }\r
5149         }\r
5150         \r
5151         \r
5152         /**\r
5153          * See if a property is defined on one object, if so assign it to the other object\r
5154          *  @param {object} ret target object\r
5155          *  @param {object} src source object\r
5156          *  @param {string} name property\r
5157          *  @param {string} [mappedName] name to map too - optional, name used if not given\r
5158          *  @memberof DataTable#oApi\r
5159          */\r
5160         function _fnMap( ret, src, name, mappedName )\r
5161         {\r
5162                 if ( $.isArray( name ) ) {\r
5163                         $.each( name, function (i, val) {\r
5164                                 if ( $.isArray( val ) ) {\r
5165                                         _fnMap( ret, src, val[0], val[1] );\r
5166                                 }\r
5167                                 else {\r
5168                                         _fnMap( ret, src, val );\r
5169                                 }\r
5170                         } );\r
5171         \r
5172                         return;\r
5173                 }\r
5174         \r
5175                 if ( mappedName === undefined ) {\r
5176                         mappedName = name;\r
5177                 }\r
5178         \r
5179                 if ( src[name] !== undefined ) {\r
5180                         ret[mappedName] = src[name];\r
5181                 }\r
5182         }\r
5183         \r
5184         \r
5185         /**\r
5186          * Extend objects - very similar to jQuery.extend, but deep copy objects, and\r
5187          * shallow copy arrays. The reason we need to do this, is that we don't want to\r
5188          * deep copy array init values (such as aaSorting) since the dev wouldn't be\r
5189          * able to override them, but we do want to deep copy arrays.\r
5190          *  @param {object} out Object to extend\r
5191          *  @param {object} extender Object from which the properties will be applied to\r
5192          *      out\r
5193          *  @param {boolean} breakRefs If true, then arrays will be sliced to take an\r
5194          *      independent copy with the exception of the `data` or `aaData` parameters\r
5195          *      if they are present. This is so you can pass in a collection to\r
5196          *      DataTables and have that used as your data source without breaking the\r
5197          *      references\r
5198          *  @returns {object} out Reference, just for convenience - out === the return.\r
5199          *  @memberof DataTable#oApi\r
5200          *  @todo This doesn't take account of arrays inside the deep copied objects.\r
5201          */\r
5202         function _fnExtend( out, extender, breakRefs )\r
5203         {\r
5204                 var val;\r
5205         \r
5206                 for ( var prop in extender ) {\r
5207                         if ( extender.hasOwnProperty(prop) ) {\r
5208                                 val = extender[prop];\r
5209         \r
5210                                 if ( $.isPlainObject( val ) ) {\r
5211                                         if ( ! $.isPlainObject( out[prop] ) ) {\r
5212                                                 out[prop] = {};\r
5213                                         }\r
5214                                         $.extend( true, out[prop], val );\r
5215                                 }\r
5216                                 else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {\r
5217                                         out[prop] = val.slice();\r
5218                                 }\r
5219                                 else {\r
5220                                         out[prop] = val;\r
5221                                 }\r
5222                         }\r
5223                 }\r
5224         \r
5225                 return out;\r
5226         }\r
5227         \r
5228         \r
5229         /**\r
5230          * Bind an event handers to allow a click or return key to activate the callback.\r
5231          * This is good for accessibility since a return on the keyboard will have the\r
5232          * same effect as a click, if the element has focus.\r
5233          *  @param {element} n Element to bind the action to\r
5234          *  @param {object} oData Data object to pass to the triggered function\r
5235          *  @param {function} fn Callback function for when the event is triggered\r
5236          *  @memberof DataTable#oApi\r
5237          */\r
5238         function _fnBindAction( n, oData, fn )\r
5239         {\r
5240                 $(n)\r
5241                         .bind( 'click.DT', oData, function (e) {\r
5242                                         n.blur(); // Remove focus outline for mouse users\r
5243                                         fn(e);\r
5244                                 } )\r
5245                         .bind( 'keypress.DT', oData, function (e){\r
5246                                         if ( e.which === 13 ) {\r
5247                                                 e.preventDefault();\r
5248                                                 fn(e);\r
5249                                         }\r
5250                                 } )\r
5251                         .bind( 'selectstart.DT', function () {\r
5252                                         /* Take the brutal approach to cancelling text selection */\r
5253                                         return false;\r
5254                                 } );\r
5255         }\r
5256         \r
5257         \r
5258         /**\r
5259          * Register a callback function. Easily allows a callback function to be added to\r
5260          * an array store of callback functions that can then all be called together.\r
5261          *  @param {object} oSettings dataTables settings object\r
5262          *  @param {string} sStore Name of the array storage for the callbacks in oSettings\r
5263          *  @param {function} fn Function to be called back\r
5264          *  @param {string} sName Identifying name for the callback (i.e. a label)\r
5265          *  @memberof DataTable#oApi\r
5266          */\r
5267         function _fnCallbackReg( oSettings, sStore, fn, sName )\r
5268         {\r
5269                 if ( fn )\r
5270                 {\r
5271                         oSettings[sStore].push( {\r
5272                                 "fn": fn,\r
5273                                 "sName": sName\r
5274                         } );\r
5275                 }\r
5276         }\r
5277         \r
5278         \r
5279         /**\r
5280          * Fire callback functions and trigger events. Note that the loop over the\r
5281          * callback array store is done backwards! Further note that you do not want to\r
5282          * fire off triggers in time sensitive applications (for example cell creation)\r
5283          * as its slow.\r
5284          *  @param {object} settings dataTables settings object\r
5285          *  @param {string} callbackArr Name of the array storage for the callbacks in\r
5286          *      oSettings\r
5287          *  @param {string} eventName Name of the jQuery custom event to trigger. If\r
5288          *      null no trigger is fired\r
5289          *  @param {array} args Array of arguments to pass to the callback function /\r
5290          *      trigger\r
5291          *  @memberof DataTable#oApi\r
5292          */\r
5293         function _fnCallbackFire( settings, callbackArr, eventName, args )\r
5294         {\r
5295                 var ret = [];\r
5296         \r
5297                 if ( callbackArr ) {\r
5298                         ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {\r
5299                                 return val.fn.apply( settings.oInstance, args );\r
5300                         } );\r
5301                 }\r
5302         \r
5303                 if ( eventName !== null ) {\r
5304                         var e = $.Event( eventName+'.dt' );\r
5305         \r
5306                         $(settings.nTable).trigger( e, args );\r
5307         \r
5308                         ret.push( e.result );\r
5309                 }\r
5310         \r
5311                 return ret;\r
5312         }\r
5313         \r
5314         \r
5315         function _fnLengthOverflow ( settings )\r
5316         {\r
5317                 var\r
5318                         start = settings._iDisplayStart,\r
5319                         end = settings.fnDisplayEnd(),\r
5320                         len = settings._iDisplayLength;\r
5321         \r
5322                 /* If we have space to show extra rows (backing up from the end point - then do so */\r
5323                 if ( start >= end )\r
5324                 {\r
5325                         start = end - len;\r
5326                 }\r
5327         \r
5328                 // Keep the start record on the current page\r
5329                 start -= (start % len);\r
5330         \r
5331                 if ( len === -1 || start < 0 )\r
5332                 {\r
5333                         start = 0;\r
5334                 }\r
5335         \r
5336                 settings._iDisplayStart = start;\r
5337         }\r
5338         \r
5339         \r
5340         function _fnRenderer( settings, type )\r
5341         {\r
5342                 var renderer = settings.renderer;\r
5343                 var host = DataTable.ext.renderer[type];\r
5344         \r
5345                 if ( $.isPlainObject( renderer ) && renderer[type] ) {\r
5346                         // Specific renderer for this type. If available use it, otherwise use\r
5347                         // the default.\r
5348                         return host[renderer[type]] || host._;\r
5349                 }\r
5350                 else if ( typeof renderer === 'string' ) {\r
5351                         // Common renderer - if there is one available for this type use it,\r
5352                         // otherwise use the default\r
5353                         return host[renderer] || host._;\r
5354                 }\r
5355         \r
5356                 // Use the default\r
5357                 return host._;\r
5358         }\r
5359         \r
5360         \r
5361         /**\r
5362          * Detect the data source being used for the table. Used to simplify the code\r
5363          * a little (ajax) and to make it compress a little smaller.\r
5364          *\r
5365          *  @param {object} settings dataTables settings object\r
5366          *  @returns {string} Data source\r
5367          *  @memberof DataTable#oApi\r
5368          */\r
5369         function _fnDataSource ( settings )\r
5370         {\r
5371                 if ( settings.oFeatures.bServerSide ) {\r
5372                         return 'ssp';\r
5373                 }\r
5374                 else if ( settings.ajax || settings.sAjaxSource ) {\r
5375                         return 'ajax';\r
5376                 }\r
5377                 return 'dom';\r
5378         }\r
5379         \r
5380 \r
5381         DataTable = function( options )\r
5382         {\r
5383                 /**\r
5384                  * Perform a jQuery selector action on the table's TR elements (from the tbody) and\r
5385                  * return the resulting jQuery object.\r
5386                  *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on\r
5387                  *  @param {object} [oOpts] Optional parameters for modifying the rows to be included\r
5388                  *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter\r
5389                  *    criterion ("applied") or all TR elements (i.e. no filter).\r
5390                  *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.\r
5391                  *    Can be either 'current', whereby the current sorting of the table is used, or\r
5392                  *    'original' whereby the original order the data was read into the table is used.\r
5393                  *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page\r
5394                  *    ("current") or not ("all"). If 'current' is given, then order is assumed to be\r
5395                  *    'current' and filter is 'applied', regardless of what they might be given as.\r
5396                  *  @returns {object} jQuery object, filtered by the given selector.\r
5397                  *  @dtopt API\r
5398                  *  @deprecated Since v1.10\r
5399                  *\r
5400                  *  @example\r
5401                  *    $(document).ready(function() {\r
5402                  *      var oTable = $('#example').dataTable();\r
5403                  *\r
5404                  *      // Highlight every second row\r
5405                  *      oTable.$('tr:odd').css('backgroundColor', 'blue');\r
5406                  *    } );\r
5407                  *\r
5408                  *  @example\r
5409                  *    $(document).ready(function() {\r
5410                  *      var oTable = $('#example').dataTable();\r
5411                  *\r
5412                  *      // Filter to rows with 'Webkit' in them, add a background colour and then\r
5413                  *      // remove the filter, thus highlighting the 'Webkit' rows only.\r
5414                  *      oTable.fnFilter('Webkit');\r
5415                  *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');\r
5416                  *      oTable.fnFilter('');\r
5417                  *    } );\r
5418                  */\r
5419                 this.$ = function ( sSelector, oOpts )\r
5420                 {\r
5421                         return this.api(true).$( sSelector, oOpts );\r
5422                 };\r
5423                 \r
5424                 \r
5425                 /**\r
5426                  * Almost identical to $ in operation, but in this case returns the data for the matched\r
5427                  * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes\r
5428                  * rather than any descendants, so the data can be obtained for the row/cell. If matching\r
5429                  * rows are found, the data returned is the original data array/object that was used to\r
5430                  * create the row (or a generated array if from a DOM source).\r
5431                  *\r
5432                  * This method is often useful in-combination with $ where both functions are given the\r
5433                  * same parameters and the array indexes will match identically.\r
5434                  *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on\r
5435                  *  @param {object} [oOpts] Optional parameters for modifying the rows to be included\r
5436                  *  @param {string} [oOpts.filter=none] Select elements that meet the current filter\r
5437                  *    criterion ("applied") or all elements (i.e. no filter).\r
5438                  *  @param {string} [oOpts.order=current] Order of the data in the processed array.\r
5439                  *    Can be either 'current', whereby the current sorting of the table is used, or\r
5440                  *    'original' whereby the original order the data was read into the table is used.\r
5441                  *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page\r
5442                  *    ("current") or not ("all"). If 'current' is given, then order is assumed to be\r
5443                  *    'current' and filter is 'applied', regardless of what they might be given as.\r
5444                  *  @returns {array} Data for the matched elements. If any elements, as a result of the\r
5445                  *    selector, were not TR, TD or TH elements in the DataTable, they will have a null\r
5446                  *    entry in the array.\r
5447                  *  @dtopt API\r
5448                  *  @deprecated Since v1.10\r
5449                  *\r
5450                  *  @example\r
5451                  *    $(document).ready(function() {\r
5452                  *      var oTable = $('#example').dataTable();\r
5453                  *\r
5454                  *      // Get the data from the first row in the table\r
5455                  *      var data = oTable._('tr:first');\r
5456                  *\r
5457                  *      // Do something useful with the data\r
5458                  *      alert( "First cell is: "+data[0] );\r
5459                  *    } );\r
5460                  *\r
5461                  *  @example\r
5462                  *    $(document).ready(function() {\r
5463                  *      var oTable = $('#example').dataTable();\r
5464                  *\r
5465                  *      // Filter to 'Webkit' and get all data for\r
5466                  *      oTable.fnFilter('Webkit');\r
5467                  *      var data = oTable._('tr', {"search": "applied"});\r
5468                  *\r
5469                  *      // Do something with the data\r
5470                  *      alert( data.length+" rows matched the search" );\r
5471                  *    } );\r
5472                  */\r
5473                 this._ = function ( sSelector, oOpts )\r
5474                 {\r
5475                         return this.api(true).rows( sSelector, oOpts ).data();\r
5476                 };\r
5477                 \r
5478                 \r
5479                 /**\r
5480                  * Create a DataTables Api instance, with the currently selected tables for\r
5481                  * the Api's context.\r
5482                  * @param {boolean} [traditional=false] Set the API instance's context to be\r
5483                  *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was\r
5484                  *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),\r
5485                  *   or if all tables captured in the jQuery object should be used.\r
5486                  * @return {DataTables.Api}\r
5487                  */\r
5488                 this.api = function ( traditional )\r
5489                 {\r
5490                         return traditional ?\r
5491                                 new _Api(\r
5492                                         _fnSettingsFromNode( this[ _ext.iApiIndex ] )\r
5493                                 ) :\r
5494                                 new _Api( this );\r
5495                 };\r
5496                 \r
5497                 \r
5498                 /**\r
5499                  * Add a single new row or multiple rows of data to the table. Please note\r
5500                  * that this is suitable for client-side processing only - if you are using\r
5501                  * server-side processing (i.e. "bServerSide": true), then to add data, you\r
5502                  * must add it to the data source, i.e. the server-side, through an Ajax call.\r
5503                  *  @param {array|object} data The data to be added to the table. This can be:\r
5504                  *    <ul>\r
5505                  *      <li>1D array of data - add a single row with the data provided</li>\r
5506                  *      <li>2D array of arrays - add multiple rows in a single call</li>\r
5507                  *      <li>object - data object when using <i>mData</i></li>\r
5508                  *      <li>array of objects - multiple data objects when using <i>mData</i></li>\r
5509                  *    </ul>\r
5510                  *  @param {bool} [redraw=true] redraw the table or not\r
5511                  *  @returns {array} An array of integers, representing the list of indexes in\r
5512                  *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to\r
5513                  *    the table.\r
5514                  *  @dtopt API\r
5515                  *  @deprecated Since v1.10\r
5516                  *\r
5517                  *  @example\r
5518                  *    // Global var for counter\r
5519                  *    var giCount = 2;\r
5520                  *\r
5521                  *    $(document).ready(function() {\r
5522                  *      $('#example').dataTable();\r
5523                  *    } );\r
5524                  *\r
5525                  *    function fnClickAddRow() {\r
5526                  *      $('#example').dataTable().fnAddData( [\r
5527                  *        giCount+".1",\r
5528                  *        giCount+".2",\r
5529                  *        giCount+".3",\r
5530                  *        giCount+".4" ]\r
5531                  *      );\r
5532                  *\r
5533                  *      giCount++;\r
5534                  *    }\r
5535                  */\r
5536                 this.fnAddData = function( data, redraw )\r
5537                 {\r
5538                         var api = this.api( true );\r
5539                 \r
5540                         /* Check if we want to add multiple rows or not */\r
5541                         var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?\r
5542                                 api.rows.add( data ) :\r
5543                                 api.row.add( data );\r
5544                 \r
5545                         if ( redraw === undefined || redraw ) {\r
5546                                 api.draw();\r
5547                         }\r
5548                 \r
5549                         return rows.flatten().toArray();\r
5550                 };\r
5551                 \r
5552                 \r
5553                 /**\r
5554                  * This function will make DataTables recalculate the column sizes, based on the data\r
5555                  * contained in the table and the sizes applied to the columns (in the DOM, CSS or\r
5556                  * through the sWidth parameter). This can be useful when the width of the table's\r
5557                  * parent element changes (for example a window resize).\r
5558                  *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to\r
5559                  *  @dtopt API\r
5560                  *  @deprecated Since v1.10\r
5561                  *\r
5562                  *  @example\r
5563                  *    $(document).ready(function() {\r
5564                  *      var oTable = $('#example').dataTable( {\r
5565                  *        "sScrollY": "200px",\r
5566                  *        "bPaginate": false\r
5567                  *      } );\r
5568                  *\r
5569                  *      $(window).bind('resize', function () {\r
5570                  *        oTable.fnAdjustColumnSizing();\r
5571                  *      } );\r
5572                  *    } );\r
5573                  */\r
5574                 this.fnAdjustColumnSizing = function ( bRedraw )\r
5575                 {\r
5576                         var api = this.api( true ).columns.adjust();\r
5577                         var settings = api.settings()[0];\r
5578                         var scroll = settings.oScroll;\r
5579                 \r
5580                         if ( bRedraw === undefined || bRedraw ) {\r
5581                                 api.draw( false );\r
5582                         }\r
5583                         else if ( scroll.sX !== "" || scroll.sY !== "" ) {\r
5584                                 /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */\r
5585                                 _fnScrollDraw( settings );\r
5586                         }\r
5587                 };\r
5588                 \r
5589                 \r
5590                 /**\r
5591                  * Quickly and simply clear a table\r
5592                  *  @param {bool} [bRedraw=true] redraw the table or not\r
5593                  *  @dtopt API\r
5594                  *  @deprecated Since v1.10\r
5595                  *\r
5596                  *  @example\r
5597                  *    $(document).ready(function() {\r
5598                  *      var oTable = $('#example').dataTable();\r
5599                  *\r
5600                  *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)\r
5601                  *      oTable.fnClearTable();\r
5602                  *    } );\r
5603                  */\r
5604                 this.fnClearTable = function( bRedraw )\r
5605                 {\r
5606                         var api = this.api( true ).clear();\r
5607                 \r
5608                         if ( bRedraw === undefined || bRedraw ) {\r
5609                                 api.draw();\r
5610                         }\r
5611                 };\r
5612                 \r
5613                 \r
5614                 /**\r
5615                  * The exact opposite of 'opening' a row, this function will close any rows which\r
5616                  * are currently 'open'.\r
5617                  *  @param {node} nTr the table row to 'close'\r
5618                  *  @returns {int} 0 on success, or 1 if failed (can't find the row)\r
5619                  *  @dtopt API\r
5620                  *  @deprecated Since v1.10\r
5621                  *\r
5622                  *  @example\r
5623                  *    $(document).ready(function() {\r
5624                  *      var oTable;\r
5625                  *\r
5626                  *      // 'open' an information row when a row is clicked on\r
5627                  *      $('#example tbody tr').click( function () {\r
5628                  *        if ( oTable.fnIsOpen(this) ) {\r
5629                  *          oTable.fnClose( this );\r
5630                  *        } else {\r
5631                  *          oTable.fnOpen( this, "Temporary row opened", "info_row" );\r
5632                  *        }\r
5633                  *      } );\r
5634                  *\r
5635                  *      oTable = $('#example').dataTable();\r
5636                  *    } );\r
5637                  */\r
5638                 this.fnClose = function( nTr )\r
5639                 {\r
5640                         this.api( true ).row( nTr ).child.hide();\r
5641                 };\r
5642                 \r
5643                 \r
5644                 /**\r
5645                  * Remove a row for the table\r
5646                  *  @param {mixed} target The index of the row from aoData to be deleted, or\r
5647                  *    the TR element you want to delete\r
5648                  *  @param {function|null} [callBack] Callback function\r
5649                  *  @param {bool} [redraw=true] Redraw the table or not\r
5650                  *  @returns {array} The row that was deleted\r
5651                  *  @dtopt API\r
5652                  *  @deprecated Since v1.10\r
5653                  *\r
5654                  *  @example\r
5655                  *    $(document).ready(function() {\r
5656                  *      var oTable = $('#example').dataTable();\r
5657                  *\r
5658                  *      // Immediately remove the first row\r
5659                  *      oTable.fnDeleteRow( 0 );\r
5660                  *    } );\r
5661                  */\r
5662                 this.fnDeleteRow = function( target, callback, redraw )\r
5663                 {\r
5664                         var api = this.api( true );\r
5665                         var rows = api.rows( target );\r
5666                         var settings = rows.settings()[0];\r
5667                         var data = settings.aoData[ rows[0][0] ];\r
5668                 \r
5669                         rows.remove();\r
5670                 \r
5671                         if ( callback ) {\r
5672                                 callback.call( this, settings, data );\r
5673                         }\r
5674                 \r
5675                         if ( redraw === undefined || redraw ) {\r
5676                                 api.draw();\r
5677                         }\r
5678                 \r
5679                         return data;\r
5680                 };\r
5681                 \r
5682                 \r
5683                 /**\r
5684                  * Restore the table to it's original state in the DOM by removing all of DataTables\r
5685                  * enhancements, alterations to the DOM structure of the table and event listeners.\r
5686                  *  @param {boolean} [remove=false] Completely remove the table from the DOM\r
5687                  *  @dtopt API\r
5688                  *  @deprecated Since v1.10\r
5689                  *\r
5690                  *  @example\r
5691                  *    $(document).ready(function() {\r
5692                  *      // This example is fairly pointless in reality, but shows how fnDestroy can be used\r
5693                  *      var oTable = $('#example').dataTable();\r
5694                  *      oTable.fnDestroy();\r
5695                  *    } );\r
5696                  */\r
5697                 this.fnDestroy = function ( remove )\r
5698                 {\r
5699                         this.api( true ).destroy( remove );\r
5700                 };\r
5701                 \r
5702                 \r
5703                 /**\r
5704                  * Redraw the table\r
5705                  *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.\r
5706                  *  @dtopt API\r
5707                  *  @deprecated Since v1.10\r
5708                  *\r
5709                  *  @example\r
5710                  *    $(document).ready(function() {\r
5711                  *      var oTable = $('#example').dataTable();\r
5712                  *\r
5713                  *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)\r
5714                  *      oTable.fnDraw();\r
5715                  *    } );\r
5716                  */\r
5717                 this.fnDraw = function( complete )\r
5718                 {\r
5719                         // Note that this isn't an exact match to the old call to _fnDraw - it takes\r
5720                         // into account the new data, but can hold position.\r
5721                         this.api( true ).draw( complete );\r
5722                 };\r
5723                 \r
5724                 \r
5725                 /**\r
5726                  * Filter the input based on data\r
5727                  *  @param {string} sInput String to filter the table on\r
5728                  *  @param {int|null} [iColumn] Column to limit filtering to\r
5729                  *  @param {bool} [bRegex=false] Treat as regular expression or not\r
5730                  *  @param {bool} [bSmart=true] Perform smart filtering or not\r
5731                  *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)\r
5732                  *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)\r
5733                  *  @dtopt API\r
5734                  *  @deprecated Since v1.10\r
5735                  *\r
5736                  *  @example\r
5737                  *    $(document).ready(function() {\r
5738                  *      var oTable = $('#example').dataTable();\r
5739                  *\r
5740                  *      // Sometime later - filter...\r
5741                  *      oTable.fnFilter( 'test string' );\r
5742                  *    } );\r
5743                  */\r
5744                 this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )\r
5745                 {\r
5746                         var api = this.api( true );\r
5747                 \r
5748                         if ( iColumn === null || iColumn === undefined ) {\r
5749                                 api.search( sInput, bRegex, bSmart, bCaseInsensitive );\r
5750                         }\r
5751                         else {\r
5752                                 api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );\r
5753                         }\r
5754                 \r
5755                         api.draw();\r
5756                 };\r
5757                 \r
5758                 \r
5759                 /**\r
5760                  * Get the data for the whole table, an individual row or an individual cell based on the\r
5761                  * provided parameters.\r
5762                  *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as\r
5763                  *    a TR node then the data source for the whole row will be returned. If given as a\r
5764                  *    TD/TH cell node then iCol will be automatically calculated and the data for the\r
5765                  *    cell returned. If given as an integer, then this is treated as the aoData internal\r
5766                  *    data index for the row (see fnGetPosition) and the data for that row used.\r
5767                  *  @param {int} [col] Optional column index that you want the data of.\r
5768                  *  @returns {array|object|string} If mRow is undefined, then the data for all rows is\r
5769                  *    returned. If mRow is defined, just data for that row, and is iCol is\r
5770                  *    defined, only data for the designated cell is returned.\r
5771                  *  @dtopt API\r
5772                  *  @deprecated Since v1.10\r
5773                  *\r
5774                  *  @example\r
5775                  *    // Row data\r
5776                  *    $(document).ready(function() {\r
5777                  *      oTable = $('#example').dataTable();\r
5778                  *\r
5779                  *      oTable.$('tr').click( function () {\r
5780                  *        var data = oTable.fnGetData( this );\r
5781                  *        // ... do something with the array / object of data for the row\r
5782                  *      } );\r
5783                  *    } );\r
5784                  *\r
5785                  *  @example\r
5786                  *    // Individual cell data\r
5787                  *    $(document).ready(function() {\r
5788                  *      oTable = $('#example').dataTable();\r
5789                  *\r
5790                  *      oTable.$('td').click( function () {\r
5791                  *        var sData = oTable.fnGetData( this );\r
5792                  *        alert( 'The cell clicked on had the value of '+sData );\r
5793                  *      } );\r
5794                  *    } );\r
5795                  */\r
5796                 this.fnGetData = function( src, col )\r
5797                 {\r
5798                         var api = this.api( true );\r
5799                 \r
5800                         if ( src !== undefined ) {\r
5801                                 var type = src.nodeName ? src.nodeName.toLowerCase() : '';\r
5802                 \r
5803                                 return col !== undefined || type == 'td' || type == 'th' ?\r
5804                                         api.cell( src, col ).data() :\r
5805                                         api.row( src ).data() || null;\r
5806                         }\r
5807                 \r
5808                         return api.data().toArray();\r
5809                 };\r
5810                 \r
5811                 \r
5812                 /**\r
5813                  * Get an array of the TR nodes that are used in the table's body. Note that you will\r
5814                  * typically want to use the '$' API method in preference to this as it is more\r
5815                  * flexible.\r
5816                  *  @param {int} [iRow] Optional row index for the TR element you want\r
5817                  *  @returns {array|node} If iRow is undefined, returns an array of all TR elements\r
5818                  *    in the table's body, or iRow is defined, just the TR element requested.\r
5819                  *  @dtopt API\r
5820                  *  @deprecated Since v1.10\r
5821                  *\r
5822                  *  @example\r
5823                  *    $(document).ready(function() {\r
5824                  *      var oTable = $('#example').dataTable();\r
5825                  *\r
5826                  *      // Get the nodes from the table\r
5827                  *      var nNodes = oTable.fnGetNodes( );\r
5828                  *    } );\r
5829                  */\r
5830                 this.fnGetNodes = function( iRow )\r
5831                 {\r
5832                         var api = this.api( true );\r
5833                 \r
5834                         return iRow !== undefined ?\r
5835                                 api.row( iRow ).node() :\r
5836                                 api.rows().nodes().flatten().toArray();\r
5837                 };\r
5838                 \r
5839                 \r
5840                 /**\r
5841                  * Get the array indexes of a particular cell from it's DOM element\r
5842                  * and column index including hidden columns\r
5843                  *  @param {node} node this can either be a TR, TD or TH in the table's body\r
5844                  *  @returns {int} If nNode is given as a TR, then a single index is returned, or\r
5845                  *    if given as a cell, an array of [row index, column index (visible),\r
5846                  *    column index (all)] is given.\r
5847                  *  @dtopt API\r
5848                  *  @deprecated Since v1.10\r
5849                  *\r
5850                  *  @example\r
5851                  *    $(document).ready(function() {\r
5852                  *      $('#example tbody td').click( function () {\r
5853                  *        // Get the position of the current data from the node\r
5854                  *        var aPos = oTable.fnGetPosition( this );\r
5855                  *\r
5856                  *        // Get the data array for this row\r
5857                  *        var aData = oTable.fnGetData( aPos[0] );\r
5858                  *\r
5859                  *        // Update the data array and return the value\r
5860                  *        aData[ aPos[1] ] = 'clicked';\r
5861                  *        this.innerHTML = 'clicked';\r
5862                  *      } );\r
5863                  *\r
5864                  *      // Init DataTables\r
5865                  *      oTable = $('#example').dataTable();\r
5866                  *    } );\r
5867                  */\r
5868                 this.fnGetPosition = function( node )\r
5869                 {\r
5870                         var api = this.api( true );\r
5871                         var nodeName = node.nodeName.toUpperCase();\r
5872                 \r
5873                         if ( nodeName == 'TR' ) {\r
5874                                 return api.row( node ).index();\r
5875                         }\r
5876                         else if ( nodeName == 'TD' || nodeName == 'TH' ) {\r
5877                                 var cell = api.cell( node ).index();\r
5878                 \r
5879                                 return [\r
5880                                         cell.row,\r
5881                                         cell.columnVisible,\r
5882                                         cell.column\r
5883                                 ];\r
5884                         }\r
5885                         return null;\r
5886                 };\r
5887                 \r
5888                 \r
5889                 /**\r
5890                  * Check to see if a row is 'open' or not.\r
5891                  *  @param {node} nTr the table row to check\r
5892                  *  @returns {boolean} true if the row is currently open, false otherwise\r
5893                  *  @dtopt API\r
5894                  *  @deprecated Since v1.10\r
5895                  *\r
5896                  *  @example\r
5897                  *    $(document).ready(function() {\r
5898                  *      var oTable;\r
5899                  *\r
5900                  *      // 'open' an information row when a row is clicked on\r
5901                  *      $('#example tbody tr').click( function () {\r
5902                  *        if ( oTable.fnIsOpen(this) ) {\r
5903                  *          oTable.fnClose( this );\r
5904                  *        } else {\r
5905                  *          oTable.fnOpen( this, "Temporary row opened", "info_row" );\r
5906                  *        }\r
5907                  *      } );\r
5908                  *\r
5909                  *      oTable = $('#example').dataTable();\r
5910                  *    } );\r
5911                  */\r
5912                 this.fnIsOpen = function( nTr )\r
5913                 {\r
5914                         return this.api( true ).row( nTr ).child.isShown();\r
5915                 };\r
5916                 \r
5917                 \r
5918                 /**\r
5919                  * This function will place a new row directly after a row which is currently\r
5920                  * on display on the page, with the HTML contents that is passed into the\r
5921                  * function. This can be used, for example, to ask for confirmation that a\r
5922                  * particular record should be deleted.\r
5923                  *  @param {node} nTr The table row to 'open'\r
5924                  *  @param {string|node|jQuery} mHtml The HTML to put into the row\r
5925                  *  @param {string} sClass Class to give the new TD cell\r
5926                  *  @returns {node} The row opened. Note that if the table row passed in as the\r
5927                  *    first parameter, is not found in the table, this method will silently\r
5928                  *    return.\r
5929                  *  @dtopt API\r
5930                  *  @deprecated Since v1.10\r
5931                  *\r
5932                  *  @example\r
5933                  *    $(document).ready(function() {\r
5934                  *      var oTable;\r
5935                  *\r
5936                  *      // 'open' an information row when a row is clicked on\r
5937                  *      $('#example tbody tr').click( function () {\r
5938                  *        if ( oTable.fnIsOpen(this) ) {\r
5939                  *          oTable.fnClose( this );\r
5940                  *        } else {\r
5941                  *          oTable.fnOpen( this, "Temporary row opened", "info_row" );\r
5942                  *        }\r
5943                  *      } );\r
5944                  *\r
5945                  *      oTable = $('#example').dataTable();\r
5946                  *    } );\r
5947                  */\r
5948                 this.fnOpen = function( nTr, mHtml, sClass )\r
5949                 {\r
5950                         return this.api( true )\r
5951                                 .row( nTr )\r
5952                                 .child( mHtml, sClass )\r
5953                                 .show()\r
5954                                 .child()[0];\r
5955                 };\r
5956                 \r
5957                 \r
5958                 /**\r
5959                  * Change the pagination - provides the internal logic for pagination in a simple API\r
5960                  * function. With this function you can have a DataTables table go to the next,\r
5961                  * previous, first or last pages.\r
5962                  *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"\r
5963                  *    or page number to jump to (integer), note that page 0 is the first page.\r
5964                  *  @param {bool} [bRedraw=true] Redraw the table or not\r
5965                  *  @dtopt API\r
5966                  *  @deprecated Since v1.10\r
5967                  *\r
5968                  *  @example\r
5969                  *    $(document).ready(function() {\r
5970                  *      var oTable = $('#example').dataTable();\r
5971                  *      oTable.fnPageChange( 'next' );\r
5972                  *    } );\r
5973                  */\r
5974                 this.fnPageChange = function ( mAction, bRedraw )\r
5975                 {\r
5976                         var api = this.api( true ).page( mAction );\r
5977                 \r
5978                         if ( bRedraw === undefined || bRedraw ) {\r
5979                                 api.draw(false);\r
5980                         }\r
5981                 };\r
5982                 \r
5983                 \r
5984                 /**\r
5985                  * Show a particular column\r
5986                  *  @param {int} iCol The column whose display should be changed\r
5987                  *  @param {bool} bShow Show (true) or hide (false) the column\r
5988                  *  @param {bool} [bRedraw=true] Redraw the table or not\r
5989                  *  @dtopt API\r
5990                  *  @deprecated Since v1.10\r
5991                  *\r
5992                  *  @example\r
5993                  *    $(document).ready(function() {\r
5994                  *      var oTable = $('#example').dataTable();\r
5995                  *\r
5996                  *      // Hide the second column after initialisation\r
5997                  *      oTable.fnSetColumnVis( 1, false );\r
5998                  *    } );\r
5999                  */\r
6000                 this.fnSetColumnVis = function ( iCol, bShow, bRedraw )\r
6001                 {\r
6002                         var api = this.api( true ).column( iCol ).visible( bShow );\r
6003                 \r
6004                         if ( bRedraw === undefined || bRedraw ) {\r
6005                                 api.columns.adjust().draw();\r
6006                         }\r
6007                 };\r
6008                 \r
6009                 \r
6010                 /**\r
6011                  * Get the settings for a particular table for external manipulation\r
6012                  *  @returns {object} DataTables settings object. See\r
6013                  *    {@link DataTable.models.oSettings}\r
6014                  *  @dtopt API\r
6015                  *  @deprecated Since v1.10\r
6016                  *\r
6017                  *  @example\r
6018                  *    $(document).ready(function() {\r
6019                  *      var oTable = $('#example').dataTable();\r
6020                  *      var oSettings = oTable.fnSettings();\r
6021                  *\r
6022                  *      // Show an example parameter from the settings\r
6023                  *      alert( oSettings._iDisplayStart );\r
6024                  *    } );\r
6025                  */\r
6026                 this.fnSettings = function()\r
6027                 {\r
6028                         return _fnSettingsFromNode( this[_ext.iApiIndex] );\r
6029                 };\r
6030                 \r
6031                 \r
6032                 /**\r
6033                  * Sort the table by a particular column\r
6034                  *  @param {int} iCol the data index to sort on. Note that this will not match the\r
6035                  *    'display index' if you have hidden data entries\r
6036                  *  @dtopt API\r
6037                  *  @deprecated Since v1.10\r
6038                  *\r
6039                  *  @example\r
6040                  *    $(document).ready(function() {\r
6041                  *      var oTable = $('#example').dataTable();\r
6042                  *\r
6043                  *      // Sort immediately with columns 0 and 1\r
6044                  *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );\r
6045                  *    } );\r
6046                  */\r
6047                 this.fnSort = function( aaSort )\r
6048                 {\r
6049                         this.api( true ).order( aaSort ).draw();\r
6050                 };\r
6051                 \r
6052                 \r
6053                 /**\r
6054                  * Attach a sort listener to an element for a given column\r
6055                  *  @param {node} nNode the element to attach the sort listener to\r
6056                  *  @param {int} iColumn the column that a click on this node will sort on\r
6057                  *  @param {function} [fnCallback] callback function when sort is run\r
6058                  *  @dtopt API\r
6059                  *  @deprecated Since v1.10\r
6060                  *\r
6061                  *  @example\r
6062                  *    $(document).ready(function() {\r
6063                  *      var oTable = $('#example').dataTable();\r
6064                  *\r
6065                  *      // Sort on column 1, when 'sorter' is clicked on\r
6066                  *      oTable.fnSortListener( document.getElementById('sorter'), 1 );\r
6067                  *    } );\r
6068                  */\r
6069                 this.fnSortListener = function( nNode, iColumn, fnCallback )\r
6070                 {\r
6071                         this.api( true ).order.listener( nNode, iColumn, fnCallback );\r
6072                 };\r
6073                 \r
6074                 \r
6075                 /**\r
6076                  * Update a table cell or row - this method will accept either a single value to\r
6077                  * update the cell with, an array of values with one element for each column or\r
6078                  * an object in the same format as the original data source. The function is\r
6079                  * self-referencing in order to make the multi column updates easier.\r
6080                  *  @param {object|array|string} mData Data to update the cell/row with\r
6081                  *  @param {node|int} mRow TR element you want to update or the aoData index\r
6082                  *  @param {int} [iColumn] The column to update, give as null or undefined to\r
6083                  *    update a whole row.\r
6084                  *  @param {bool} [bRedraw=true] Redraw the table or not\r
6085                  *  @param {bool} [bAction=true] Perform pre-draw actions or not\r
6086                  *  @returns {int} 0 on success, 1 on error\r
6087                  *  @dtopt API\r
6088                  *  @deprecated Since v1.10\r
6089                  *\r
6090                  *  @example\r
6091                  *    $(document).ready(function() {\r
6092                  *      var oTable = $('#example').dataTable();\r
6093                  *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell\r
6094                  *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row\r
6095                  *    } );\r
6096                  */\r
6097                 this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )\r
6098                 {\r
6099                         var api = this.api( true );\r
6100                 \r
6101                         if ( iColumn === undefined || iColumn === null ) {\r
6102                                 api.row( mRow ).data( mData );\r
6103                         }\r
6104                         else {\r
6105                                 api.cell( mRow, iColumn ).data( mData );\r
6106                         }\r
6107                 \r
6108                         if ( bAction === undefined || bAction ) {\r
6109                                 api.columns.adjust();\r
6110                         }\r
6111                 \r
6112                         if ( bRedraw === undefined || bRedraw ) {\r
6113                                 api.draw();\r
6114                         }\r
6115                         return 0;\r
6116                 };\r
6117                 \r
6118                 \r
6119                 /**\r
6120                  * Provide a common method for plug-ins to check the version of DataTables being used, in order\r
6121                  * to ensure compatibility.\r
6122                  *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the\r
6123                  *    formats "X" and "X.Y" are also acceptable.\r
6124                  *  @returns {boolean} true if this version of DataTables is greater or equal to the required\r
6125                  *    version, or false if this version of DataTales is not suitable\r
6126                  *  @method\r
6127                  *  @dtopt API\r
6128                  *  @deprecated Since v1.10\r
6129                  *\r
6130                  *  @example\r
6131                  *    $(document).ready(function() {\r
6132                  *      var oTable = $('#example').dataTable();\r
6133                  *      alert( oTable.fnVersionCheck( '1.9.0' ) );\r
6134                  *    } );\r
6135                  */\r
6136                 this.fnVersionCheck = _ext.fnVersionCheck;\r
6137                 \r
6138 \r
6139                 var _that = this;\r
6140                 var emptyInit = options === undefined;\r
6141                 var len = this.length;\r
6142 \r
6143                 if ( emptyInit ) {\r
6144                         options = {};\r
6145                 }\r
6146 \r
6147                 this.oApi = this.internal = _ext.internal;\r
6148 \r
6149                 // Extend with old style plug-in API methods\r
6150                 for ( var fn in DataTable.ext.internal ) {\r
6151                         if ( fn ) {\r
6152                                 this[fn] = _fnExternApiFunc(fn);\r
6153                         }\r
6154                 }\r
6155 \r
6156                 this.each(function() {\r
6157                         // For each initialisation we want to give it a clean initialisation\r
6158                         // object that can be bashed around\r
6159                         var o = {};\r
6160                         var oInit = len > 1 ? // optimisation for single table case\r
6161                                 _fnExtend( o, options, true ) :\r
6162                                 options;\r
6163 \r
6164                         /*global oInit,_that,emptyInit*/\r
6165                         var i=0, iLen, j, jLen, k, kLen;\r
6166                         var sId = this.getAttribute( 'id' );\r
6167                         var bInitHandedOff = false;\r
6168                         var defaults = DataTable.defaults;\r
6169                         var $this = $(this);\r
6170                         \r
6171                         \r
6172                         /* Sanity check */\r
6173                         if ( this.nodeName.toLowerCase() != 'table' )\r
6174                         {\r
6175                                 _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );\r
6176                                 return;\r
6177                         }\r
6178                         \r
6179                         /* Backwards compatibility for the defaults */\r
6180                         _fnCompatOpts( defaults );\r
6181                         _fnCompatCols( defaults.column );\r
6182                         \r
6183                         /* Convert the camel-case defaults to Hungarian */\r
6184                         _fnCamelToHungarian( defaults, defaults, true );\r
6185                         _fnCamelToHungarian( defaults.column, defaults.column, true );\r
6186                         \r
6187                         /* Setting up the initialisation object */\r
6188                         _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) );\r
6189                         \r
6190                         \r
6191                         \r
6192                         /* Check to see if we are re-initialising a table */\r
6193                         var allSettings = DataTable.settings;\r
6194                         for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )\r
6195                         {\r
6196                                 var s = allSettings[i];\r
6197                         \r
6198                                 /* Base check on table node */\r
6199                                 if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) )\r
6200                                 {\r
6201                                         var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;\r
6202                                         var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;\r
6203                         \r
6204                                         if ( emptyInit || bRetrieve )\r
6205                                         {\r
6206                                                 return s.oInstance;\r
6207                                         }\r
6208                                         else if ( bDestroy )\r
6209                                         {\r
6210                                                 s.oInstance.fnDestroy();\r
6211                                                 break;\r
6212                                         }\r
6213                                         else\r
6214                                         {\r
6215                                                 _fnLog( s, 0, 'Cannot reinitialise DataTable', 3 );\r
6216                                                 return;\r
6217                                         }\r
6218                                 }\r
6219                         \r
6220                                 /* If the element we are initialising has the same ID as a table which was previously\r
6221                                  * initialised, but the table nodes don't match (from before) then we destroy the old\r
6222                                  * instance by simply deleting it. This is under the assumption that the table has been\r
6223                                  * destroyed by other methods. Anyone using non-id selectors will need to do this manually\r
6224                                  */\r
6225                                 if ( s.sTableId == this.id )\r
6226                                 {\r
6227                                         allSettings.splice( i, 1 );\r
6228                                         break;\r
6229                                 }\r
6230                         }\r
6231                         \r
6232                         /* Ensure the table has an ID - required for accessibility */\r
6233                         if ( sId === null || sId === "" )\r
6234                         {\r
6235                                 sId = "DataTables_Table_"+(DataTable.ext._unique++);\r
6236                                 this.id = sId;\r
6237                         }\r
6238                         \r
6239                         /* Create the settings object for this table and set some of the default parameters */\r
6240                         var oSettings = $.extend( true, {}, DataTable.models.oSettings, {\r
6241                                 "sDestroyWidth": $this[0].style.width,\r
6242                                 "sInstance":     sId,\r
6243                                 "sTableId":      sId\r
6244                         } );\r
6245                         oSettings.nTable = this;\r
6246                         oSettings.oApi   = _that.internal;\r
6247                         oSettings.oInit  = oInit;\r
6248                         \r
6249                         allSettings.push( oSettings );\r
6250                         \r
6251                         // Need to add the instance after the instance after the settings object has been added\r
6252                         // to the settings array, so we can self reference the table instance if more than one\r
6253                         oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable();\r
6254                         \r
6255                         // Backwards compatibility, before we apply all the defaults\r
6256                         _fnCompatOpts( oInit );\r
6257                         \r
6258                         if ( oInit.oLanguage )\r
6259                         {\r
6260                                 _fnLanguageCompat( oInit.oLanguage );\r
6261                         }\r
6262                         \r
6263                         // If the length menu is given, but the init display length is not, use the length menu\r
6264                         if ( oInit.aLengthMenu && ! oInit.iDisplayLength )\r
6265                         {\r
6266                                 oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?\r
6267                                         oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];\r
6268                         }\r
6269                         \r
6270                         // Apply the defaults and init options to make a single init object will all\r
6271                         // options defined from defaults and instance options.\r
6272                         oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );\r
6273                         \r
6274                         \r
6275                         // Map the initialisation options onto the settings object\r
6276                         _fnMap( oSettings.oFeatures, oInit, [\r
6277                                 "bPaginate",\r
6278                                 "bLengthChange",\r
6279                                 "bFilter",\r
6280                                 "bSort",\r
6281                                 "bSortMulti",\r
6282                                 "bInfo",\r
6283                                 "bProcessing",\r
6284                                 "bAutoWidth",\r
6285                                 "bSortClasses",\r
6286                                 "bServerSide",\r
6287                                 "bDeferRender"\r
6288                         ] );\r
6289                         _fnMap( oSettings, oInit, [\r
6290                                 "asStripeClasses",\r
6291                                 "ajax",\r
6292                                 "fnServerData",\r
6293                                 "fnFormatNumber",\r
6294                                 "sServerMethod",\r
6295                                 "aaSorting",\r
6296                                 "aaSortingFixed",\r
6297                                 "aLengthMenu",\r
6298                                 "sPaginationType",\r
6299                                 "sAjaxSource",\r
6300                                 "sAjaxDataProp",\r
6301                                 "iStateDuration",\r
6302                                 "sDom",\r
6303                                 "bSortCellsTop",\r
6304                                 "iTabIndex",\r
6305                                 "fnStateLoadCallback",\r
6306                                 "fnStateSaveCallback",\r
6307                                 "renderer",\r
6308                                 "searchDelay",\r
6309                                 "rowId",\r
6310                                 [ "iCookieDuration", "iStateDuration" ], // backwards compat\r
6311                                 [ "oSearch", "oPreviousSearch" ],\r
6312                                 [ "aoSearchCols", "aoPreSearchCols" ],\r
6313                                 [ "iDisplayLength", "_iDisplayLength" ],\r
6314                                 [ "bJQueryUI", "bJUI" ]\r
6315                         ] );\r
6316                         _fnMap( oSettings.oScroll, oInit, [\r
6317                                 [ "sScrollX", "sX" ],\r
6318                                 [ "sScrollXInner", "sXInner" ],\r
6319                                 [ "sScrollY", "sY" ],\r
6320                                 [ "bScrollCollapse", "bCollapse" ]\r
6321                         ] );\r
6322                         _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );\r
6323                         \r
6324                         /* Callback functions which are array driven */\r
6325                         _fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );\r
6326                         _fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );\r
6327                         _fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );\r
6328                         _fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );\r
6329                         _fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );\r
6330                         _fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );\r
6331                         _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );\r
6332                         _fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );\r
6333                         _fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );\r
6334                         _fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );\r
6335                         _fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );\r
6336                         \r
6337                         oSettings.rowIdFn = _fnGetObjectDataFn( oInit.rowId );\r
6338                         \r
6339                         /* Browser support detection */\r
6340                         _fnBrowserDetect( oSettings );\r
6341                         \r
6342                         var oClasses = oSettings.oClasses;\r
6343                         \r
6344                         // @todo Remove in 1.11\r
6345                         if ( oInit.bJQueryUI )\r
6346                         {\r
6347                                 /* Use the JUI classes object for display. You could clone the oStdClasses object if\r
6348                                  * you want to have multiple tables with multiple independent classes\r
6349                                  */\r
6350                                 $.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses );\r
6351                         \r
6352                                 if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" )\r
6353                                 {\r
6354                                         /* Set the DOM to use a layout suitable for jQuery UI's theming */\r
6355                                         oSettings.sDom = '<"H"lfr>t<"F"ip>';\r
6356                                 }\r
6357                         \r
6358                                 if ( ! oSettings.renderer ) {\r
6359                                         oSettings.renderer = 'jqueryui';\r
6360                                 }\r
6361                                 else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) {\r
6362                                         oSettings.renderer.header = 'jqueryui';\r
6363                                 }\r
6364                         }\r
6365                         else\r
6366                         {\r
6367                                 $.extend( oClasses, DataTable.ext.classes, oInit.oClasses );\r
6368                         }\r
6369                         $this.addClass( oClasses.sTable );\r
6370                         \r
6371                         \r
6372                         if ( oSettings.iInitDisplayStart === undefined )\r
6373                         {\r
6374                                 /* Display start point, taking into account the save saving */\r
6375                                 oSettings.iInitDisplayStart = oInit.iDisplayStart;\r
6376                                 oSettings._iDisplayStart = oInit.iDisplayStart;\r
6377                         }\r
6378                         \r
6379                         if ( oInit.iDeferLoading !== null )\r
6380                         {\r
6381                                 oSettings.bDeferLoading = true;\r
6382                                 var tmp = $.isArray( oInit.iDeferLoading );\r
6383                                 oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;\r
6384                                 oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;\r
6385                         }\r
6386                         \r
6387                         /* Language definitions */\r
6388                         var oLanguage = oSettings.oLanguage;\r
6389                         $.extend( true, oLanguage, oInit.oLanguage );\r
6390                         \r
6391                         if ( oLanguage.sUrl !== "" )\r
6392                         {\r
6393                                 /* Get the language definitions from a file - because this Ajax call makes the language\r
6394                                  * get async to the remainder of this function we use bInitHandedOff to indicate that\r
6395                                  * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor\r
6396                                  */\r
6397                                 $.ajax( {\r
6398                                         dataType: 'json',\r
6399                                         url: oLanguage.sUrl,\r
6400                                         success: function ( json ) {\r
6401                                                 _fnLanguageCompat( json );\r
6402                                                 _fnCamelToHungarian( defaults.oLanguage, json );\r
6403                                                 $.extend( true, oLanguage, json );\r
6404                                                 _fnInitialise( oSettings );\r
6405                                         },\r
6406                                         error: function () {\r
6407                                                 // Error occurred loading language file, continue on as best we can\r
6408                                                 _fnInitialise( oSettings );\r
6409                                         }\r
6410                                 } );\r
6411                                 bInitHandedOff = true;\r
6412                         }\r
6413                         \r
6414                         /*\r
6415                          * Stripes\r
6416                          */\r
6417                         if ( oInit.asStripeClasses === null )\r
6418                         {\r
6419                                 oSettings.asStripeClasses =[\r
6420                                         oClasses.sStripeOdd,\r
6421                                         oClasses.sStripeEven\r
6422                                 ];\r
6423                         }\r
6424                         \r
6425                         /* Remove row stripe classes if they are already on the table row */\r
6426                         var stripeClasses = oSettings.asStripeClasses;\r
6427                         var rowOne = $this.children('tbody').find('tr').eq(0);\r
6428                         if ( $.inArray( true, $.map( stripeClasses, function(el, i) {\r
6429                                 return rowOne.hasClass(el);\r
6430                         } ) ) !== -1 ) {\r
6431                                 $('tbody tr', this).removeClass( stripeClasses.join(' ') );\r
6432                                 oSettings.asDestroyStripes = stripeClasses.slice();\r
6433                         }\r
6434                         \r
6435                         /*\r
6436                          * Columns\r
6437                          * See if we should load columns automatically or use defined ones\r
6438                          */\r
6439                         var anThs = [];\r
6440                         var aoColumnsInit;\r
6441                         var nThead = this.getElementsByTagName('thead');\r
6442                         if ( nThead.length !== 0 )\r
6443                         {\r
6444                                 _fnDetectHeader( oSettings.aoHeader, nThead[0] );\r
6445                                 anThs = _fnGetUniqueThs( oSettings );\r
6446                         }\r
6447                         \r
6448                         /* If not given a column array, generate one with nulls */\r
6449                         if ( oInit.aoColumns === null )\r
6450                         {\r
6451                                 aoColumnsInit = [];\r
6452                                 for ( i=0, iLen=anThs.length ; i<iLen ; i++ )\r
6453                                 {\r
6454                                         aoColumnsInit.push( null );\r
6455                                 }\r
6456                         }\r
6457                         else\r
6458                         {\r
6459                                 aoColumnsInit = oInit.aoColumns;\r
6460                         }\r
6461                         \r
6462                         /* Add the columns */\r
6463                         for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )\r
6464                         {\r
6465                                 _fnAddColumn( oSettings, anThs ? anThs[i] : null );\r
6466                         }\r
6467                         \r
6468                         /* Apply the column definitions */\r
6469                         _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {\r
6470                                 _fnColumnOptions( oSettings, iCol, oDef );\r
6471                         } );\r
6472                         \r
6473                         /* HTML5 attribute detection - build an mData object automatically if the\r
6474                          * attributes are found\r
6475                          */\r
6476                         if ( rowOne.length ) {\r
6477                                 var a = function ( cell, name ) {\r
6478                                         return cell.getAttribute( 'data-'+name ) !== null ? name : null;\r
6479                                 };\r
6480                         \r
6481                                 $( rowOne[0] ).children('th, td').each( function (i, cell) {\r
6482                                         var col = oSettings.aoColumns[i];\r
6483                         \r
6484                                         if ( col.mData === i ) {\r
6485                                                 var sort = a( cell, 'sort' ) || a( cell, 'order' );\r
6486                                                 var filter = a( cell, 'filter' ) || a( cell, 'search' );\r
6487                         \r
6488                                                 if ( sort !== null || filter !== null ) {\r
6489                                                         col.mData = {\r
6490                                                                 _:      i+'.display',\r
6491                                                                 sort:   sort !== null   ? i+'.@data-'+sort   : undefined,\r
6492                                                                 type:   sort !== null   ? i+'.@data-'+sort   : undefined,\r
6493                                                                 filter: filter !== null ? i+'.@data-'+filter : undefined\r
6494                                                         };\r
6495                         \r
6496                                                         _fnColumnOptions( oSettings, i );\r
6497                                                 }\r
6498                                         }\r
6499                                 } );\r
6500                         }\r
6501                         \r
6502                         var features = oSettings.oFeatures;\r
6503                         \r
6504                         /* Must be done after everything which can be overridden by the state saving! */\r
6505                         if ( oInit.bStateSave )\r
6506                         {\r
6507                                 features.bStateSave = true;\r
6508                                 _fnLoadState( oSettings, oInit );\r
6509                                 _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );\r
6510                         }\r
6511                         \r
6512                         \r
6513                         /*\r
6514                          * Sorting\r
6515                          * @todo For modularisation (1.11) this needs to do into a sort start up handler\r
6516                          */\r
6517                         \r
6518                         // If aaSorting is not defined, then we use the first indicator in asSorting\r
6519                         // in case that has been altered, so the default sort reflects that option\r
6520                         if ( oInit.aaSorting === undefined )\r
6521                         {\r
6522                                 var sorting = oSettings.aaSorting;\r
6523                                 for ( i=0, iLen=sorting.length ; i<iLen ; i++ )\r
6524                                 {\r
6525                                         sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];\r
6526                                 }\r
6527                         }\r
6528                         \r
6529                         /* Do a first pass on the sorting classes (allows any size changes to be taken into\r
6530                          * account, and also will apply sorting disabled classes if disabled\r
6531                          */\r
6532                         _fnSortingClasses( oSettings );\r
6533                         \r
6534                         if ( features.bSort )\r
6535                         {\r
6536                                 _fnCallbackReg( oSettings, 'aoDrawCallback', function () {\r
6537                                         if ( oSettings.bSorted ) {\r
6538                                                 var aSort = _fnSortFlatten( oSettings );\r
6539                                                 var sortedColumns = {};\r
6540                         \r
6541                                                 $.each( aSort, function (i, val) {\r
6542                                                         sortedColumns[ val.src ] = val.dir;\r
6543                                                 } );\r
6544                         \r
6545                                                 _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );\r
6546                                                 _fnSortAria( oSettings );\r
6547                                         }\r
6548                                 } );\r
6549                         }\r
6550                         \r
6551                         _fnCallbackReg( oSettings, 'aoDrawCallback', function () {\r
6552                                 if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {\r
6553                                         _fnSortingClasses( oSettings );\r
6554                                 }\r
6555                         }, 'sc' );\r
6556                         \r
6557                         \r
6558                         /*\r
6559                          * Final init\r
6560                          * Cache the header, body and footer as required, creating them if needed\r
6561                          */\r
6562                         \r
6563                         // Work around for Webkit bug 83867 - store the caption-side before removing from doc\r
6564                         var captions = $this.children('caption').each( function () {\r
6565                                 this._captionSide = $this.css('caption-side');\r
6566                         } );\r
6567                         \r
6568                         var thead = $this.children('thead');\r
6569                         if ( thead.length === 0 )\r
6570                         {\r
6571                                 thead = $('<thead/>').appendTo(this);\r
6572                         }\r
6573                         oSettings.nTHead = thead[0];\r
6574                         \r
6575                         var tbody = $this.children('tbody');\r
6576                         if ( tbody.length === 0 )\r
6577                         {\r
6578                                 tbody = $('<tbody/>').appendTo(this);\r
6579                         }\r
6580                         oSettings.nTBody = tbody[0];\r
6581                         \r
6582                         var tfoot = $this.children('tfoot');\r
6583                         if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )\r
6584                         {\r
6585                                 // If we are a scrolling table, and no footer has been given, then we need to create\r
6586                                 // a tfoot element for the caption element to be appended to\r
6587                                 tfoot = $('<tfoot/>').appendTo(this);\r
6588                         }\r
6589                         \r
6590                         if ( tfoot.length === 0 || tfoot.children().length === 0 ) {\r
6591                                 $this.addClass( oClasses.sNoFooter );\r
6592                         }\r
6593                         else if ( tfoot.length > 0 ) {\r
6594                                 oSettings.nTFoot = tfoot[0];\r
6595                                 _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );\r
6596                         }\r
6597                         \r
6598                         /* Check if there is data passing into the constructor */\r
6599                         if ( oInit.aaData )\r
6600                         {\r
6601                                 for ( i=0 ; i<oInit.aaData.length ; i++ )\r
6602                                 {\r
6603                                         _fnAddData( oSettings, oInit.aaData[ i ] );\r
6604                                 }\r
6605                         }\r
6606                         else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' )\r
6607                         {\r
6608                                 /* Grab the data from the page - only do this when deferred loading or no Ajax\r
6609                                  * source since there is no point in reading the DOM data if we are then going\r
6610                                  * to replace it with Ajax data\r
6611                                  */\r
6612                                 _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );\r
6613                         }\r
6614                         \r
6615                         /* Copy the data index array */\r
6616                         oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();\r
6617                         \r
6618                         /* Initialisation complete - table can be drawn */\r
6619                         oSettings.bInitialised = true;\r
6620                         \r
6621                         /* Check if we need to initialise the table (it might not have been handed off to the\r
6622                          * language processor)\r
6623                          */\r
6624                         if ( bInitHandedOff === false )\r
6625                         {\r
6626                                 _fnInitialise( oSettings );\r
6627                         }\r
6628                 } );\r
6629                 _that = null;\r
6630                 return this;\r
6631         };\r
6632 \r
6633         \r
6634         \r
6635         /**\r
6636          * Computed structure of the DataTables API, defined by the options passed to\r
6637          * `DataTable.Api.register()` when building the API.\r
6638          *\r
6639          * The structure is built in order to speed creation and extension of the Api\r
6640          * objects since the extensions are effectively pre-parsed.\r
6641          *\r
6642          * The array is an array of objects with the following structure, where this\r
6643          * base array represents the Api prototype base:\r
6644          *\r
6645          *     [\r
6646          *       {\r
6647          *         name:      'data'                -- string   - Property name\r
6648          *         val:       function () {},       -- function - Api method (or undefined if just an object\r
6649          *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result\r
6650          *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property\r
6651          *       },\r
6652          *       {\r
6653          *         name:     'row'\r
6654          *         val:       {},\r
6655          *         methodExt: [ ... ],\r
6656          *         propExt:   [\r
6657          *           {\r
6658          *             name:      'data'\r
6659          *             val:       function () {},\r
6660          *             methodExt: [ ... ],\r
6661          *             propExt:   [ ... ]\r
6662          *           },\r
6663          *           ...\r
6664          *         ]\r
6665          *       }\r
6666          *     ]\r
6667          *\r
6668          * @type {Array}\r
6669          * @ignore\r
6670          */\r
6671         var __apiStruct = [];\r
6672         \r
6673         \r
6674         /**\r
6675          * `Array.prototype` reference.\r
6676          *\r
6677          * @type object\r
6678          * @ignore\r
6679          */\r
6680         var __arrayProto = Array.prototype;\r
6681         \r
6682         \r
6683         /**\r
6684          * Abstraction for `context` parameter of the `Api` constructor to allow it to\r
6685          * take several different forms for ease of use.\r
6686          *\r
6687          * Each of the input parameter types will be converted to a DataTables settings\r
6688          * object where possible.\r
6689          *\r
6690          * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one\r
6691          *   of:\r
6692          *\r
6693          *   * `string` - jQuery selector. Any DataTables' matching the given selector\r
6694          *     with be found and used.\r
6695          *   * `node` - `TABLE` node which has already been formed into a DataTable.\r
6696          *   * `jQuery` - A jQuery object of `TABLE` nodes.\r
6697          *   * `object` - DataTables settings object\r
6698          *   * `DataTables.Api` - API instance\r
6699          * @return {array|null} Matching DataTables settings objects. `null` or\r
6700          *   `undefined` is returned if no matching DataTable is found.\r
6701          * @ignore\r
6702          */\r
6703         var _toSettings = function ( mixed )\r
6704         {\r
6705                 var idx, jq;\r
6706                 var settings = DataTable.settings;\r
6707                 var tables = $.map( settings, function (el, i) {\r
6708                         return el.nTable;\r
6709                 } );\r
6710         \r
6711                 if ( ! mixed ) {\r
6712                         return [];\r
6713                 }\r
6714                 else if ( mixed.nTable && mixed.oApi ) {\r
6715                         // DataTables settings object\r
6716                         return [ mixed ];\r
6717                 }\r
6718                 else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {\r
6719                         // Table node\r
6720                         idx = $.inArray( mixed, tables );\r
6721                         return idx !== -1 ? [ settings[idx] ] : null;\r
6722                 }\r
6723                 else if ( mixed && typeof mixed.settings === 'function' ) {\r
6724                         return mixed.settings().toArray();\r
6725                 }\r
6726                 else if ( typeof mixed === 'string' ) {\r
6727                         // jQuery selector\r
6728                         jq = $(mixed);\r
6729                 }\r
6730                 else if ( mixed instanceof $ ) {\r
6731                         // jQuery object (also DataTables instance)\r
6732                         jq = mixed;\r
6733                 }\r
6734         \r
6735                 if ( jq ) {\r
6736                         return jq.map( function(i) {\r
6737                                 idx = $.inArray( this, tables );\r
6738                                 return idx !== -1 ? settings[idx] : null;\r
6739                         } ).toArray();\r
6740                 }\r
6741         };\r
6742         \r
6743         \r
6744         /**\r
6745          * DataTables API class - used to control and interface with  one or more\r
6746          * DataTables enhanced tables.\r
6747          *\r
6748          * The API class is heavily based on jQuery, presenting a chainable interface\r
6749          * that you can use to interact with tables. Each instance of the API class has\r
6750          * a "context" - i.e. the tables that it will operate on. This could be a single\r
6751          * table, all tables on a page or a sub-set thereof.\r
6752          *\r
6753          * Additionally the API is designed to allow you to easily work with the data in\r
6754          * the tables, retrieving and manipulating it as required. This is done by\r
6755          * presenting the API class as an array like interface. The contents of the\r
6756          * array depend upon the actions requested by each method (for example\r
6757          * `rows().nodes()` will return an array of nodes, while `rows().data()` will\r
6758          * return an array of objects or arrays depending upon your table's\r
6759          * configuration). The API object has a number of array like methods (`push`,\r
6760          * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,\r
6761          * `unique` etc) to assist your working with the data held in a table.\r
6762          *\r
6763          * Most methods (those which return an Api instance) are chainable, which means\r
6764          * the return from a method call also has all of the methods available that the\r
6765          * top level object had. For example, these two calls are equivalent:\r
6766          *\r
6767          *     // Not chained\r
6768          *     api.row.add( {...} );\r
6769          *     api.draw();\r
6770          *\r
6771          *     // Chained\r
6772          *     api.row.add( {...} ).draw();\r
6773          *\r
6774          * @class DataTable.Api\r
6775          * @param {array|object|string|jQuery} context DataTable identifier. This is\r
6776          *   used to define which DataTables enhanced tables this API will operate on.\r
6777          *   Can be one of:\r
6778          *\r
6779          *   * `string` - jQuery selector. Any DataTables' matching the given selector\r
6780          *     with be found and used.\r
6781          *   * `node` - `TABLE` node which has already been formed into a DataTable.\r
6782          *   * `jQuery` - A jQuery object of `TABLE` nodes.\r
6783          *   * `object` - DataTables settings object\r
6784          * @param {array} [data] Data to initialise the Api instance with.\r
6785          *\r
6786          * @example\r
6787          *   // Direct initialisation during DataTables construction\r
6788          *   var api = $('#example').DataTable();\r
6789          *\r
6790          * @example\r
6791          *   // Initialisation using a DataTables jQuery object\r
6792          *   var api = $('#example').dataTable().api();\r
6793          *\r
6794          * @example\r
6795          *   // Initialisation as a constructor\r
6796          *   var api = new $.fn.DataTable.Api( 'table.dataTable' );\r
6797          */\r
6798         _Api = function ( context, data )\r
6799         {\r
6800                 if ( ! (this instanceof _Api) ) {\r
6801                         return new _Api( context, data );\r
6802                 }\r
6803         \r
6804                 var settings = [];\r
6805                 var ctxSettings = function ( o ) {\r
6806                         var a = _toSettings( o );\r
6807                         if ( a ) {\r
6808                                 settings = settings.concat( a );\r
6809                         }\r
6810                 };\r
6811         \r
6812                 if ( $.isArray( context ) ) {\r
6813                         for ( var i=0, ien=context.length ; i<ien ; i++ ) {\r
6814                                 ctxSettings( context[i] );\r
6815                         }\r
6816                 }\r
6817                 else {\r
6818                         ctxSettings( context );\r
6819                 }\r
6820         \r
6821                 // Remove duplicates\r
6822                 this.context = _unique( settings );\r
6823         \r
6824                 // Initial data\r
6825                 if ( data ) {\r
6826                         $.merge( this, data );\r
6827                 }\r
6828         \r
6829                 // selector\r
6830                 this.selector = {\r
6831                         rows: null,\r
6832                         cols: null,\r
6833                         opts: null\r
6834                 };\r
6835         \r
6836                 _Api.extend( this, this, __apiStruct );\r
6837         };\r
6838         \r
6839         DataTable.Api = _Api;\r
6840         \r
6841         // Don't destroy the existing prototype, just extend it. Required for jQuery 2's\r
6842         // isPlainObject.\r
6843         $.extend( _Api.prototype, {\r
6844                 any: function ()\r
6845                 {\r
6846                         return this.count() !== 0;\r
6847                 },\r
6848         \r
6849         \r
6850                 concat:  __arrayProto.concat,\r
6851         \r
6852         \r
6853                 context: [], // array of table settings objects\r
6854         \r
6855         \r
6856                 count: function ()\r
6857                 {\r
6858                         return this.flatten().length;\r
6859                 },\r
6860         \r
6861         \r
6862                 each: function ( fn )\r
6863                 {\r
6864                         for ( var i=0, ien=this.length ; i<ien; i++ ) {\r
6865                                 fn.call( this, this[i], i, this );\r
6866                         }\r
6867         \r
6868                         return this;\r
6869                 },\r
6870         \r
6871         \r
6872                 eq: function ( idx )\r
6873                 {\r
6874                         var ctx = this.context;\r
6875         \r
6876                         return ctx.length > idx ?\r
6877                                 new _Api( ctx[idx], this[idx] ) :\r
6878                                 null;\r
6879                 },\r
6880         \r
6881         \r
6882                 filter: function ( fn )\r
6883                 {\r
6884                         var a = [];\r
6885         \r
6886                         if ( __arrayProto.filter ) {\r
6887                                 a = __arrayProto.filter.call( this, fn, this );\r
6888                         }\r
6889                         else {\r
6890                                 // Compatibility for browsers without EMCA-252-5 (JS 1.6)\r
6891                                 for ( var i=0, ien=this.length ; i<ien ; i++ ) {\r
6892                                         if ( fn.call( this, this[i], i, this ) ) {\r
6893                                                 a.push( this[i] );\r
6894                                         }\r
6895                                 }\r
6896                         }\r
6897         \r
6898                         return new _Api( this.context, a );\r
6899                 },\r
6900         \r
6901         \r
6902                 flatten: function ()\r
6903                 {\r
6904                         var a = [];\r
6905                         return new _Api( this.context, a.concat.apply( a, this.toArray() ) );\r
6906                 },\r
6907         \r
6908         \r
6909                 join:    __arrayProto.join,\r
6910         \r
6911         \r
6912                 indexOf: __arrayProto.indexOf || function (obj, start)\r
6913                 {\r
6914                         for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {\r
6915                                 if ( this[i] === obj ) {\r
6916                                         return i;\r
6917                                 }\r
6918                         }\r
6919                         return -1;\r
6920                 },\r
6921         \r
6922                 iterator: function ( flatten, type, fn, alwaysNew ) {\r
6923                         var\r
6924                                 a = [], ret,\r
6925                                 i, ien, j, jen,\r
6926                                 context = this.context,\r
6927                                 rows, items, item,\r
6928                                 selector = this.selector;\r
6929         \r
6930                         // Argument shifting\r
6931                         if ( typeof flatten === 'string' ) {\r
6932                                 alwaysNew = fn;\r
6933                                 fn = type;\r
6934                                 type = flatten;\r
6935                                 flatten = false;\r
6936                         }\r
6937         \r
6938                         for ( i=0, ien=context.length ; i<ien ; i++ ) {\r
6939                                 var apiInst = new _Api( context[i] );\r
6940         \r
6941                                 if ( type === 'table' ) {\r
6942                                         ret = fn.call( apiInst, context[i], i );\r
6943         \r
6944                                         if ( ret !== undefined ) {\r
6945                                                 a.push( ret );\r
6946                                         }\r
6947                                 }\r
6948                                 else if ( type === 'columns' || type === 'rows' ) {\r
6949                                         // this has same length as context - one entry for each table\r
6950                                         ret = fn.call( apiInst, context[i], this[i], i );\r
6951         \r
6952                                         if ( ret !== undefined ) {\r
6953                                                 a.push( ret );\r
6954                                         }\r
6955                                 }\r
6956                                 else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {\r
6957                                         // columns and rows share the same structure.\r
6958                                         // 'this' is an array of column indexes for each context\r
6959                                         items = this[i];\r
6960         \r
6961                                         if ( type === 'column-rows' ) {\r
6962                                                 rows = _selector_row_indexes( context[i], selector.opts );\r
6963                                         }\r
6964         \r
6965                                         for ( j=0, jen=items.length ; j<jen ; j++ ) {\r
6966                                                 item = items[j];\r
6967         \r
6968                                                 if ( type === 'cell' ) {\r
6969                                                         ret = fn.call( apiInst, context[i], item.row, item.column, i, j );\r
6970                                                 }\r
6971                                                 else {\r
6972                                                         ret = fn.call( apiInst, context[i], item, i, j, rows );\r
6973                                                 }\r
6974         \r
6975                                                 if ( ret !== undefined ) {\r
6976                                                         a.push( ret );\r
6977                                                 }\r
6978                                         }\r
6979                                 }\r
6980                         }\r
6981         \r
6982                         if ( a.length || alwaysNew ) {\r
6983                                 var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );\r
6984                                 var apiSelector = api.selector;\r
6985                                 apiSelector.rows = selector.rows;\r
6986                                 apiSelector.cols = selector.cols;\r
6987                                 apiSelector.opts = selector.opts;\r
6988                                 return api;\r
6989                         }\r
6990                         return this;\r
6991                 },\r
6992         \r
6993         \r
6994                 lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)\r
6995                 {\r
6996                         // Bit cheeky...\r
6997                         return this.indexOf.apply( this.toArray.reverse(), arguments );\r
6998                 },\r
6999         \r
7000         \r
7001                 length:  0,\r
7002         \r
7003         \r
7004                 map: function ( fn )\r
7005                 {\r
7006                         var a = [];\r
7007         \r
7008                         if ( __arrayProto.map ) {\r
7009                                 a = __arrayProto.map.call( this, fn, this );\r
7010                         }\r
7011                         else {\r
7012                                 // Compatibility for browsers without EMCA-252-5 (JS 1.6)\r
7013                                 for ( var i=0, ien=this.length ; i<ien ; i++ ) {\r
7014                                         a.push( fn.call( this, this[i], i ) );\r
7015                                 }\r
7016                         }\r
7017         \r
7018                         return new _Api( this.context, a );\r
7019                 },\r
7020         \r
7021         \r
7022                 pluck: function ( prop )\r
7023                 {\r
7024                         return this.map( function ( el ) {\r
7025                                 return el[ prop ];\r
7026                         } );\r
7027                 },\r
7028         \r
7029                 pop:     __arrayProto.pop,\r
7030         \r
7031         \r
7032                 push:    __arrayProto.push,\r
7033         \r
7034         \r
7035                 // Does not return an API instance\r
7036                 reduce: __arrayProto.reduce || function ( fn, init )\r
7037                 {\r
7038                         return _fnReduce( this, fn, init, 0, this.length, 1 );\r
7039                 },\r
7040         \r
7041         \r
7042                 reduceRight: __arrayProto.reduceRight || function ( fn, init )\r
7043                 {\r
7044                         return _fnReduce( this, fn, init, this.length-1, -1, -1 );\r
7045                 },\r
7046         \r
7047         \r
7048                 reverse: __arrayProto.reverse,\r
7049         \r
7050         \r
7051                 // Object with rows, columns and opts\r
7052                 selector: null,\r
7053         \r
7054         \r
7055                 shift:   __arrayProto.shift,\r
7056         \r
7057         \r
7058                 sort:    __arrayProto.sort, // ? name - order?\r
7059         \r
7060         \r
7061                 splice:  __arrayProto.splice,\r
7062         \r
7063         \r
7064                 toArray: function ()\r
7065                 {\r
7066                         return __arrayProto.slice.call( this );\r
7067                 },\r
7068         \r
7069         \r
7070                 to$: function ()\r
7071                 {\r
7072                         return $( this );\r
7073                 },\r
7074         \r
7075         \r
7076                 toJQuery: function ()\r
7077                 {\r
7078                         return $( this );\r
7079                 },\r
7080         \r
7081         \r
7082                 unique: function ()\r
7083                 {\r
7084                         return new _Api( this.context, _unique(this) );\r
7085                 },\r
7086         \r
7087         \r
7088                 unshift: __arrayProto.unshift\r
7089         } );\r
7090         \r
7091         \r
7092         _Api.extend = function ( scope, obj, ext )\r
7093         {\r
7094                 // Only extend API instances and static properties of the API\r
7095                 if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {\r
7096                         return;\r
7097                 }\r
7098         \r
7099                 var\r
7100                         i, ien,\r
7101                         j, jen,\r
7102                         struct, inner,\r
7103                         methodScoping = function ( scope, fn, struc ) {\r
7104                                 return function () {\r
7105                                         var ret = fn.apply( scope, arguments );\r
7106         \r
7107                                         // Method extension\r
7108                                         _Api.extend( ret, ret, struc.methodExt );\r
7109                                         return ret;\r
7110                                 };\r
7111                         };\r
7112         \r
7113                 for ( i=0, ien=ext.length ; i<ien ; i++ ) {\r
7114                         struct = ext[i];\r
7115         \r
7116                         // Value\r
7117                         obj[ struct.name ] = typeof struct.val === 'function' ?\r
7118                                 methodScoping( scope, struct.val, struct ) :\r
7119                                 $.isPlainObject( struct.val ) ?\r
7120                                         {} :\r
7121                                         struct.val;\r
7122         \r
7123                         obj[ struct.name ].__dt_wrapper = true;\r
7124         \r
7125                         // Property extension\r
7126                         _Api.extend( scope, obj[ struct.name ], struct.propExt );\r
7127                 }\r
7128         };\r
7129         \r
7130         \r
7131         // @todo - Is there need for an augment function?\r
7132         // _Api.augment = function ( inst, name )\r
7133         // {\r
7134         //      // Find src object in the structure from the name\r
7135         //      var parts = name.split('.');\r
7136         \r
7137         //      _Api.extend( inst, obj );\r
7138         // };\r
7139         \r
7140         \r
7141         //     [\r
7142         //       {\r
7143         //         name:      'data'                -- string   - Property name\r
7144         //         val:       function () {},       -- function - Api method (or undefined if just an object\r
7145         //         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result\r
7146         //         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property\r
7147         //       },\r
7148         //       {\r
7149         //         name:     'row'\r
7150         //         val:       {},\r
7151         //         methodExt: [ ... ],\r
7152         //         propExt:   [\r
7153         //           {\r
7154         //             name:      'data'\r
7155         //             val:       function () {},\r
7156         //             methodExt: [ ... ],\r
7157         //             propExt:   [ ... ]\r
7158         //           },\r
7159         //           ...\r
7160         //         ]\r
7161         //       }\r
7162         //     ]\r
7163         \r
7164         _Api.register = _api_register = function ( name, val )\r
7165         {\r
7166                 if ( $.isArray( name ) ) {\r
7167                         for ( var j=0, jen=name.length ; j<jen ; j++ ) {\r
7168                                 _Api.register( name[j], val );\r
7169                         }\r
7170                         return;\r
7171                 }\r
7172         \r
7173                 var\r
7174                         i, ien,\r
7175                         heir = name.split('.'),\r
7176                         struct = __apiStruct,\r
7177                         key, method;\r
7178         \r
7179                 var find = function ( src, name ) {\r
7180                         for ( var i=0, ien=src.length ; i<ien ; i++ ) {\r
7181                                 if ( src[i].name === name ) {\r
7182                                         return src[i];\r
7183                                 }\r
7184                         }\r
7185                         return null;\r
7186                 };\r
7187         \r
7188                 for ( i=0, ien=heir.length ; i<ien ; i++ ) {\r
7189                         method = heir[i].indexOf('()') !== -1;\r
7190                         key = method ?\r
7191                                 heir[i].replace('()', '') :\r
7192                                 heir[i];\r
7193         \r
7194                         var src = find( struct, key );\r
7195                         if ( ! src ) {\r
7196                                 src = {\r
7197                                         name:      key,\r
7198                                         val:       {},\r
7199                                         methodExt: [],\r
7200                                         propExt:   []\r
7201                                 };\r
7202                                 struct.push( src );\r
7203                         }\r
7204         \r
7205                         if ( i === ien-1 ) {\r
7206                                 src.val = val;\r
7207                         }\r
7208                         else {\r
7209                                 struct = method ?\r
7210                                         src.methodExt :\r
7211                                         src.propExt;\r
7212                         }\r
7213                 }\r
7214         };\r
7215         \r
7216         \r
7217         _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {\r
7218                 _Api.register( pluralName, val );\r
7219         \r
7220                 _Api.register( singularName, function () {\r
7221                         var ret = val.apply( this, arguments );\r
7222         \r
7223                         if ( ret === this ) {\r
7224                                 // Returned item is the API instance that was passed in, return it\r
7225                                 return this;\r
7226                         }\r
7227                         else if ( ret instanceof _Api ) {\r
7228                                 // New API instance returned, want the value from the first item\r
7229                                 // in the returned array for the singular result.\r
7230                                 return ret.length ?\r
7231                                         $.isArray( ret[0] ) ?\r
7232                                                 new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'\r
7233                                                 ret[0] :\r
7234                                         undefined;\r
7235                         }\r
7236         \r
7237                         // Non-API return - just fire it back\r
7238                         return ret;\r
7239                 } );\r
7240         };\r
7241         \r
7242         \r
7243         /**\r
7244          * Selector for HTML tables. Apply the given selector to the give array of\r
7245          * DataTables settings objects.\r
7246          *\r
7247          * @param {string|integer} [selector] jQuery selector string or integer\r
7248          * @param  {array} Array of DataTables settings objects to be filtered\r
7249          * @return {array}\r
7250          * @ignore\r
7251          */\r
7252         var __table_selector = function ( selector, a )\r
7253         {\r
7254                 // Integer is used to pick out a table by index\r
7255                 if ( typeof selector === 'number' ) {\r
7256                         return [ a[ selector ] ];\r
7257                 }\r
7258         \r
7259                 // Perform a jQuery selector on the table nodes\r
7260                 var nodes = $.map( a, function (el, i) {\r
7261                         return el.nTable;\r
7262                 } );\r
7263         \r
7264                 return $(nodes)\r
7265                         .filter( selector )\r
7266                         .map( function (i) {\r
7267                                 // Need to translate back from the table node to the settings\r
7268                                 var idx = $.inArray( this, nodes );\r
7269                                 return a[ idx ];\r
7270                         } )\r
7271                         .toArray();\r
7272         };\r
7273         \r
7274         \r
7275         \r
7276         /**\r
7277          * Context selector for the API's context (i.e. the tables the API instance\r
7278          * refers to.\r
7279          *\r
7280          * @name    DataTable.Api#tables\r
7281          * @param {string|integer} [selector] Selector to pick which tables the iterator\r
7282          *   should operate on. If not given, all tables in the current context are\r
7283          *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to\r
7284          *   select multiple tables or as an integer to select a single table.\r
7285          * @returns {DataTable.Api} Returns a new API instance if a selector is given.\r
7286          */\r
7287         _api_register( 'tables()', function ( selector ) {\r
7288                 // A new instance is created if there was a selector specified\r
7289                 return selector ?\r
7290                         new _Api( __table_selector( selector, this.context ) ) :\r
7291                         this;\r
7292         } );\r
7293         \r
7294         \r
7295         _api_register( 'table()', function ( selector ) {\r
7296                 var tables = this.tables( selector );\r
7297                 var ctx = tables.context;\r
7298         \r
7299                 // Truncate to the first matched table\r
7300                 return ctx.length ?\r
7301                         new _Api( ctx[0] ) :\r
7302                         tables;\r
7303         } );\r
7304         \r
7305         \r
7306         _api_registerPlural( 'tables().nodes()', 'table().node()' , function () {\r
7307                 return this.iterator( 'table', function ( ctx ) {\r
7308                         return ctx.nTable;\r
7309                 }, 1 );\r
7310         } );\r
7311         \r
7312         \r
7313         _api_registerPlural( 'tables().body()', 'table().body()' , function () {\r
7314                 return this.iterator( 'table', function ( ctx ) {\r
7315                         return ctx.nTBody;\r
7316                 }, 1 );\r
7317         } );\r
7318         \r
7319         \r
7320         _api_registerPlural( 'tables().header()', 'table().header()' , function () {\r
7321                 return this.iterator( 'table', function ( ctx ) {\r
7322                         return ctx.nTHead;\r
7323                 }, 1 );\r
7324         } );\r
7325         \r
7326         \r
7327         _api_registerPlural( 'tables().footer()', 'table().footer()' , function () {\r
7328                 return this.iterator( 'table', function ( ctx ) {\r
7329                         return ctx.nTFoot;\r
7330                 }, 1 );\r
7331         } );\r
7332         \r
7333         \r
7334         _api_registerPlural( 'tables().containers()', 'table().container()' , function () {\r
7335                 return this.iterator( 'table', function ( ctx ) {\r
7336                         return ctx.nTableWrapper;\r
7337                 }, 1 );\r
7338         } );\r
7339         \r
7340         \r
7341         \r
7342         /**\r
7343          * Redraw the tables in the current context.\r
7344          */\r
7345         _api_register( 'draw()', function ( paging ) {\r
7346                 return this.iterator( 'table', function ( settings ) {\r
7347                         if ( paging === 'page' ) {\r
7348                                 _fnDraw( settings );\r
7349                         }\r
7350                         else {\r
7351                                 if ( typeof paging === 'string' ) {\r
7352                                         paging = paging === 'full-hold' ?\r
7353                                                 false :\r
7354                                                 true;\r
7355                                 }\r
7356         \r
7357                                 _fnReDraw( settings, paging===false );\r
7358                         }\r
7359                 } );\r
7360         } );\r
7361         \r
7362         \r
7363         \r
7364         /**\r
7365          * Get the current page index.\r
7366          *\r
7367          * @return {integer} Current page index (zero based)\r
7368          *//**\r
7369          * Set the current page.\r
7370          *\r
7371          * Note that if you attempt to show a page which does not exist, DataTables will\r
7372          * not throw an error, but rather reset the paging.\r
7373          *\r
7374          * @param {integer|string} action The paging action to take. This can be one of:\r
7375          *  * `integer` - The page index to jump to\r
7376          *  * `string` - An action to take:\r
7377          *    * `first` - Jump to first page.\r
7378          *    * `next` - Jump to the next page\r
7379          *    * `previous` - Jump to previous page\r
7380          *    * `last` - Jump to the last page.\r
7381          * @returns {DataTables.Api} this\r
7382          */\r
7383         _api_register( 'page()', function ( action ) {\r
7384                 if ( action === undefined ) {\r
7385                         return this.page.info().page; // not an expensive call\r
7386                 }\r
7387         \r
7388                 // else, have an action to take on all tables\r
7389                 return this.iterator( 'table', function ( settings ) {\r
7390                         _fnPageChange( settings, action );\r
7391                 } );\r
7392         } );\r
7393         \r
7394         \r
7395         /**\r
7396          * Paging information for the first table in the current context.\r
7397          *\r
7398          * If you require paging information for another table, use the `table()` method\r
7399          * with a suitable selector.\r
7400          *\r
7401          * @return {object} Object with the following properties set:\r
7402          *  * `page` - Current page index (zero based - i.e. the first page is `0`)\r
7403          *  * `pages` - Total number of pages\r
7404          *  * `start` - Display index for the first record shown on the current page\r
7405          *  * `end` - Display index for the last record shown on the current page\r
7406          *  * `length` - Display length (number of records). Note that generally `start\r
7407          *    + length = end`, but this is not always true, for example if there are\r
7408          *    only 2 records to show on the final page, with a length of 10.\r
7409          *  * `recordsTotal` - Full data set length\r
7410          *  * `recordsDisplay` - Data set length once the current filtering criterion\r
7411          *    are applied.\r
7412          */\r
7413         _api_register( 'page.info()', function ( action ) {\r
7414                 if ( this.context.length === 0 ) {\r
7415                         return undefined;\r
7416                 }\r
7417         \r
7418                 var\r
7419                         settings   = this.context[0],\r
7420                         start      = settings._iDisplayStart,\r
7421                         len        = settings.oFeatures.bPaginate ? settings._iDisplayLength : -1,\r
7422                         visRecords = settings.fnRecordsDisplay(),\r
7423                         all        = len === -1;\r
7424         \r
7425                 return {\r
7426                         "page":           all ? 0 : Math.floor( start / len ),\r
7427                         "pages":          all ? 1 : Math.ceil( visRecords / len ),\r
7428                         "start":          start,\r
7429                         "end":            settings.fnDisplayEnd(),\r
7430                         "length":         len,\r
7431                         "recordsTotal":   settings.fnRecordsTotal(),\r
7432                         "recordsDisplay": visRecords,\r
7433                         "serverSide":     _fnDataSource( settings ) === 'ssp'\r
7434                 };\r
7435         } );\r
7436         \r
7437         \r
7438         /**\r
7439          * Get the current page length.\r
7440          *\r
7441          * @return {integer} Current page length. Note `-1` indicates that all records\r
7442          *   are to be shown.\r
7443          *//**\r
7444          * Set the current page length.\r
7445          *\r
7446          * @param {integer} Page length to set. Use `-1` to show all records.\r
7447          * @returns {DataTables.Api} this\r
7448          */\r
7449         _api_register( 'page.len()', function ( len ) {\r
7450                 // Note that we can't call this function 'length()' because `length`\r
7451                 // is a Javascript property of functions which defines how many arguments\r
7452                 // the function expects.\r
7453                 if ( len === undefined ) {\r
7454                         return this.context.length !== 0 ?\r
7455                                 this.context[0]._iDisplayLength :\r
7456                                 undefined;\r
7457                 }\r
7458         \r
7459                 // else, set the page length\r
7460                 return this.iterator( 'table', function ( settings ) {\r
7461                         _fnLengthChange( settings, len );\r
7462                 } );\r
7463         } );\r
7464         \r
7465         \r
7466         \r
7467         var __reload = function ( settings, holdPosition, callback ) {\r
7468                 // Use the draw event to trigger a callback\r
7469                 if ( callback ) {\r
7470                         var api = new _Api( settings );\r
7471         \r
7472                         api.one( 'draw', function () {\r
7473                                 callback( api.ajax.json() );\r
7474                         } );\r
7475                 }\r
7476         \r
7477                 if ( _fnDataSource( settings ) == 'ssp' ) {\r
7478                         _fnReDraw( settings, holdPosition );\r
7479                 }\r
7480                 else {\r
7481                         _fnProcessingDisplay( settings, true );\r
7482         \r
7483                         // Cancel an existing request\r
7484                         var xhr = settings.jqXHR;\r
7485                         if ( xhr && xhr.readyState !== 4 ) {\r
7486                                 xhr.abort();\r
7487                         }\r
7488         \r
7489                         // Trigger xhr\r
7490                         _fnBuildAjax( settings, [], function( json ) {\r
7491                                 _fnClearTable( settings );\r
7492         \r
7493                                 var data = _fnAjaxDataSrc( settings, json );\r
7494                                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {\r
7495                                         _fnAddData( settings, data[i] );\r
7496                                 }\r
7497         \r
7498                                 _fnReDraw( settings, holdPosition );\r
7499                                 _fnProcessingDisplay( settings, false );\r
7500                         } );\r
7501                 }\r
7502         };\r
7503         \r
7504         \r
7505         /**\r
7506          * Get the JSON response from the last Ajax request that DataTables made to the\r
7507          * server. Note that this returns the JSON from the first table in the current\r
7508          * context.\r
7509          *\r
7510          * @return {object} JSON received from the server.\r
7511          */\r
7512         _api_register( 'ajax.json()', function () {\r
7513                 var ctx = this.context;\r
7514         \r
7515                 if ( ctx.length > 0 ) {\r
7516                         return ctx[0].json;\r
7517                 }\r
7518         \r
7519                 // else return undefined;\r
7520         } );\r
7521         \r
7522         \r
7523         /**\r
7524          * Get the data submitted in the last Ajax request\r
7525          */\r
7526         _api_register( 'ajax.params()', function () {\r
7527                 var ctx = this.context;\r
7528         \r
7529                 if ( ctx.length > 0 ) {\r
7530                         return ctx[0].oAjaxData;\r
7531                 }\r
7532         \r
7533                 // else return undefined;\r
7534         } );\r
7535         \r
7536         \r
7537         /**\r
7538          * Reload tables from the Ajax data source. Note that this function will\r
7539          * automatically re-draw the table when the remote data has been loaded.\r
7540          *\r
7541          * @param {boolean} [reset=true] Reset (default) or hold the current paging\r
7542          *   position. A full re-sort and re-filter is performed when this method is\r
7543          *   called, which is why the pagination reset is the default action.\r
7544          * @returns {DataTables.Api} this\r
7545          */\r
7546         _api_register( 'ajax.reload()', function ( callback, resetPaging ) {\r
7547                 return this.iterator( 'table', function (settings) {\r
7548                         __reload( settings, resetPaging===false, callback );\r
7549                 } );\r
7550         } );\r
7551         \r
7552         \r
7553         /**\r
7554          * Get the current Ajax URL. Note that this returns the URL from the first\r
7555          * table in the current context.\r
7556          *\r
7557          * @return {string} Current Ajax source URL\r
7558          *//**\r
7559          * Set the Ajax URL. Note that this will set the URL for all tables in the\r
7560          * current context.\r
7561          *\r
7562          * @param {string} url URL to set.\r
7563          * @returns {DataTables.Api} this\r
7564          */\r
7565         _api_register( 'ajax.url()', function ( url ) {\r
7566                 var ctx = this.context;\r
7567         \r
7568                 if ( url === undefined ) {\r
7569                         // get\r
7570                         if ( ctx.length === 0 ) {\r
7571                                 return undefined;\r
7572                         }\r
7573                         ctx = ctx[0];\r
7574         \r
7575                         return ctx.ajax ?\r
7576                                 $.isPlainObject( ctx.ajax ) ?\r
7577                                         ctx.ajax.url :\r
7578                                         ctx.ajax :\r
7579                                 ctx.sAjaxSource;\r
7580                 }\r
7581         \r
7582                 // set\r
7583                 return this.iterator( 'table', function ( settings ) {\r
7584                         if ( $.isPlainObject( settings.ajax ) ) {\r
7585                                 settings.ajax.url = url;\r
7586                         }\r
7587                         else {\r
7588                                 settings.ajax = url;\r
7589                         }\r
7590                         // No need to consider sAjaxSource here since DataTables gives priority\r
7591                         // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any\r
7592                         // value of `sAjaxSource` redundant.\r
7593                 } );\r
7594         } );\r
7595         \r
7596         \r
7597         /**\r
7598          * Load data from the newly set Ajax URL. Note that this method is only\r
7599          * available when `ajax.url()` is used to set a URL. Additionally, this method\r
7600          * has the same effect as calling `ajax.reload()` but is provided for\r
7601          * convenience when setting a new URL. Like `ajax.reload()` it will\r
7602          * automatically redraw the table once the remote data has been loaded.\r
7603          *\r
7604          * @returns {DataTables.Api} this\r
7605          */\r
7606         _api_register( 'ajax.url().load()', function ( callback, resetPaging ) {\r
7607                 // Same as a reload, but makes sense to present it for easy access after a\r
7608                 // url change\r
7609                 return this.iterator( 'table', function ( ctx ) {\r
7610                         __reload( ctx, resetPaging===false, callback );\r
7611                 } );\r
7612         } );\r
7613         \r
7614         \r
7615         \r
7616         \r
7617         var _selector_run = function ( type, selector, selectFn, settings, opts )\r
7618         {\r
7619                 var\r
7620                         out = [], res,\r
7621                         a, i, ien, j, jen,\r
7622                         selectorType = typeof selector;\r
7623         \r
7624                 // Can't just check for isArray here, as an API or jQuery instance might be\r
7625                 // given with their array like look\r
7626                 if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) {\r
7627                         selector = [ selector ];\r
7628                 }\r
7629         \r
7630                 for ( i=0, ien=selector.length ; i<ien ; i++ ) {\r
7631                         a = selector[i] && selector[i].split ?\r
7632                                 selector[i].split(',') :\r
7633                                 [ selector[i] ];\r
7634         \r
7635                         for ( j=0, jen=a.length ; j<jen ; j++ ) {\r
7636                                 res = selectFn( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );\r
7637         \r
7638                                 if ( res && res.length ) {\r
7639                                         out = out.concat( res );\r
7640                                 }\r
7641                         }\r
7642                 }\r
7643         \r
7644                 // selector extensions\r
7645                 var ext = _ext.selector[ type ];\r
7646                 if ( ext.length ) {\r
7647                         for ( i=0, ien=ext.length ; i<ien ; i++ ) {\r
7648                                 out = ext[i]( settings, opts, out );\r
7649                         }\r
7650                 }\r
7651         \r
7652                 return _unique( out );\r
7653         };\r
7654         \r
7655         \r
7656         var _selector_opts = function ( opts )\r
7657         {\r
7658                 if ( ! opts ) {\r
7659                         opts = {};\r
7660                 }\r
7661         \r
7662                 // Backwards compatibility for 1.9- which used the terminology filter rather\r
7663                 // than search\r
7664                 if ( opts.filter && opts.search === undefined ) {\r
7665                         opts.search = opts.filter;\r
7666                 }\r
7667         \r
7668                 return $.extend( {\r
7669                         search: 'none',\r
7670                         order: 'current',\r
7671                         page: 'all'\r
7672                 }, opts );\r
7673         };\r
7674         \r
7675         \r
7676         var _selector_first = function ( inst )\r
7677         {\r
7678                 // Reduce the API instance to the first item found\r
7679                 for ( var i=0, ien=inst.length ; i<ien ; i++ ) {\r
7680                         if ( inst[i].length > 0 ) {\r
7681                                 // Assign the first element to the first item in the instance\r
7682                                 // and truncate the instance and context\r
7683                                 inst[0] = inst[i];\r
7684                                 inst[0].length = 1;\r
7685                                 inst.length = 1;\r
7686                                 inst.context = [ inst.context[i] ];\r
7687         \r
7688                                 return inst;\r
7689                         }\r
7690                 }\r
7691         \r
7692                 // Not found - return an empty instance\r
7693                 inst.length = 0;\r
7694                 return inst;\r
7695         };\r
7696         \r
7697         \r
7698         var _selector_row_indexes = function ( settings, opts )\r
7699         {\r
7700                 var\r
7701                         i, ien, tmp, a=[],\r
7702                         displayFiltered = settings.aiDisplay,\r
7703                         displayMaster = settings.aiDisplayMaster;\r
7704         \r
7705                 var\r
7706                         search = opts.search,  // none, applied, removed\r
7707                         order  = opts.order,   // applied, current, index (original - compatibility with 1.9)\r
7708                         page   = opts.page;    // all, current\r
7709         \r
7710                 if ( _fnDataSource( settings ) == 'ssp' ) {\r
7711                         // In server-side processing mode, most options are irrelevant since\r
7712                         // rows not shown don't exist and the index order is the applied order\r
7713                         // Removed is a special case - for consistency just return an empty\r
7714                         // array\r
7715                         return search === 'removed' ?\r
7716                                 [] :\r
7717                                 _range( 0, displayMaster.length );\r
7718                 }\r
7719                 else if ( page == 'current' ) {\r
7720                         // Current page implies that order=current and fitler=applied, since it is\r
7721                         // fairly senseless otherwise, regardless of what order and search actually\r
7722                         // are\r
7723                         for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {\r
7724                                 a.push( displayFiltered[i] );\r
7725                         }\r
7726                 }\r
7727                 else if ( order == 'current' || order == 'applied' ) {\r
7728                         a = search == 'none' ?\r
7729                                 displayMaster.slice() :                      // no search\r
7730                                 search == 'applied' ?\r
7731                                         displayFiltered.slice() :                // applied search\r
7732                                         $.map( displayMaster, function (el, i) { // removed search\r
7733                                                 return $.inArray( el, displayFiltered ) === -1 ? el : null;\r
7734                                         } );\r
7735                 }\r
7736                 else if ( order == 'index' || order == 'original' ) {\r
7737                         for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {\r
7738                                 if ( search == 'none' ) {\r
7739                                         a.push( i );\r
7740                                 }\r
7741                                 else { // applied | removed\r
7742                                         tmp = $.inArray( i, displayFiltered );\r
7743         \r
7744                                         if ((tmp === -1 && search == 'removed') ||\r
7745                                                 (tmp >= 0   && search == 'applied') )\r
7746                                         {\r
7747                                                 a.push( i );\r
7748                                         }\r
7749                                 }\r
7750                         }\r
7751                 }\r
7752         \r
7753                 return a;\r
7754         };\r
7755         \r
7756         \r
7757         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\r
7758          * Rows\r
7759          *\r
7760          * {}          - no selector - use all available rows\r
7761          * {integer}   - row aoData index\r
7762          * {node}      - TR node\r
7763          * {string}    - jQuery selector to apply to the TR elements\r
7764          * {array}     - jQuery array of nodes, or simply an array of TR nodes\r
7765          *\r
7766          */\r
7767         \r
7768         \r
7769         var __row_selector = function ( settings, selector, opts )\r
7770         {\r
7771                 var run = function ( sel ) {\r
7772                         var selInt = _intVal( sel );\r
7773                         var i, ien;\r
7774         \r
7775                         // Short cut - selector is a number and no options provided (default is\r
7776                         // all records, so no need to check if the index is in there, since it\r
7777                         // must be - dev error if the index doesn't exist).\r
7778                         if ( selInt !== null && ! opts ) {\r
7779                                 return [ selInt ];\r
7780                         }\r
7781         \r
7782                         var rows = _selector_row_indexes( settings, opts );\r
7783         \r
7784                         if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {\r
7785                                 // Selector - integer\r
7786                                 return [ selInt ];\r
7787                         }\r
7788                         else if ( ! sel ) {\r
7789                                 // Selector - none\r
7790                                 return rows;\r
7791                         }\r
7792         \r
7793                         // Selector - function\r
7794                         if ( typeof sel === 'function' ) {\r
7795                                 return $.map( rows, function (idx) {\r
7796                                         var row = settings.aoData[ idx ];\r
7797                                         return sel( idx, row._aData, row.nTr ) ? idx : null;\r
7798                                 } );\r
7799                         }\r
7800         \r
7801                         // Get nodes in the order from the `rows` array with null values removed\r
7802                         var nodes = _removeEmpty(\r
7803                                 _pluck_order( settings.aoData, rows, 'nTr' )\r
7804                         );\r
7805         \r
7806                         // Selector - node\r
7807                         if ( sel.nodeName ) {\r
7808                                 if ( sel._DT_RowIndex !== undefined ) {\r
7809                                         return [ sel._DT_RowIndex ]; // Property added by DT for fast lookup\r
7810                                 }\r
7811                                 else if ( sel._DT_CellIndex ) {\r
7812                                         return [ sel._DT_CellIndex.row ];\r
7813                                 }\r
7814                                 else {\r
7815                                         var host = $(sel).closest('*[data-dt-row]');\r
7816                                         return host.length ?\r
7817                                                 [ host.data('dt-row') ] :\r
7818                                                 [];\r
7819                                 }\r
7820                         }\r
7821         \r
7822                         // ID selector. Want to always be able to select rows by id, regardless\r
7823                         // of if the tr element has been created or not, so can't rely upon\r
7824                         // jQuery here - hence a custom implementation. This does not match\r
7825                         // Sizzle's fast selector or HTML4 - in HTML5 the ID can be anything,\r
7826                         // but to select it using a CSS selector engine (like Sizzle or\r
7827                         // querySelect) it would need to need to be escaped for some characters.\r
7828                         // DataTables simplifies this for row selectors since you can select\r
7829                         // only a row. A # indicates an id any anything that follows is the id -\r
7830                         // unescaped.\r
7831                         if ( typeof sel === 'string' && sel.charAt(0) === '#' ) {\r
7832                                 // get row index from id\r
7833                                 var rowObj = settings.aIds[ sel.replace( /^#/, '' ) ];\r
7834                                 if ( rowObj !== undefined ) {\r
7835                                         return [ rowObj.idx ];\r
7836                                 }\r
7837         \r
7838                                 // need to fall through to jQuery in case there is DOM id that\r
7839                                 // matches\r
7840                         }\r
7841         \r
7842                         // Selector - jQuery selector string, array of nodes or jQuery object/\r
7843                         // As jQuery's .filter() allows jQuery objects to be passed in filter,\r
7844                         // it also allows arrays, so this will cope with all three options\r
7845                         return $(nodes)\r
7846                                 .filter( sel )\r
7847                                 .map( function () {\r
7848                                         return this._DT_RowIndex;\r
7849                                 } )\r
7850                                 .toArray();\r
7851                 };\r
7852         \r
7853                 return _selector_run( 'row', selector, run, settings, opts );\r
7854         };\r
7855         \r
7856         \r
7857         _api_register( 'rows()', function ( selector, opts ) {\r
7858                 // argument shifting\r
7859                 if ( selector === undefined ) {\r
7860                         selector = '';\r
7861                 }\r
7862                 else if ( $.isPlainObject( selector ) ) {\r
7863                         opts = selector;\r
7864                         selector = '';\r
7865                 }\r
7866         \r
7867                 opts = _selector_opts( opts );\r
7868         \r
7869                 var inst = this.iterator( 'table', function ( settings ) {\r
7870                         return __row_selector( settings, selector, opts );\r
7871                 }, 1 );\r
7872         \r
7873                 // Want argument shifting here and in __row_selector?\r
7874                 inst.selector.rows = selector;\r
7875                 inst.selector.opts = opts;\r
7876         \r
7877                 return inst;\r
7878         } );\r
7879         \r
7880         _api_register( 'rows().nodes()', function () {\r
7881                 return this.iterator( 'row', function ( settings, row ) {\r
7882                         return settings.aoData[ row ].nTr || undefined;\r
7883                 }, 1 );\r
7884         } );\r
7885         \r
7886         _api_register( 'rows().data()', function () {\r
7887                 return this.iterator( true, 'rows', function ( settings, rows ) {\r
7888                         return _pluck_order( settings.aoData, rows, '_aData' );\r
7889                 }, 1 );\r
7890         } );\r
7891         \r
7892         _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {\r
7893                 return this.iterator( 'row', function ( settings, row ) {\r
7894                         var r = settings.aoData[ row ];\r
7895                         return type === 'search' ? r._aFilterData : r._aSortData;\r
7896                 }, 1 );\r
7897         } );\r
7898         \r
7899         _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {\r
7900                 return this.iterator( 'row', function ( settings, row ) {\r
7901                         _fnInvalidate( settings, row, src );\r
7902                 } );\r
7903         } );\r
7904         \r
7905         _api_registerPlural( 'rows().indexes()', 'row().index()', function () {\r
7906                 return this.iterator( 'row', function ( settings, row ) {\r
7907                         return row;\r
7908                 }, 1 );\r
7909         } );\r
7910         \r
7911         _api_registerPlural( 'rows().ids()', 'row().id()', function ( hash ) {\r
7912                 var a = [];\r
7913                 var context = this.context;\r
7914         \r
7915                 // `iterator` will drop undefined values, but in this case we want them\r
7916                 for ( var i=0, ien=context.length ; i<ien ; i++ ) {\r
7917                         for ( var j=0, jen=this[i].length ; j<jen ; j++ ) {\r
7918                                 var id = context[i].rowIdFn( context[i].aoData[ this[i][j] ]._aData );\r
7919                                 a.push( (hash === true ? '#' : '' )+ id );\r
7920                         }\r
7921                 }\r
7922         \r
7923                 return new _Api( context, a );\r
7924         } );\r
7925         \r
7926         _api_registerPlural( 'rows().remove()', 'row().remove()', function () {\r
7927                 var that = this;\r
7928         \r
7929                 this.iterator( 'row', function ( settings, row, thatIdx ) {\r
7930                         var data = settings.aoData;\r
7931                         var rowData = data[ row ];\r
7932                         var i, ien, j, jen;\r
7933                         var loopRow, loopCells;\r
7934         \r
7935                         data.splice( row, 1 );\r
7936         \r
7937                         // Update the cached indexes\r
7938                         for ( i=0, ien=data.length ; i<ien ; i++ ) {\r
7939                                 loopRow = data[i];\r
7940                                 loopCells = loopRow.anCells;\r
7941         \r
7942                                 // Rows\r
7943                                 if ( loopRow.nTr !== null ) {\r
7944                                         loopRow.nTr._DT_RowIndex = i;\r
7945                                 }\r
7946         \r
7947                                 // Cells\r
7948                                 if ( loopCells !== null ) {\r
7949                                         for ( j=0, jen=loopCells.length ; j<jen ; j++ ) {\r
7950                                                 loopCells[j]._DT_CellIndex.row = i;\r
7951                                         }\r
7952                                 }\r
7953                         }\r
7954         \r
7955                         // Delete from the display arrays\r
7956                         _fnDeleteIndex( settings.aiDisplayMaster, row );\r
7957                         _fnDeleteIndex( settings.aiDisplay, row );\r
7958                         _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes\r
7959         \r
7960                         // Check for an 'overflow' they case for displaying the table\r
7961                         _fnLengthOverflow( settings );\r
7962         \r
7963                         // Remove the row's ID reference if there is one\r
7964                         var id = settings.rowIdFn( rowData._aData );\r
7965                         if ( id !== undefined ) {\r
7966                                 delete settings.aIds[ id ];\r
7967                         }\r
7968                 } );\r
7969         \r
7970                 this.iterator( 'table', function ( settings ) {\r
7971                         for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {\r
7972                                 settings.aoData[i].idx = i;\r
7973                         }\r
7974                 } );\r
7975         \r
7976                 return this;\r
7977         } );\r
7978         \r
7979         \r
7980         _api_register( 'rows.add()', function ( rows ) {\r
7981                 var newRows = this.iterator( 'table', function ( settings ) {\r
7982                                 var row, i, ien;\r
7983                                 var out = [];\r
7984         \r
7985                                 for ( i=0, ien=rows.length ; i<ien ; i++ ) {\r
7986                                         row = rows[i];\r
7987         \r
7988                                         if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {\r
7989                                                 out.push( _fnAddTr( settings, row )[0] );\r
7990                                         }\r
7991                                         else {\r
7992                                                 out.push( _fnAddData( settings, row ) );\r
7993                                         }\r
7994                                 }\r
7995         \r
7996                                 return out;\r
7997                         }, 1 );\r
7998         \r
7999                 // Return an Api.rows() extended instance, so rows().nodes() etc can be used\r
8000                 var modRows = this.rows( -1 );\r
8001                 modRows.pop();\r
8002                 $.merge( modRows, newRows );\r
8003         \r
8004                 return modRows;\r
8005         } );\r
8006         \r
8007         \r
8008         \r
8009         \r
8010         \r
8011         /**\r
8012          *\r
8013          */\r
8014         _api_register( 'row()', function ( selector, opts ) {\r
8015                 return _selector_first( this.rows( selector, opts ) );\r
8016         } );\r
8017         \r
8018         \r
8019         _api_register( 'row().data()', function ( data ) {\r
8020                 var ctx = this.context;\r
8021         \r
8022                 if ( data === undefined ) {\r
8023                         // Get\r
8024                         return ctx.length && this.length ?\r
8025                                 ctx[0].aoData[ this[0] ]._aData :\r
8026                                 undefined;\r
8027                 }\r
8028         \r
8029                 // Set\r
8030                 ctx[0].aoData[ this[0] ]._aData = data;\r
8031         \r
8032                 // Automatically invalidate\r
8033                 _fnInvalidate( ctx[0], this[0], 'data' );\r
8034         \r
8035                 return this;\r
8036         } );\r
8037         \r
8038         \r
8039         _api_register( 'row().node()', function () {\r
8040                 var ctx = this.context;\r
8041         \r
8042                 return ctx.length && this.length ?\r
8043                         ctx[0].aoData[ this[0] ].nTr || null :\r
8044                         null;\r
8045         } );\r
8046         \r
8047         \r
8048         _api_register( 'row.add()', function ( row ) {\r
8049                 // Allow a jQuery object to be passed in - only a single row is added from\r
8050                 // it though - the first element in the set\r
8051                 if ( row instanceof $ && row.length ) {\r
8052                         row = row[0];\r
8053                 }\r
8054         \r
8055                 var rows = this.iterator( 'table', function ( settings ) {\r
8056                         if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {\r
8057                                 return _fnAddTr( settings, row )[0];\r
8058                         }\r
8059                         return _fnAddData( settings, row );\r
8060                 } );\r
8061         \r
8062                 // Return an Api.rows() extended instance, with the newly added row selected\r
8063                 return this.row( rows[0] );\r
8064         } );\r
8065         \r
8066         \r
8067         \r
8068         var __details_add = function ( ctx, row, data, klass )\r
8069         {\r
8070                 // Convert to array of TR elements\r
8071                 var rows = [];\r
8072                 var addRow = function ( r, k ) {\r
8073                         // Recursion to allow for arrays of jQuery objects\r
8074                         if ( $.isArray( r ) || r instanceof $ ) {\r
8075                                 for ( var i=0, ien=r.length ; i<ien ; i++ ) {\r
8076                                         addRow( r[i], k );\r
8077                                 }\r
8078                                 return;\r
8079                         }\r
8080         \r
8081                         // If we get a TR element, then just add it directly - up to the dev\r
8082                         // to add the correct number of columns etc\r
8083                         if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {\r
8084                                 rows.push( r );\r
8085                         }\r
8086                         else {\r
8087                                 // Otherwise create a row with a wrapper\r
8088                                 var created = $('<tr><td/></tr>').addClass( k );\r
8089                                 $('td', created)\r
8090                                         .addClass( k )\r
8091                                         .html( r )\r
8092                                         [0].colSpan = _fnVisbleColumns( ctx );\r
8093         \r
8094                                 rows.push( created[0] );\r
8095                         }\r
8096                 };\r
8097         \r
8098                 addRow( data, klass );\r
8099         \r
8100                 if ( row._details ) {\r
8101                         row._details.remove();\r
8102                 }\r
8103         \r
8104                 row._details = $(rows);\r
8105         \r
8106                 // If the children were already shown, that state should be retained\r
8107                 if ( row._detailsShow ) {\r
8108                         row._details.insertAfter( row.nTr );\r
8109                 }\r
8110         };\r
8111         \r
8112         \r
8113         var __details_remove = function ( api, idx )\r
8114         {\r
8115                 var ctx = api.context;\r
8116         \r
8117                 if ( ctx.length ) {\r
8118                         var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ];\r
8119         \r
8120                         if ( row && row._details ) {\r
8121                                 row._details.remove();\r
8122         \r
8123                                 row._detailsShow = undefined;\r
8124                                 row._details = undefined;\r
8125                         }\r
8126                 }\r
8127         };\r
8128         \r
8129         \r
8130         var __details_display = function ( api, show ) {\r
8131                 var ctx = api.context;\r
8132         \r
8133                 if ( ctx.length && api.length ) {\r
8134                         var row = ctx[0].aoData[ api[0] ];\r
8135         \r
8136                         if ( row._details ) {\r
8137                                 row._detailsShow = show;\r
8138         \r
8139                                 if ( show ) {\r
8140                                         row._details.insertAfter( row.nTr );\r
8141                                 }\r
8142                                 else {\r
8143                                         row._details.detach();\r
8144                                 }\r
8145         \r
8146                                 __details_events( ctx[0] );\r
8147                         }\r
8148                 }\r
8149         };\r
8150         \r
8151         \r
8152         var __details_events = function ( settings )\r
8153         {\r
8154                 var api = new _Api( settings );\r
8155                 var namespace = '.dt.DT_details';\r
8156                 var drawEvent = 'draw'+namespace;\r
8157                 var colvisEvent = 'column-visibility'+namespace;\r
8158                 var destroyEvent = 'destroy'+namespace;\r
8159                 var data = settings.aoData;\r
8160         \r
8161                 api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );\r
8162         \r
8163                 if ( _pluck( data, '_details' ).length > 0 ) {\r
8164                         // On each draw, insert the required elements into the document\r
8165                         api.on( drawEvent, function ( e, ctx ) {\r
8166                                 if ( settings !== ctx ) {\r
8167                                         return;\r
8168                                 }\r
8169         \r
8170                                 api.rows( {page:'current'} ).eq(0).each( function (idx) {\r
8171                                         // Internal data grab\r
8172                                         var row = data[ idx ];\r
8173         \r
8174                                         if ( row._detailsShow ) {\r
8175                                                 row._details.insertAfter( row.nTr );\r
8176                                         }\r
8177                                 } );\r
8178                         } );\r
8179         \r
8180                         // Column visibility change - update the colspan\r
8181                         api.on( colvisEvent, function ( e, ctx, idx, vis ) {\r
8182                                 if ( settings !== ctx ) {\r
8183                                         return;\r
8184                                 }\r
8185         \r
8186                                 // Update the colspan for the details rows (note, only if it already has\r
8187                                 // a colspan)\r
8188                                 var row, visible = _fnVisbleColumns( ctx );\r
8189         \r
8190                                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {\r
8191                                         row = data[i];\r
8192         \r
8193                                         if ( row._details ) {\r
8194                                                 row._details.children('td[colspan]').attr('colspan', visible );\r
8195                                         }\r
8196                                 }\r
8197                         } );\r
8198         \r
8199                         // Table destroyed - nuke any child rows\r
8200                         api.on( destroyEvent, function ( e, ctx ) {\r
8201                                 if ( settings !== ctx ) {\r
8202                                         return;\r
8203                                 }\r
8204         \r
8205                                 for ( var i=0, ien=data.length ; i<ien ; i++ ) {\r
8206                                         if ( data[i]._details ) {\r
8207                                                 __details_remove( api, i );\r
8208                                         }\r
8209                                 }\r
8210                         } );\r
8211                 }\r
8212         };\r
8213         \r
8214         // Strings for the method names to help minification\r
8215         var _emp = '';\r
8216         var _child_obj = _emp+'row().child';\r
8217         var _child_mth = _child_obj+'()';\r
8218         \r
8219         // data can be:\r
8220         //  tr\r
8221         //  string\r
8222         //  jQuery or array of any of the above\r
8223         _api_register( _child_mth, function ( data, klass ) {\r
8224                 var ctx = this.context;\r
8225         \r
8226                 if ( data === undefined ) {\r
8227                         // get\r
8228                         return ctx.length && this.length ?\r
8229                                 ctx[0].aoData[ this[0] ]._details :\r
8230                                 undefined;\r
8231                 }\r
8232                 else if ( data === true ) {\r
8233                         // show\r
8234                         this.child.show();\r
8235                 }\r
8236                 else if ( data === false ) {\r
8237                         // remove\r
8238                         __details_remove( this );\r
8239                 }\r
8240                 else if ( ctx.length && this.length ) {\r
8241                         // set\r
8242                         __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );\r
8243                 }\r
8244         \r
8245                 return this;\r
8246         } );\r
8247         \r
8248         \r
8249         _api_register( [\r
8250                 _child_obj+'.show()',\r
8251                 _child_mth+'.show()' // only when `child()` was called with parameters (without\r
8252         ], function ( show ) {   // it returns an object and this method is not executed)\r
8253                 __details_display( this, true );\r
8254                 return this;\r
8255         } );\r
8256         \r
8257         \r
8258         _api_register( [\r
8259                 _child_obj+'.hide()',\r
8260                 _child_mth+'.hide()' // only when `child()` was called with parameters (without\r
8261         ], function () {         // it returns an object and this method is not executed)\r
8262                 __details_display( this, false );\r
8263                 return this;\r
8264         } );\r
8265         \r
8266         \r
8267         _api_register( [\r
8268                 _child_obj+'.remove()',\r
8269                 _child_mth+'.remove()' // only when `child()` was called with parameters (without\r
8270         ], function () {           // it returns an object and this method is not executed)\r
8271                 __details_remove( this );\r
8272                 return this;\r
8273         } );\r
8274         \r
8275         \r
8276         _api_register( _child_obj+'.isShown()', function () {\r
8277                 var ctx = this.context;\r
8278         \r
8279                 if ( ctx.length && this.length ) {\r
8280                         // _detailsShown as false or undefined will fall through to return false\r
8281                         return ctx[0].aoData[ this[0] ]._detailsShow || false;\r
8282                 }\r
8283                 return false;\r
8284         } );\r
8285         \r
8286         \r
8287         \r
8288         /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\r
8289          * Columns\r
8290          *\r
8291          * {integer}           - column index (>=0 count from left, <0 count from right)\r
8292          * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)\r
8293          * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)\r
8294          * "{string}:name"     - column name\r
8295          * "{string}"          - jQuery selector on column header nodes\r
8296          *\r
8297          */\r
8298         \r
8299         // can be an array of these items, comma separated list, or an array of comma\r
8300         // separated lists\r
8301         \r
8302         var __re_column_selector = /^(.+):(name|visIdx|visible)$/;\r
8303         \r
8304         \r
8305         // r1 and r2 are redundant - but it means that the parameters match for the\r
8306         // iterator callback in columns().data()\r
8307         var __columnData = function ( settings, column, r1, r2, rows ) {\r
8308                 var a = [];\r
8309                 for ( var row=0, ien=rows.length ; row<ien ; row++ ) {\r
8310                         a.push( _fnGetCellData( settings, rows[row], column ) );\r
8311                 }\r
8312                 return a;\r
8313         };\r
8314         \r
8315         \r
8316         var __column_selector = function ( settings, selector, opts )\r
8317         {\r
8318                 var\r
8319                         columns = settings.aoColumns,\r
8320                         names = _pluck( columns, 'sName' ),\r
8321                         nodes = _pluck( columns, 'nTh' );\r
8322         \r
8323                 var run = function ( s ) {\r
8324                         var selInt = _intVal( s );\r
8325         \r
8326                         // Selector - all\r
8327                         if ( s === '' ) {\r
8328                                 return _range( columns.length );\r
8329                         }\r
8330                         \r
8331                         // Selector - index\r
8332                         if ( selInt !== null ) {\r
8333                                 return [ selInt >= 0 ?\r
8334                                         selInt : // Count from left\r
8335                                         columns.length + selInt // Count from right (+ because its a negative value)\r
8336                                 ];\r
8337                         }\r
8338                         \r
8339                         // Selector = function\r
8340                         if ( typeof s === 'function' ) {\r
8341                                 var rows = _selector_row_indexes( settings, opts );\r
8342         \r
8343                                 return $.map( columns, function (col, idx) {\r
8344                                         return s(\r
8345                                                         idx,\r
8346                                                         __columnData( settings, idx, 0, 0, rows ),\r
8347                                                         nodes[ idx ]\r
8348                                                 ) ? idx : null;\r
8349                                 } );\r
8350                         }\r
8351         \r
8352                         // jQuery or string selector\r
8353                         var match = typeof s === 'string' ?\r
8354                                 s.match( __re_column_selector ) :\r
8355                                 '';\r
8356         \r
8357                         if ( match ) {\r
8358                                 switch( match[2] ) {\r
8359                                         case 'visIdx':\r
8360                                         case 'visible':\r
8361                                                 var idx = parseInt( match[1], 10 );\r
8362                                                 // Visible index given, convert to column index\r
8363                                                 if ( idx < 0 ) {\r
8364                                                         // Counting from the right\r
8365                                                         var visColumns = $.map( columns, function (col,i) {\r
8366                                                                 return col.bVisible ? i : null;\r
8367                                                         } );\r
8368                                                         return [ visColumns[ visColumns.length + idx ] ];\r
8369                                                 }\r
8370                                                 // Counting from the left\r
8371                                                 return [ _fnVisibleToColumnIndex( settings, idx ) ];\r
8372         \r
8373                                         case 'name':\r
8374                                                 // match by name. `names` is column index complete and in order\r
8375                                                 return $.map( names, function (name, i) {\r
8376                                                         return name === match[1] ? i : null;\r
8377                                                 } );\r
8378         \r
8379                                         default:\r
8380                                                 return [];\r
8381                                 }\r
8382                         }\r
8383         \r
8384                         // Cell in the table body\r
8385                         if ( s.nodeName && s._DT_CellIndex ) {\r
8386                                 return [ s._DT_CellIndex.column ];\r
8387                         }\r
8388         \r
8389                         // jQuery selector on the TH elements for the columns\r
8390                         var jqResult = $( nodes )\r
8391                                 .filter( s )\r
8392                                 .map( function () {\r
8393                                         return $.inArray( this, nodes ); // `nodes` is column index complete and in order\r
8394                                 } )\r
8395                                 .toArray();\r
8396         \r
8397                         if ( jqResult.length || ! s.nodeName ) {\r
8398                                 return jqResult;\r
8399                         }\r
8400         \r
8401                         // Otherwise a node which might have a `dt-column` data attribute, or be\r
8402                         // a child or such an element\r
8403                         var host = $(s).closest('*[data-dt-column]');\r
8404                         return host.length ?\r
8405                                 [ host.data('dt-column') ] :\r
8406                                 [];\r
8407                 };\r
8408         \r
8409                 return _selector_run( 'column', selector, run, settings, opts );\r
8410         };\r
8411         \r
8412         \r
8413         var __setColumnVis = function ( settings, column, vis, recalc ) {\r
8414                 var\r
8415                         cols = settings.aoColumns,\r
8416                         col  = cols[ column ],\r
8417                         data = settings.aoData,\r
8418                         row, cells, i, ien, tr;\r
8419         \r
8420                 // Get\r
8421                 if ( vis === undefined ) {\r
8422                         return col.bVisible;\r
8423                 }\r
8424         \r
8425                 // Set\r
8426                 // No change\r
8427                 if ( col.bVisible === vis ) {\r
8428                         return;\r
8429                 }\r
8430         \r
8431                 if ( vis ) {\r
8432                         // Insert column\r
8433                         // Need to decide if we should use appendChild or insertBefore\r
8434                         var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );\r
8435         \r
8436                         for ( i=0, ien=data.length ; i<ien ; i++ ) {\r
8437                                 tr = data[i].nTr;\r
8438                                 cells = data[i].anCells;\r
8439         \r
8440                                 if ( tr ) {\r
8441                                         // insertBefore can act like appendChild if 2nd arg is null\r
8442                                         tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );\r
8443                                 }\r
8444                         }\r
8445                 }\r
8446                 else {\r
8447                         // Remove column\r
8448                         $( _pluck( settings.aoData, 'anCells', column ) ).detach();\r
8449                 }\r
8450         \r
8451                 // Common actions\r
8452                 col.bVisible = vis;\r
8453                 _fnDrawHead( settings, settings.aoHeader );\r
8454                 _fnDrawHead( settings, settings.aoFooter );\r
8455         \r
8456                 if ( recalc === undefined || recalc ) {\r
8457                         // Automatically adjust column sizing\r
8458                         _fnAdjustColumnSizing( settings );\r
8459                 }\r
8460         \r
8461                 _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis, recalc] );\r
8462         \r
8463                 _fnSaveState( settings );\r
8464         };\r
8465         \r
8466         \r
8467         _api_register( 'columns()', function ( selector, opts ) {\r
8468                 // argument shifting\r
8469                 if ( selector === undefined ) {\r
8470                         selector = '';\r
8471                 }\r
8472                 else if ( $.isPlainObject( selector ) ) {\r
8473                         opts = selector;\r
8474                         selector = '';\r
8475                 }\r
8476         \r
8477                 opts = _selector_opts( opts );\r
8478         \r
8479                 var inst = this.iterator( 'table', function ( settings ) {\r
8480                         return __column_selector( settings, selector, opts );\r
8481                 }, 1 );\r
8482         \r
8483                 // Want argument shifting here and in _row_selector?\r
8484                 inst.selector.cols = selector;\r
8485                 inst.selector.opts = opts;\r
8486         \r
8487                 return inst;\r
8488         } );\r
8489         \r
8490         _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {\r
8491                 return this.iterator( 'column', function ( settings, column ) {\r
8492                         return settings.aoColumns[column].nTh;\r
8493                 }, 1 );\r
8494         } );\r
8495         \r
8496         _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {\r
8497                 return this.iterator( 'column', function ( settings, column ) {\r
8498                         return settings.aoColumns[column].nTf;\r
8499                 }, 1 );\r
8500         } );\r
8501         \r
8502         _api_registerPlural( 'columns().data()', 'column().data()', function () {\r
8503                 return this.iterator( 'column-rows', __columnData, 1 );\r
8504         } );\r
8505         \r
8506         _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () {\r
8507                 return this.iterator( 'column', function ( settings, column ) {\r
8508                         return settings.aoColumns[column].mData;\r
8509                 }, 1 );\r
8510         } );\r
8511         \r
8512         _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {\r
8513                 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {\r
8514                         return _pluck_order( settings.aoData, rows,\r
8515                                 type === 'search' ? '_aFilterData' : '_aSortData', column\r
8516                         );\r
8517                 }, 1 );\r
8518         } );\r
8519         \r
8520         _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {\r
8521                 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {\r
8522                         return _pluck_order( settings.aoData, rows, 'anCells', column ) ;\r
8523                 }, 1 );\r
8524         } );\r
8525         \r
8526         _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {\r
8527                 return this.iterator( 'column', function ( settings, column ) {\r
8528                         if ( vis === undefined ) {\r
8529                                 return settings.aoColumns[ column ].bVisible;\r
8530                         } // else\r
8531                         __setColumnVis( settings, column, vis, calc );\r
8532                 } );\r
8533         } );\r
8534         \r
8535         _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {\r
8536                 return this.iterator( 'column', function ( settings, column ) {\r
8537                         return type === 'visible' ?\r
8538                                 _fnColumnIndexToVisible( settings, column ) :\r
8539                                 column;\r
8540                 }, 1 );\r
8541         } );\r
8542         \r
8543         _api_register( 'columns.adjust()', function () {\r
8544                 return this.iterator( 'table', function ( settings ) {\r
8545                         _fnAdjustColumnSizing( settings );\r
8546                 }, 1 );\r
8547         } );\r
8548         \r
8549         _api_register( 'column.index()', function ( type, idx ) {\r
8550                 if ( this.context.length !== 0 ) {\r
8551                         var ctx = this.context[0];\r
8552         \r
8553                         if ( type === 'fromVisible' || type === 'toData' ) {\r
8554                                 return _fnVisibleToColumnIndex( ctx, idx );\r
8555                         }\r
8556                         else if ( type === 'fromData' || type === 'toVisible' ) {\r
8557                                 return _fnColumnIndexToVisible( ctx, idx );\r
8558                         }\r
8559                 }\r
8560         } );\r
8561         \r
8562         _api_register( 'column()', function ( selector, opts ) {\r
8563                 return _selector_first( this.columns( selector, opts ) );\r
8564         } );\r
8565         \r
8566         \r
8567         \r
8568         \r
8569         var __cell_selector = function ( settings, selector, opts )\r
8570         {\r
8571                 var data = settings.aoData;\r
8572                 var rows = _selector_row_indexes( settings, opts );\r
8573                 var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) );\r
8574                 var allCells = $( [].concat.apply([], cells) );\r
8575                 var row;\r
8576                 var columns = settings.aoColumns.length;\r
8577                 var a, i, ien, j, o, host;\r
8578         \r
8579                 var run = function ( s ) {\r
8580                         var fnSelector = typeof s === 'function';\r
8581         \r
8582                         if ( s === null || s === undefined || fnSelector ) {\r
8583                                 // All cells and function selectors\r
8584                                 a = [];\r
8585         \r
8586                                 for ( i=0, ien=rows.length ; i<ien ; i++ ) {\r
8587                                         row = rows[i];\r
8588         \r
8589                                         for ( j=0 ; j<columns ; j++ ) {\r
8590                                                 o = {\r
8591                                                         row: row,\r
8592                                                         column: j\r
8593                                                 };\r
8594         \r
8595                                                 if ( fnSelector ) {\r
8596                                                         // Selector - function\r
8597                                                         host = data[ row ];\r
8598         \r
8599                                                         if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) {\r
8600                                                                 a.push( o );\r
8601                                                         }\r
8602                                                 }\r
8603                                                 else {\r
8604                                                         // Selector - all\r
8605                                                         a.push( o );\r
8606                                                 }\r
8607                                         }\r
8608                                 }\r
8609         \r
8610                                 return a;\r
8611                         }\r
8612                         \r
8613                         // Selector - index\r
8614                         if ( $.isPlainObject( s ) ) {\r
8615                                 return [s];\r
8616                         }\r
8617         \r
8618                         // Selector - jQuery filtered cells\r
8619                         var jqResult = allCells\r
8620                                 .filter( s )\r
8621                                 .map( function (i, el) {\r
8622                                         return { // use a new object, in case someone changes the values\r
8623                                                 row:    el._DT_CellIndex.row,\r
8624                                                 column: el._DT_CellIndex.column\r
8625                                         };\r
8626                                 } )\r
8627                                 .toArray();\r
8628         \r
8629                         if ( jqResult.length || ! s.nodeName ) {\r
8630                                 return jqResult;\r
8631                         }\r
8632         \r
8633                         // Otherwise the selector is a node, and there is one last option - the\r
8634                         // element might be a child of an element which has dt-row and dt-column\r
8635                         // data attributes\r
8636                         host = $(s).closest('*[data-dt-row]');\r
8637                         return host.length ?\r
8638                                 [ {\r
8639                                         row: host.data('dt-row'),\r
8640                                         column: host.data('dt-column')\r
8641                                 } ] :\r
8642                                 [];\r
8643                 };\r
8644         \r
8645                 return _selector_run( 'cell', selector, run, settings, opts );\r
8646         };\r
8647         \r
8648         \r
8649         \r
8650         \r
8651         _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {\r
8652                 // Argument shifting\r
8653                 if ( $.isPlainObject( rowSelector ) ) {\r
8654                         // Indexes\r
8655                         if ( rowSelector.row === undefined ) {\r
8656                                 // Selector options in first parameter\r
8657                                 opts = rowSelector;\r
8658                                 rowSelector = null;\r
8659                         }\r
8660                         else {\r
8661                                 // Cell index objects in first parameter\r
8662                                 opts = columnSelector;\r
8663                                 columnSelector = null;\r
8664                         }\r
8665                 }\r
8666                 if ( $.isPlainObject( columnSelector ) ) {\r
8667                         opts = columnSelector;\r
8668                         columnSelector = null;\r
8669                 }\r
8670         \r
8671                 // Cell selector\r
8672                 if ( columnSelector === null || columnSelector === undefined ) {\r
8673                         return this.iterator( 'table', function ( settings ) {\r
8674                                 return __cell_selector( settings, rowSelector, _selector_opts( opts ) );\r
8675                         } );\r
8676                 }\r
8677         \r
8678                 // Row + column selector\r
8679                 var columns = this.columns( columnSelector, opts );\r
8680                 var rows = this.rows( rowSelector, opts );\r
8681                 var a, i, ien, j, jen;\r
8682         \r
8683                 var cells = this.iterator( 'table', function ( settings, idx ) {\r
8684                         a = [];\r
8685         \r
8686                         for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {\r
8687                                 for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {\r
8688                                         a.push( {\r
8689                                                 row:    rows[idx][i],\r
8690                                                 column: columns[idx][j]\r
8691                                         } );\r
8692                                 }\r
8693                         }\r
8694         \r
8695                         return a;\r
8696                 }, 1 );\r
8697         \r
8698                 $.extend( cells.selector, {\r
8699                         cols: columnSelector,\r
8700                         rows: rowSelector,\r
8701                         opts: opts\r
8702                 } );\r
8703         \r
8704                 return cells;\r
8705         } );\r
8706         \r
8707         \r
8708         _api_registerPlural( 'cells().nodes()', 'cell().node()', function () {\r
8709                 return this.iterator( 'cell', function ( settings, row, column ) {\r
8710                         var data = settings.aoData[ row ];\r
8711         \r
8712                         return data && data.anCells ?\r
8713                                 data.anCells[ column ] :\r
8714                                 undefined;\r
8715                 }, 1 );\r
8716         } );\r
8717         \r
8718         \r
8719         _api_register( 'cells().data()', function () {\r
8720                 return this.iterator( 'cell', function ( settings, row, column ) {\r
8721                         return _fnGetCellData( settings, row, column );\r
8722                 }, 1 );\r
8723         } );\r
8724         \r
8725         \r
8726         _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {\r
8727                 type = type === 'search' ? '_aFilterData' : '_aSortData';\r
8728         \r
8729                 return this.iterator( 'cell', function ( settings, row, column ) {\r
8730                         return settings.aoData[ row ][ type ][ column ];\r
8731                 }, 1 );\r
8732         } );\r
8733         \r
8734         \r
8735         _api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) {\r
8736                 return this.iterator( 'cell', function ( settings, row, column ) {\r
8737                         return _fnGetCellData( settings, row, column, type );\r
8738                 }, 1 );\r
8739         } );\r
8740         \r
8741         \r
8742         _api_registerPlural( 'cells().indexes()', 'cell().index()', function () {\r
8743                 return this.iterator( 'cell', function ( settings, row, column ) {\r
8744                         return {\r
8745                                 row: row,\r
8746                                 column: column,\r
8747                                 columnVisible: _fnColumnIndexToVisible( settings, column )\r
8748                         };\r
8749                 }, 1 );\r
8750         } );\r
8751         \r
8752         \r
8753         _api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) {\r
8754                 return this.iterator( 'cell', function ( settings, row, column ) {\r
8755                         _fnInvalidate( settings, row, src, column );\r
8756                 } );\r
8757         } );\r
8758         \r
8759         \r
8760         \r
8761         _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {\r
8762                 return _selector_first( this.cells( rowSelector, columnSelector, opts ) );\r
8763         } );\r
8764         \r
8765         \r
8766         _api_register( 'cell().data()', function ( data ) {\r
8767                 var ctx = this.context;\r
8768                 var cell = this[0];\r
8769         \r
8770                 if ( data === undefined ) {\r
8771                         // Get\r
8772                         return ctx.length && cell.length ?\r
8773                                 _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :\r
8774                                 undefined;\r
8775                 }\r
8776         \r
8777                 // Set\r
8778                 _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );\r
8779                 _fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column );\r
8780         \r
8781                 return this;\r
8782         } );\r
8783         \r
8784         \r
8785         \r
8786         /**\r
8787          * Get current ordering (sorting) that has been applied to the table.\r
8788          *\r
8789          * @returns {array} 2D array containing the sorting information for the first\r
8790          *   table in the current context. Each element in the parent array represents\r
8791          *   a column being sorted upon (i.e. multi-sorting with two columns would have\r
8792          *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is\r
8793          *   the column index that the sorting condition applies to, the second is the\r
8794          *   direction of the sort (`desc` or `asc`) and, optionally, the third is the\r
8795          *   index of the sorting order from the `column.sorting` initialisation array.\r
8796          *//**\r
8797          * Set the ordering for the table.\r
8798          *\r
8799          * @param {integer} order Column index to sort upon.\r
8800          * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)\r
8801          * @returns {DataTables.Api} this\r
8802          *//**\r
8803          * Set the ordering for the table.\r
8804          *\r
8805          * @param {array} order 1D array of sorting information to be applied.\r
8806          * @param {array} [...] Optional additional sorting conditions\r
8807          * @returns {DataTables.Api} this\r
8808          *//**\r
8809          * Set the ordering for the table.\r
8810          *\r
8811          * @param {array} order 2D array of sorting information to be applied.\r
8812          * @returns {DataTables.Api} this\r
8813          */\r
8814         _api_register( 'order()', function ( order, dir ) {\r
8815                 var ctx = this.context;\r
8816         \r
8817                 if ( order === undefined ) {\r
8818                         // get\r
8819                         return ctx.length !== 0 ?\r
8820                                 ctx[0].aaSorting :\r
8821                                 undefined;\r
8822                 }\r
8823         \r
8824                 // set\r
8825                 if ( typeof order === 'number' ) {\r
8826                         // Simple column / direction passed in\r
8827                         order = [ [ order, dir ] ];\r
8828                 }\r
8829                 else if ( ! $.isArray( order[0] ) ) {\r
8830                         // Arguments passed in (list of 1D arrays)\r
8831                         order = Array.prototype.slice.call( arguments );\r
8832                 }\r
8833                 // otherwise a 2D array was passed in\r
8834         \r
8835                 return this.iterator( 'table', function ( settings ) {\r
8836                         settings.aaSorting = order.slice();\r
8837                 } );\r
8838         } );\r
8839         \r
8840         \r
8841         /**\r
8842          * Attach a sort listener to an element for a given column\r
8843          *\r
8844          * @param {node|jQuery|string} node Identifier for the element(s) to attach the\r
8845          *   listener to. This can take the form of a single DOM node, a jQuery\r
8846          *   collection of nodes or a jQuery selector which will identify the node(s).\r
8847          * @param {integer} column the column that a click on this node will sort on\r
8848          * @param {function} [callback] callback function when sort is run\r
8849          * @returns {DataTables.Api} this\r
8850          */\r
8851         _api_register( 'order.listener()', function ( node, column, callback ) {\r
8852                 return this.iterator( 'table', function ( settings ) {\r
8853                         _fnSortAttachListener( settings, node, column, callback );\r
8854                 } );\r
8855         } );\r
8856         \r
8857         \r
8858         _api_register( 'order.fixed()', function ( set ) {\r
8859                 if ( ! set ) {\r
8860                         var ctx = this.context;\r
8861                         var fixed = ctx.length ?\r
8862                                 ctx[0].aaSortingFixed :\r
8863                                 undefined;\r
8864         \r
8865                         return $.isArray( fixed ) ?\r
8866                                 { pre: fixed } :\r
8867                                 fixed;\r
8868                 }\r
8869         \r
8870                 return this.iterator( 'table', function ( settings ) {\r
8871                         settings.aaSortingFixed = $.extend( true, {}, set );\r
8872                 } );\r
8873         } );\r
8874         \r
8875         \r
8876         // Order by the selected column(s)\r
8877         _api_register( [\r
8878                 'columns().order()',\r
8879                 'column().order()'\r
8880         ], function ( dir ) {\r
8881                 var that = this;\r
8882         \r
8883                 return this.iterator( 'table', function ( settings, i ) {\r
8884                         var sort = [];\r
8885         \r
8886                         $.each( that[i], function (j, col) {\r
8887                                 sort.push( [ col, dir ] );\r
8888                         } );\r
8889         \r
8890                         settings.aaSorting = sort;\r
8891                 } );\r
8892         } );\r
8893         \r
8894         \r
8895         \r
8896         _api_register( 'search()', function ( input, regex, smart, caseInsen ) {\r
8897                 var ctx = this.context;\r
8898         \r
8899                 if ( input === undefined ) {\r
8900                         // get\r
8901                         return ctx.length !== 0 ?\r
8902                                 ctx[0].oPreviousSearch.sSearch :\r
8903                                 undefined;\r
8904                 }\r
8905         \r
8906                 // set\r
8907                 return this.iterator( 'table', function ( settings ) {\r
8908                         if ( ! settings.oFeatures.bFilter ) {\r
8909                                 return;\r
8910                         }\r
8911         \r
8912                         _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {\r
8913                                 "sSearch": input+"",\r
8914                                 "bRegex":  regex === null ? false : regex,\r
8915                                 "bSmart":  smart === null ? true  : smart,\r
8916                                 "bCaseInsensitive": caseInsen === null ? true : caseInsen\r
8917                         } ), 1 );\r
8918                 } );\r
8919         } );\r
8920         \r
8921         \r
8922         _api_registerPlural(\r
8923                 'columns().search()',\r
8924                 'column().search()',\r
8925                 function ( input, regex, smart, caseInsen ) {\r
8926                         return this.iterator( 'column', function ( settings, column ) {\r
8927                                 var preSearch = settings.aoPreSearchCols;\r
8928         \r
8929                                 if ( input === undefined ) {\r
8930                                         // get\r
8931                                         return preSearch[ column ].sSearch;\r
8932                                 }\r
8933         \r
8934                                 // set\r
8935                                 if ( ! settings.oFeatures.bFilter ) {\r
8936                                         return;\r
8937                                 }\r
8938         \r
8939                                 $.extend( preSearch[ column ], {\r
8940                                         "sSearch": input+"",\r
8941                                         "bRegex":  regex === null ? false : regex,\r
8942                                         "bSmart":  smart === null ? true  : smart,\r
8943                                         "bCaseInsensitive": caseInsen === null ? true : caseInsen\r
8944                                 } );\r
8945         \r
8946                                 _fnFilterComplete( settings, settings.oPreviousSearch, 1 );\r
8947                         } );\r
8948                 }\r
8949         );\r
8950         \r
8951         /*\r
8952          * State API methods\r
8953          */\r
8954         \r
8955         _api_register( 'state()', function () {\r
8956                 return this.context.length ?\r
8957                         this.context[0].oSavedState :\r
8958                         null;\r
8959         } );\r
8960         \r
8961         \r
8962         _api_register( 'state.clear()', function () {\r
8963                 return this.iterator( 'table', function ( settings ) {\r
8964                         // Save an empty object\r
8965                         settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );\r
8966                 } );\r
8967         } );\r
8968         \r
8969         \r
8970         _api_register( 'state.loaded()', function () {\r
8971                 return this.context.length ?\r
8972                         this.context[0].oLoadedState :\r
8973                         null;\r
8974         } );\r
8975         \r
8976         \r
8977         _api_register( 'state.save()', function () {\r
8978                 return this.iterator( 'table', function ( settings ) {\r
8979                         _fnSaveState( settings );\r
8980                 } );\r
8981         } );\r
8982         \r
8983         \r
8984         \r
8985         /**\r
8986          * Provide a common method for plug-ins to check the version of DataTables being\r
8987          * used, in order to ensure compatibility.\r
8988          *\r
8989          *  @param {string} version Version string to check for, in the format "X.Y.Z".\r
8990          *    Note that the formats "X" and "X.Y" are also acceptable.\r
8991          *  @returns {boolean} true if this version of DataTables is greater or equal to\r
8992          *    the required version, or false if this version of DataTales is not\r
8993          *    suitable\r
8994          *  @static\r
8995          *  @dtopt API-Static\r
8996          *\r
8997          *  @example\r
8998          *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );\r
8999          */\r
9000         DataTable.versionCheck = DataTable.fnVersionCheck = function( version )\r
9001         {\r
9002                 var aThis = DataTable.version.split('.');\r
9003                 var aThat = version.split('.');\r
9004                 var iThis, iThat;\r
9005         \r
9006                 for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {\r
9007                         iThis = parseInt( aThis[i], 10 ) || 0;\r
9008                         iThat = parseInt( aThat[i], 10 ) || 0;\r
9009         \r
9010                         // Parts are the same, keep comparing\r
9011                         if (iThis === iThat) {\r
9012                                 continue;\r
9013                         }\r
9014         \r
9015                         // Parts are different, return immediately\r
9016                         return iThis > iThat;\r
9017                 }\r
9018         \r
9019                 return true;\r
9020         };\r
9021         \r
9022         \r
9023         /**\r
9024          * Check if a `<table>` node is a DataTable table already or not.\r
9025          *\r
9026          *  @param {node|jquery|string} table Table node, jQuery object or jQuery\r
9027          *      selector for the table to test. Note that if more than more than one\r
9028          *      table is passed on, only the first will be checked\r
9029          *  @returns {boolean} true the table given is a DataTable, or false otherwise\r
9030          *  @static\r
9031          *  @dtopt API-Static\r
9032          *\r
9033          *  @example\r
9034          *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {\r
9035          *      $('#example').dataTable();\r
9036          *    }\r
9037          */\r
9038         DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )\r
9039         {\r
9040                 var t = $(table).get(0);\r
9041                 var is = false;\r
9042         \r
9043                 $.each( DataTable.settings, function (i, o) {\r
9044                         var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null;\r
9045                         var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null;\r
9046         \r
9047                         if ( o.nTable === t || head === t || foot === t ) {\r
9048                                 is = true;\r
9049                         }\r
9050                 } );\r
9051         \r
9052                 return is;\r
9053         };\r
9054         \r
9055         \r
9056         /**\r
9057          * Get all DataTable tables that have been initialised - optionally you can\r
9058          * select to get only currently visible tables.\r
9059          *\r
9060          *  @param {boolean} [visible=false] Flag to indicate if you want all (default)\r
9061          *    or visible tables only.\r
9062          *  @returns {array} Array of `table` nodes (not DataTable instances) which are\r
9063          *    DataTables\r
9064          *  @static\r
9065          *  @dtopt API-Static\r
9066          *\r
9067          *  @example\r
9068          *    $.each( $.fn.dataTable.tables(true), function () {\r
9069          *      $(table).DataTable().columns.adjust();\r
9070          *    } );\r
9071          */\r
9072         DataTable.tables = DataTable.fnTables = function ( visible )\r
9073         {\r
9074                 var api = false;\r
9075         \r
9076                 if ( $.isPlainObject( visible ) ) {\r
9077                         api = visible.api;\r
9078                         visible = visible.visible;\r
9079                 }\r
9080         \r
9081                 var a = $.map( DataTable.settings, function (o) {\r
9082                         if ( !visible || (visible && $(o.nTable).is(':visible')) ) {\r
9083                                 return o.nTable;\r
9084                         }\r
9085                 } );\r
9086         \r
9087                 return api ?\r
9088                         new _Api( a ) :\r
9089                         a;\r
9090         };\r
9091         \r
9092         \r
9093         /**\r
9094          * DataTables utility methods\r
9095          * \r
9096          * This namespace provides helper methods that DataTables uses internally to\r
9097          * create a DataTable, but which are not exclusively used only for DataTables.\r
9098          * These methods can be used by extension authors to save the duplication of\r
9099          * code.\r
9100          *\r
9101          *  @namespace\r
9102          */\r
9103         DataTable.util = {\r
9104                 /**\r
9105                  * Throttle the calls to a function. Arguments and context are maintained\r
9106                  * for the throttled function.\r
9107                  *\r
9108                  * @param {function} fn Function to be called\r
9109                  * @param {integer} freq Call frequency in mS\r
9110                  * @return {function} Wrapped function\r
9111                  */\r
9112                 throttle: _fnThrottle,\r
9113         \r
9114         \r
9115                 /**\r
9116                  * Escape a string such that it can be used in a regular expression\r
9117                  *\r
9118                  *  @param {string} sVal string to escape\r
9119                  *  @returns {string} escaped string\r
9120                  */\r
9121                 escapeRegex: _fnEscapeRegex\r
9122         };\r
9123         \r
9124         \r
9125         /**\r
9126          * Convert from camel case parameters to Hungarian notation. This is made public\r
9127          * for the extensions to provide the same ability as DataTables core to accept\r
9128          * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase\r
9129          * parameters.\r
9130          *\r
9131          *  @param {object} src The model object which holds all parameters that can be\r
9132          *    mapped.\r
9133          *  @param {object} user The object to convert from camel case to Hungarian.\r
9134          *  @param {boolean} force When set to `true`, properties which already have a\r
9135          *    Hungarian value in the `user` object will be overwritten. Otherwise they\r
9136          *    won't be.\r
9137          */\r
9138         DataTable.camelToHungarian = _fnCamelToHungarian;\r
9139         \r
9140         \r
9141         \r
9142         /**\r
9143          *\r
9144          */\r
9145         _api_register( '$()', function ( selector, opts ) {\r
9146                 var\r
9147                         rows   = this.rows( opts ).nodes(), // Get all rows\r
9148                         jqRows = $(rows);\r
9149         \r
9150                 return $( [].concat(\r
9151                         jqRows.filter( selector ).toArray(),\r
9152                         jqRows.find( selector ).toArray()\r
9153                 ) );\r
9154         } );\r
9155         \r
9156         \r
9157         // jQuery functions to operate on the tables\r
9158         $.each( [ 'on', 'one', 'off' ], function (i, key) {\r
9159                 _api_register( key+'()', function ( /* event, handler */ ) {\r
9160                         var args = Array.prototype.slice.call(arguments);\r
9161         \r
9162                         // Add the `dt` namespace automatically if it isn't already present\r
9163                         if ( ! args[0].match(/\.dt\b/) ) {\r
9164                                 args[0] += '.dt';\r
9165                         }\r
9166         \r
9167                         var inst = $( this.tables().nodes() );\r
9168                         inst[key].apply( inst, args );\r
9169                         return this;\r
9170                 } );\r
9171         } );\r
9172         \r
9173         \r
9174         _api_register( 'clear()', function () {\r
9175                 return this.iterator( 'table', function ( settings ) {\r
9176                         _fnClearTable( settings );\r
9177                 } );\r
9178         } );\r
9179         \r
9180         \r
9181         _api_register( 'settings()', function () {\r
9182                 return new _Api( this.context, this.context );\r
9183         } );\r
9184         \r
9185         \r
9186         _api_register( 'init()', function () {\r
9187                 var ctx = this.context;\r
9188                 return ctx.length ? ctx[0].oInit : null;\r
9189         } );\r
9190         \r
9191         \r
9192         _api_register( 'data()', function () {\r
9193                 return this.iterator( 'table', function ( settings ) {\r
9194                         return _pluck( settings.aoData, '_aData' );\r
9195                 } ).flatten();\r
9196         } );\r
9197         \r
9198         \r
9199         _api_register( 'destroy()', function ( remove ) {\r
9200                 remove = remove || false;\r
9201         \r
9202                 return this.iterator( 'table', function ( settings ) {\r
9203                         var orig      = settings.nTableWrapper.parentNode;\r
9204                         var classes   = settings.oClasses;\r
9205                         var table     = settings.nTable;\r
9206                         var tbody     = settings.nTBody;\r
9207                         var thead     = settings.nTHead;\r
9208                         var tfoot     = settings.nTFoot;\r
9209                         var jqTable   = $(table);\r
9210                         var jqTbody   = $(tbody);\r
9211                         var jqWrapper = $(settings.nTableWrapper);\r
9212                         var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );\r
9213                         var i, ien;\r
9214         \r
9215                         // Flag to note that the table is currently being destroyed - no action\r
9216                         // should be taken\r
9217                         settings.bDestroying = true;\r
9218         \r
9219                         // Fire off the destroy callbacks for plug-ins etc\r
9220                         _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );\r
9221         \r
9222                         // If not being removed from the document, make all columns visible\r
9223                         if ( ! remove ) {\r
9224                                 new _Api( settings ).columns().visible( true );\r
9225                         }\r
9226         \r
9227                         // Blitz all `DT` namespaced events (these are internal events, the\r
9228                         // lowercase, `dt` events are user subscribed and they are responsible\r
9229                         // for removing them\r
9230                         jqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT');\r
9231                         $(window).unbind('.DT-'+settings.sInstance);\r
9232         \r
9233                         // When scrolling we had to break the table up - restore it\r
9234                         if ( table != thead.parentNode ) {\r
9235                                 jqTable.children('thead').detach();\r
9236                                 jqTable.append( thead );\r
9237                         }\r
9238         \r
9239                         if ( tfoot && table != tfoot.parentNode ) {\r
9240                                 jqTable.children('tfoot').detach();\r
9241                                 jqTable.append( tfoot );\r
9242                         }\r
9243         \r
9244                         settings.aaSorting = [];\r
9245                         settings.aaSortingFixed = [];\r
9246                         _fnSortingClasses( settings );\r
9247         \r
9248                         $( rows ).removeClass( settings.asStripeClasses.join(' ') );\r
9249         \r
9250                         $('th, td', thead).removeClass( classes.sSortable+' '+\r
9251                                 classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone\r
9252                         );\r
9253         \r
9254                         if ( settings.bJUI ) {\r
9255                                 $('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach();\r
9256                                 $('th, td', thead).each( function () {\r
9257                                         var wrapper = $('div.'+classes.sSortJUIWrapper, this);\r
9258                                         $(this).append( wrapper.contents() );\r
9259                                         wrapper.detach();\r
9260                                 } );\r
9261                         }\r
9262         \r
9263                         // Add the TR elements back into the table in their original order\r
9264                         jqTbody.children().detach();\r
9265                         jqTbody.append( rows );\r
9266         \r
9267                         // Remove the DataTables generated nodes, events and classes\r
9268                         var removedMethod = remove ? 'remove' : 'detach';\r
9269                         jqTable[ removedMethod ]();\r
9270                         jqWrapper[ removedMethod ]();\r
9271         \r
9272                         // If we need to reattach the table to the document\r
9273                         if ( ! remove && orig ) {\r
9274                                 // insertBefore acts like appendChild if !arg[1]\r
9275                                 orig.insertBefore( table, settings.nTableReinsertBefore );\r
9276         \r
9277                                 // Restore the width of the original table - was read from the style property,\r
9278                                 // so we can restore directly to that\r
9279                                 jqTable\r
9280                                         .css( 'width', settings.sDestroyWidth )\r
9281                                         .removeClass( classes.sTable );\r
9282         \r
9283                                 // If the were originally stripe classes - then we add them back here.\r
9284                                 // Note this is not fool proof (for example if not all rows had stripe\r
9285                                 // classes - but it's a good effort without getting carried away\r
9286                                 ien = settings.asDestroyStripes.length;\r
9287         \r
9288                                 if ( ien ) {\r
9289                                         jqTbody.children().each( function (i) {\r
9290                                                 $(this).addClass( settings.asDestroyStripes[i % ien] );\r
9291                                         } );\r
9292                                 }\r
9293                         }\r
9294         \r
9295                         /* Remove the settings object from the settings array */\r
9296                         var idx = $.inArray( settings, DataTable.settings );\r
9297                         if ( idx !== -1 ) {\r
9298                                 DataTable.settings.splice( idx, 1 );\r
9299                         }\r
9300                 } );\r
9301         } );\r
9302         \r
9303         \r
9304         // Add the `every()` method for rows, columns and cells in a compact form\r
9305         $.each( [ 'column', 'row', 'cell' ], function ( i, type ) {\r
9306                 _api_register( type+'s().every()', function ( fn ) {\r
9307                         var opts = this.selector.opts;\r
9308                         var api = this;\r
9309         \r
9310                         return this.iterator( type, function ( settings, arg1, arg2, arg3, arg4 ) {\r
9311                                 // Rows and columns:\r
9312                                 //  arg1 - index\r
9313                                 //  arg2 - table counter\r
9314                                 //  arg3 - loop counter\r
9315                                 //  arg4 - undefined\r
9316                                 // Cells:\r
9317                                 //  arg1 - row index\r
9318                                 //  arg2 - column index\r
9319                                 //  arg3 - table counter\r
9320                                 //  arg4 - loop counter\r
9321                                 fn.call(\r
9322                                         api[ type ](\r
9323                                                 arg1,\r
9324                                                 type==='cell' ? arg2 : opts,\r
9325                                                 type==='cell' ? opts : undefined\r
9326                                         ),\r
9327                                         arg1, arg2, arg3, arg4\r
9328                                 );\r
9329                         } );\r
9330                 } );\r
9331         } );\r
9332         \r
9333         \r
9334         // i18n method for extensions to be able to use the language object from the\r
9335         // DataTable\r
9336         _api_register( 'i18n()', function ( token, def, plural ) {\r
9337                 var ctx = this.context[0];\r
9338                 var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage );\r
9339         \r
9340                 if ( resolved === undefined ) {\r
9341                         resolved = def;\r
9342                 }\r
9343         \r
9344                 if ( plural !== undefined && $.isPlainObject( resolved ) ) {\r
9345                         resolved = resolved[ plural ] !== undefined ?\r
9346                                 resolved[ plural ] :\r
9347                                 resolved._;\r
9348                 }\r
9349         \r
9350                 return resolved.replace( '%d', plural ); // nb: plural might be undefined,\r
9351         } );\r
9352 \r
9353         /**\r
9354          * Version string for plug-ins to check compatibility. Allowed format is\r
9355          * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used\r
9356          * only for non-release builds. See http://semver.org/ for more information.\r
9357          *  @member\r
9358          *  @type string\r
9359          *  @default Version number\r
9360          */\r
9361         DataTable.version = "1.10.11";\r
9362 \r
9363         /**\r
9364          * Private data store, containing all of the settings objects that are\r
9365          * created for the tables on a given page.\r
9366          *\r
9367          * Note that the `DataTable.settings` object is aliased to\r
9368          * `jQuery.fn.dataTableExt` through which it may be accessed and\r
9369          * manipulated, or `jQuery.fn.dataTable.settings`.\r
9370          *  @member\r
9371          *  @type array\r
9372          *  @default []\r
9373          *  @private\r
9374          */\r
9375         DataTable.settings = [];\r
9376 \r
9377         /**\r
9378          * Object models container, for the various models that DataTables has\r
9379          * available to it. These models define the objects that are used to hold\r
9380          * the active state and configuration of the table.\r
9381          *  @namespace\r
9382          */\r
9383         DataTable.models = {};\r
9384         \r
9385         \r
9386         \r
9387         /**\r
9388          * Template object for the way in which DataTables holds information about\r
9389          * search information for the global filter and individual column filters.\r
9390          *  @namespace\r
9391          */\r
9392         DataTable.models.oSearch = {\r
9393                 /**\r
9394                  * Flag to indicate if the filtering should be case insensitive or not\r
9395                  *  @type boolean\r
9396                  *  @default true\r
9397                  */\r
9398                 "bCaseInsensitive": true,\r
9399         \r
9400                 /**\r
9401                  * Applied search term\r
9402                  *  @type string\r
9403                  *  @default <i>Empty string</i>\r
9404                  */\r
9405                 "sSearch": "",\r
9406         \r
9407                 /**\r
9408                  * Flag to indicate if the search term should be interpreted as a\r
9409                  * regular expression (true) or not (false) and therefore and special\r
9410                  * regex characters escaped.\r
9411                  *  @type boolean\r
9412                  *  @default false\r
9413                  */\r
9414                 "bRegex": false,\r
9415         \r
9416                 /**\r
9417                  * Flag to indicate if DataTables is to use its smart filtering or not.\r
9418                  *  @type boolean\r
9419                  *  @default true\r
9420                  */\r
9421                 "bSmart": true\r
9422         };\r
9423         \r
9424         \r
9425         \r
9426         \r
9427         /**\r
9428          * Template object for the way in which DataTables holds information about\r
9429          * each individual row. This is the object format used for the settings\r
9430          * aoData array.\r
9431          *  @namespace\r
9432          */\r
9433         DataTable.models.oRow = {\r
9434                 /**\r
9435                  * TR element for the row\r
9436                  *  @type node\r
9437                  *  @default null\r
9438                  */\r
9439                 "nTr": null,\r
9440         \r
9441                 /**\r
9442                  * Array of TD elements for each row. This is null until the row has been\r
9443                  * created.\r
9444                  *  @type array nodes\r
9445                  *  @default []\r
9446                  */\r
9447                 "anCells": null,\r
9448         \r
9449                 /**\r
9450                  * Data object from the original data source for the row. This is either\r
9451                  * an array if using the traditional form of DataTables, or an object if\r
9452                  * using mData options. The exact type will depend on the passed in\r
9453                  * data from the data source, or will be an array if using DOM a data\r
9454                  * source.\r
9455                  *  @type array|object\r
9456                  *  @default []\r
9457                  */\r
9458                 "_aData": [],\r
9459         \r
9460                 /**\r
9461                  * Sorting data cache - this array is ostensibly the same length as the\r
9462                  * number of columns (although each index is generated only as it is\r
9463                  * needed), and holds the data that is used for sorting each column in the\r
9464                  * row. We do this cache generation at the start of the sort in order that\r
9465                  * the formatting of the sort data need be done only once for each cell\r
9466                  * per sort. This array should not be read from or written to by anything\r
9467                  * other than the master sorting methods.\r
9468                  *  @type array\r
9469                  *  @default null\r
9470                  *  @private\r
9471                  */\r
9472                 "_aSortData": null,\r
9473         \r
9474                 /**\r
9475                  * Per cell filtering data cache. As per the sort data cache, used to\r
9476                  * increase the performance of the filtering in DataTables\r
9477                  *  @type array\r
9478                  *  @default null\r
9479                  *  @private\r
9480                  */\r
9481                 "_aFilterData": null,\r
9482         \r
9483                 /**\r
9484                  * Filtering data cache. This is the same as the cell filtering cache, but\r
9485                  * in this case a string rather than an array. This is easily computed with\r
9486                  * a join on `_aFilterData`, but is provided as a cache so the join isn't\r
9487                  * needed on every search (memory traded for performance)\r
9488                  *  @type array\r
9489                  *  @default null\r
9490                  *  @private\r
9491                  */\r
9492                 "_sFilterRow": null,\r
9493         \r
9494                 /**\r
9495                  * Cache of the class name that DataTables has applied to the row, so we\r
9496                  * can quickly look at this variable rather than needing to do a DOM check\r
9497                  * on className for the nTr property.\r
9498                  *  @type string\r
9499                  *  @default <i>Empty string</i>\r
9500                  *  @private\r
9501                  */\r
9502                 "_sRowStripe": "",\r
9503         \r
9504                 /**\r
9505                  * Denote if the original data source was from the DOM, or the data source\r
9506                  * object. This is used for invalidating data, so DataTables can\r
9507                  * automatically read data from the original source, unless uninstructed\r
9508                  * otherwise.\r
9509                  *  @type string\r
9510                  *  @default null\r
9511                  *  @private\r
9512                  */\r
9513                 "src": null,\r
9514         \r
9515                 /**\r
9516                  * Index in the aoData array. This saves an indexOf lookup when we have the\r
9517                  * object, but want to know the index\r
9518                  *  @type integer\r
9519                  *  @default -1\r
9520                  *  @private\r
9521                  */\r
9522                 "idx": -1\r
9523         };\r
9524         \r
9525         \r
9526         /**\r
9527          * Template object for the column information object in DataTables. This object\r
9528          * is held in the settings aoColumns array and contains all the information that\r
9529          * DataTables needs about each individual column.\r
9530          *\r
9531          * Note that this object is related to {@link DataTable.defaults.column}\r
9532          * but this one is the internal data store for DataTables's cache of columns.\r
9533          * It should NOT be manipulated outside of DataTables. Any configuration should\r
9534          * be done through the initialisation options.\r
9535          *  @namespace\r
9536          */\r
9537         DataTable.models.oColumn = {\r
9538                 /**\r
9539                  * Column index. This could be worked out on-the-fly with $.inArray, but it\r
9540                  * is faster to just hold it as a variable\r
9541                  *  @type integer\r
9542                  *  @default null\r
9543                  */\r
9544                 "idx": null,\r
9545         \r
9546                 /**\r
9547                  * A list of the columns that sorting should occur on when this column\r
9548                  * is sorted. That this property is an array allows multi-column sorting\r
9549                  * to be defined for a column (for example first name / last name columns\r
9550                  * would benefit from this). The values are integers pointing to the\r
9551                  * columns to be sorted on (typically it will be a single integer pointing\r
9552                  * at itself, but that doesn't need to be the case).\r
9553                  *  @type array\r
9554                  */\r
9555                 "aDataSort": null,\r
9556         \r
9557                 /**\r
9558                  * Define the sorting directions that are applied to the column, in sequence\r
9559                  * as the column is repeatedly sorted upon - i.e. the first value is used\r
9560                  * as the sorting direction when the column if first sorted (clicked on).\r
9561                  * Sort it again (click again) and it will move on to the next index.\r
9562                  * Repeat until loop.\r
9563                  *  @type array\r
9564                  */\r
9565                 "asSorting": null,\r
9566         \r
9567                 /**\r
9568                  * Flag to indicate if the column is searchable, and thus should be included\r
9569                  * in the filtering or not.\r
9570                  *  @type boolean\r
9571                  */\r
9572                 "bSearchable": null,\r
9573         \r
9574                 /**\r
9575                  * Flag to indicate if the column is sortable or not.\r
9576                  *  @type boolean\r
9577                  */\r
9578                 "bSortable": null,\r
9579         \r
9580                 /**\r
9581                  * Flag to indicate if the column is currently visible in the table or not\r
9582                  *  @type boolean\r
9583                  */\r
9584                 "bVisible": null,\r
9585         \r
9586                 /**\r
9587                  * Store for manual type assignment using the `column.type` option. This\r
9588                  * is held in store so we can manipulate the column's `sType` property.\r
9589                  *  @type string\r
9590                  *  @default null\r
9591                  *  @private\r
9592                  */\r
9593                 "_sManualType": null,\r
9594         \r
9595                 /**\r
9596                  * Flag to indicate if HTML5 data attributes should be used as the data\r
9597                  * source for filtering or sorting. True is either are.\r
9598                  *  @type boolean\r
9599                  *  @default false\r
9600                  *  @private\r
9601                  */\r
9602                 "_bAttrSrc": false,\r
9603         \r
9604                 /**\r
9605                  * Developer definable function that is called whenever a cell is created (Ajax source,\r
9606                  * etc) or processed for input (DOM source). This can be used as a compliment to mRender\r
9607                  * allowing you to modify the DOM element (add background colour for example) when the\r
9608                  * element is available.\r
9609                  *  @type function\r
9610                  *  @param {element} nTd The TD node that has been created\r
9611                  *  @param {*} sData The Data for the cell\r
9612                  *  @param {array|object} oData The data for the whole row\r
9613                  *  @param {int} iRow The row index for the aoData data store\r
9614                  *  @default null\r
9615                  */\r
9616                 "fnCreatedCell": null,\r
9617         \r
9618                 /**\r
9619                  * Function to get data from a cell in a column. You should <b>never</b>\r
9620                  * access data directly through _aData internally in DataTables - always use\r
9621                  * the method attached to this property. It allows mData to function as\r
9622                  * required. This function is automatically assigned by the column\r
9623                  * initialisation method\r
9624                  *  @type function\r
9625                  *  @param {array|object} oData The data array/object for the array\r
9626                  *    (i.e. aoData[]._aData)\r
9627                  *  @param {string} sSpecific The specific data type you want to get -\r
9628                  *    'display', 'type' 'filter' 'sort'\r
9629                  *  @returns {*} The data for the cell from the given row's data\r
9630                  *  @default null\r
9631                  */\r
9632                 "fnGetData": null,\r
9633         \r
9634                 /**\r
9635                  * Function to set data for a cell in the column. You should <b>never</b>\r
9636                  * set the data directly to _aData internally in DataTables - always use\r
9637                  * this method. It allows mData to function as required. This function\r
9638                  * is automatically assigned by the column initialisation method\r
9639                  *  @type function\r
9640                  *  @param {array|object} oData The data array/object for the array\r
9641                  *    (i.e. aoData[]._aData)\r
9642                  *  @param {*} sValue Value to set\r
9643                  *  @default null\r
9644                  */\r
9645                 "fnSetData": null,\r
9646         \r
9647                 /**\r
9648                  * Property to read the value for the cells in the column from the data\r
9649                  * source array / object. If null, then the default content is used, if a\r
9650                  * function is given then the return from the function is used.\r
9651                  *  @type function|int|string|null\r
9652                  *  @default null\r
9653                  */\r
9654                 "mData": null,\r
9655         \r
9656                 /**\r
9657                  * Partner property to mData which is used (only when defined) to get\r
9658                  * the data - i.e. it is basically the same as mData, but without the\r
9659                  * 'set' option, and also the data fed to it is the result from mData.\r
9660                  * This is the rendering method to match the data method of mData.\r
9661                  *  @type function|int|string|null\r
9662                  *  @default null\r
9663                  */\r
9664                 "mRender": null,\r
9665         \r
9666                 /**\r
9667                  * Unique header TH/TD element for this column - this is what the sorting\r
9668                  * listener is attached to (if sorting is enabled.)\r
9669                  *  @type node\r
9670                  *  @default null\r
9671                  */\r
9672                 "nTh": null,\r
9673         \r
9674                 /**\r
9675                  * Unique footer TH/TD element for this column (if there is one). Not used\r
9676                  * in DataTables as such, but can be used for plug-ins to reference the\r
9677                  * footer for each column.\r
9678                  *  @type node\r
9679                  *  @default null\r
9680                  */\r
9681                 "nTf": null,\r
9682         \r
9683                 /**\r
9684                  * The class to apply to all TD elements in the table's TBODY for the column\r
9685                  *  @type string\r
9686                  *  @default null\r
9687                  */\r
9688                 "sClass": null,\r
9689         \r
9690                 /**\r
9691                  * When DataTables calculates the column widths to assign to each column,\r
9692                  * it finds the longest string in each column and then constructs a\r
9693                  * temporary table and reads the widths from that. The problem with this\r
9694                  * is that "mmm" is much wider then "iiii", but the latter is a longer\r
9695                  * string - thus the calculation can go wrong (doing it properly and putting\r
9696                  * it into an DOM object and measuring that is horribly(!) slow). Thus as\r
9697                  * a "work around" we provide this option. It will append its value to the\r
9698                  * text that is found to be the longest string for the column - i.e. padding.\r
9699                  *  @type string\r
9700                  */\r
9701                 "sContentPadding": null,\r
9702         \r
9703                 /**\r
9704                  * Allows a default value to be given for a column's data, and will be used\r
9705                  * whenever a null data source is encountered (this can be because mData\r
9706                  * is set to null, or because the data source itself is null).\r
9707                  *  @type string\r
9708                  *  @default null\r
9709                  */\r
9710                 "sDefaultContent": null,\r
9711         \r
9712                 /**\r
9713                  * Name for the column, allowing reference to the column by name as well as\r
9714                  * by index (needs a lookup to work by name).\r
9715                  *  @type string\r
9716                  */\r
9717                 "sName": null,\r
9718         \r
9719                 /**\r
9720                  * Custom sorting data type - defines which of the available plug-ins in\r
9721                  * afnSortData the custom sorting will use - if any is defined.\r
9722                  *  @type string\r
9723                  *  @default std\r
9724                  */\r
9725                 "sSortDataType": 'std',\r
9726         \r
9727                 /**\r
9728                  * Class to be applied to the header element when sorting on this column\r
9729                  *  @type string\r
9730                  *  @default null\r
9731                  */\r
9732                 "sSortingClass": null,\r
9733         \r
9734                 /**\r
9735                  * Class to be applied to the header element when sorting on this column -\r
9736                  * when jQuery UI theming is used.\r
9737                  *  @type string\r
9738                  *  @default null\r
9739                  */\r
9740                 "sSortingClassJUI": null,\r
9741         \r
9742                 /**\r
9743                  * Title of the column - what is seen in the TH element (nTh).\r
9744                  *  @type string\r
9745                  */\r
9746                 "sTitle": null,\r
9747         \r
9748                 /**\r
9749                  * Column sorting and filtering type\r
9750                  *  @type string\r
9751                  *  @default null\r
9752                  */\r
9753                 "sType": null,\r
9754         \r
9755                 /**\r
9756                  * Width of the column\r
9757                  *  @type string\r
9758                  *  @default null\r
9759                  */\r
9760                 "sWidth": null,\r
9761         \r
9762                 /**\r
9763                  * Width of the column when it was first "encountered"\r
9764                  *  @type string\r
9765                  *  @default null\r
9766                  */\r
9767                 "sWidthOrig": null\r
9768         };\r
9769         \r
9770         \r
9771         /*\r
9772          * Developer note: The properties of the object below are given in Hungarian\r
9773          * notation, that was used as the interface for DataTables prior to v1.10, however\r
9774          * from v1.10 onwards the primary interface is camel case. In order to avoid\r
9775          * breaking backwards compatibility utterly with this change, the Hungarian\r
9776          * version is still, internally the primary interface, but is is not documented\r
9777          * - hence the @name tags in each doc comment. This allows a Javascript function\r
9778          * to create a map from Hungarian notation to camel case (going the other direction\r
9779          * would require each property to be listed, which would at around 3K to the size\r
9780          * of DataTables, while this method is about a 0.5K hit.\r
9781          *\r
9782          * Ultimately this does pave the way for Hungarian notation to be dropped\r
9783          * completely, but that is a massive amount of work and will break current\r
9784          * installs (therefore is on-hold until v2).\r
9785          */\r
9786         \r
9787         /**\r
9788          * Initialisation options that can be given to DataTables at initialisation\r
9789          * time.\r
9790          *  @namespace\r
9791          */\r
9792         DataTable.defaults = {\r
9793                 /**\r
9794                  * An array of data to use for the table, passed in at initialisation which\r
9795                  * will be used in preference to any data which is already in the DOM. This is\r
9796                  * particularly useful for constructing tables purely in Javascript, for\r
9797                  * example with a custom Ajax call.\r
9798                  *  @type array\r
9799                  *  @default null\r
9800                  *\r
9801                  *  @dtopt Option\r
9802                  *  @name DataTable.defaults.data\r
9803                  *\r
9804                  *  @example\r
9805                  *    // Using a 2D array data source\r
9806                  *    $(document).ready( function () {\r
9807                  *      $('#example').dataTable( {\r
9808                  *        "data": [\r
9809                  *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],\r
9810                  *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],\r
9811                  *        ],\r
9812                  *        "columns": [\r
9813                  *          { "title": "Engine" },\r
9814                  *          { "title": "Browser" },\r
9815                  *          { "title": "Platform" },\r
9816                  *          { "title": "Version" },\r
9817                  *          { "title": "Grade" }\r
9818                  *        ]\r
9819                  *      } );\r
9820                  *    } );\r
9821                  *\r
9822                  *  @example\r
9823                  *    // Using an array of objects as a data source (`data`)\r
9824                  *    $(document).ready( function () {\r
9825                  *      $('#example').dataTable( {\r
9826                  *        "data": [\r
9827                  *          {\r
9828                  *            "engine":   "Trident",\r
9829                  *            "browser":  "Internet Explorer 4.0",\r
9830                  *            "platform": "Win 95+",\r
9831                  *            "version":  4,\r
9832                  *            "grade":    "X"\r
9833                  *          },\r
9834                  *          {\r
9835                  *            "engine":   "Trident",\r
9836                  *            "browser":  "Internet Explorer 5.0",\r
9837                  *            "platform": "Win 95+",\r
9838                  *            "version":  5,\r
9839                  *            "grade":    "C"\r
9840                  *          }\r
9841                  *        ],\r
9842                  *        "columns": [\r
9843                  *          { "title": "Engine",   "data": "engine" },\r
9844                  *          { "title": "Browser",  "data": "browser" },\r
9845                  *          { "title": "Platform", "data": "platform" },\r
9846                  *          { "title": "Version",  "data": "version" },\r
9847                  *          { "title": "Grade",    "data": "grade" }\r
9848                  *        ]\r
9849                  *      } );\r
9850                  *    } );\r
9851                  */\r
9852                 "aaData": null,\r
9853         \r
9854         \r
9855                 /**\r
9856                  * If ordering is enabled, then DataTables will perform a first pass sort on\r
9857                  * initialisation. You can define which column(s) the sort is performed\r
9858                  * upon, and the sorting direction, with this variable. The `sorting` array\r
9859                  * should contain an array for each column to be sorted initially containing\r
9860                  * the column's index and a direction string ('asc' or 'desc').\r
9861                  *  @type array\r
9862                  *  @default [[0,'asc']]\r
9863                  *\r
9864                  *  @dtopt Option\r
9865                  *  @name DataTable.defaults.order\r
9866                  *\r
9867                  *  @example\r
9868                  *    // Sort by 3rd column first, and then 4th column\r
9869                  *    $(document).ready( function() {\r
9870                  *      $('#example').dataTable( {\r
9871                  *        "order": [[2,'asc'], [3,'desc']]\r
9872                  *      } );\r
9873                  *    } );\r
9874                  *\r
9875                  *    // No initial sorting\r
9876                  *    $(document).ready( function() {\r
9877                  *      $('#example').dataTable( {\r
9878                  *        "order": []\r
9879                  *      } );\r
9880                  *    } );\r
9881                  */\r
9882                 "aaSorting": [[0,'asc']],\r
9883         \r
9884         \r
9885                 /**\r
9886                  * This parameter is basically identical to the `sorting` parameter, but\r
9887                  * cannot be overridden by user interaction with the table. What this means\r
9888                  * is that you could have a column (visible or hidden) which the sorting\r
9889                  * will always be forced on first - any sorting after that (from the user)\r
9890                  * will then be performed as required. This can be useful for grouping rows\r
9891                  * together.\r
9892                  *  @type array\r
9893                  *  @default null\r
9894                  *\r
9895                  *  @dtopt Option\r
9896                  *  @name DataTable.defaults.orderFixed\r
9897                  *\r
9898                  *  @example\r
9899                  *    $(document).ready( function() {\r
9900                  *      $('#example').dataTable( {\r
9901                  *        "orderFixed": [[0,'asc']]\r
9902                  *      } );\r
9903                  *    } )\r
9904                  */\r
9905                 "aaSortingFixed": [],\r
9906         \r
9907         \r
9908                 /**\r
9909                  * DataTables can be instructed to load data to display in the table from a\r
9910                  * Ajax source. This option defines how that Ajax call is made and where to.\r
9911                  *\r
9912                  * The `ajax` property has three different modes of operation, depending on\r
9913                  * how it is defined. These are:\r
9914                  *\r
9915                  * * `string` - Set the URL from where the data should be loaded from.\r
9916                  * * `object` - Define properties for `jQuery.ajax`.\r
9917                  * * `function` - Custom data get function\r
9918                  *\r
9919                  * `string`\r
9920                  * --------\r
9921                  *\r
9922                  * As a string, the `ajax` property simply defines the URL from which\r
9923                  * DataTables will load data.\r
9924                  *\r
9925                  * `object`\r
9926                  * --------\r
9927                  *\r
9928                  * As an object, the parameters in the object are passed to\r
9929                  * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control\r
9930                  * of the Ajax request. DataTables has a number of default parameters which\r
9931                  * you can override using this option. Please refer to the jQuery\r
9932                  * documentation for a full description of the options available, although\r
9933                  * the following parameters provide additional options in DataTables or\r
9934                  * require special consideration:\r
9935                  *\r
9936                  * * `data` - As with jQuery, `data` can be provided as an object, but it\r
9937                  *   can also be used as a function to manipulate the data DataTables sends\r
9938                  *   to the server. The function takes a single parameter, an object of\r
9939                  *   parameters with the values that DataTables has readied for sending. An\r
9940                  *   object may be returned which will be merged into the DataTables\r
9941                  *   defaults, or you can add the items to the object that was passed in and\r
9942                  *   not return anything from the function. This supersedes `fnServerParams`\r
9943                  *   from DataTables 1.9-.\r
9944                  *\r
9945                  * * `dataSrc` - By default DataTables will look for the property `data` (or\r
9946                  *   `aaData` for compatibility with DataTables 1.9-) when obtaining data\r
9947                  *   from an Ajax source or for server-side processing - this parameter\r
9948                  *   allows that property to be changed. You can use Javascript dotted\r
9949                  *   object notation to get a data source for multiple levels of nesting, or\r
9950                  *   it my be used as a function. As a function it takes a single parameter,\r
9951                  *   the JSON returned from the server, which can be manipulated as\r
9952                  *   required, with the returned value being that used by DataTables as the\r
9953                  *   data source for the table. This supersedes `sAjaxDataProp` from\r
9954                  *   DataTables 1.9-.\r
9955                  *\r
9956                  * * `success` - Should not be overridden it is used internally in\r
9957                  *   DataTables. To manipulate / transform the data returned by the server\r
9958                  *   use `ajax.dataSrc`, or use `ajax` as a function (see below).\r
9959                  *\r
9960                  * `function`\r
9961                  * ----------\r
9962                  *\r
9963                  * As a function, making the Ajax call is left up to yourself allowing\r
9964                  * complete control of the Ajax request. Indeed, if desired, a method other\r
9965                  * than Ajax could be used to obtain the required data, such as Web storage\r
9966                  * or an AIR database.\r
9967                  *\r
9968                  * The function is given four parameters and no return is required. The\r
9969                  * parameters are:\r
9970                  *\r
9971                  * 1. _object_ - Data to send to the server\r
9972                  * 2. _function_ - Callback function that must be executed when the required\r
9973                  *    data has been obtained. That data should be passed into the callback\r
9974                  *    as the only parameter\r
9975                  * 3. _object_ - DataTables settings object for the table\r
9976                  *\r
9977                  * Note that this supersedes `fnServerData` from DataTables 1.9-.\r
9978                  *\r
9979                  *  @type string|object|function\r
9980                  *  @default null\r
9981                  *\r
9982                  *  @dtopt Option\r
9983                  *  @name DataTable.defaults.ajax\r
9984                  *  @since 1.10.0\r
9985                  *\r
9986                  * @example\r
9987                  *   // Get JSON data from a file via Ajax.\r
9988                  *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).\r
9989                  *   $('#example').dataTable( {\r
9990                  *     "ajax": "data.json"\r
9991                  *   } );\r
9992                  *\r
9993                  * @example\r
9994                  *   // Get JSON data from a file via Ajax, using `dataSrc` to change\r
9995                  *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)\r
9996                  *   $('#example').dataTable( {\r
9997                  *     "ajax": {\r
9998                  *       "url": "data.json",\r
9999                  *       "dataSrc": "tableData"\r
10000                  *     }\r
10001                  *   } );\r
10002                  *\r
10003                  * @example\r
10004                  *   // Get JSON data from a file via Ajax, using `dataSrc` to read data\r
10005                  *   // from a plain array rather than an array in an object\r
10006                  *   $('#example').dataTable( {\r
10007                  *     "ajax": {\r
10008                  *       "url": "data.json",\r
10009                  *       "dataSrc": ""\r
10010                  *     }\r
10011                  *   } );\r
10012                  *\r
10013                  * @example\r
10014                  *   // Manipulate the data returned from the server - add a link to data\r
10015                  *   // (note this can, should, be done using `render` for the column - this\r
10016                  *   // is just a simple example of how the data can be manipulated).\r
10017                  *   $('#example').dataTable( {\r
10018                  *     "ajax": {\r
10019                  *       "url": "data.json",\r
10020                  *       "dataSrc": function ( json ) {\r
10021                  *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {\r
10022                  *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';\r
10023                  *         }\r
10024                  *         return json;\r
10025                  *       }\r
10026                  *     }\r
10027                  *   } );\r
10028                  *\r
10029                  * @example\r
10030                  *   // Add data to the request\r
10031                  *   $('#example').dataTable( {\r
10032                  *     "ajax": {\r
10033                  *       "url": "data.json",\r
10034                  *       "data": function ( d ) {\r
10035                  *         return {\r
10036                  *           "extra_search": $('#extra').val()\r
10037                  *         };\r
10038                  *       }\r
10039                  *     }\r
10040                  *   } );\r
10041                  *\r
10042                  * @example\r
10043                  *   // Send request as POST\r
10044                  *   $('#example').dataTable( {\r
10045                  *     "ajax": {\r
10046                  *       "url": "data.json",\r
10047                  *       "type": "POST"\r
10048                  *     }\r
10049                  *   } );\r
10050                  *\r
10051                  * @example\r
10052                  *   // Get the data from localStorage (could interface with a form for\r
10053                  *   // adding, editing and removing rows).\r
10054                  *   $('#example').dataTable( {\r
10055                  *     "ajax": function (data, callback, settings) {\r
10056                  *       callback(\r
10057                  *         JSON.parse( localStorage.getItem('dataTablesData') )\r
10058                  *       );\r
10059                  *     }\r
10060                  *   } );\r
10061                  */\r
10062                 "ajax": null,\r
10063         \r
10064         \r
10065                 /**\r
10066                  * This parameter allows you to readily specify the entries in the length drop\r
10067                  * down menu that DataTables shows when pagination is enabled. It can be\r
10068                  * either a 1D array of options which will be used for both the displayed\r
10069                  * option and the value, or a 2D array which will use the array in the first\r
10070                  * position as the value, and the array in the second position as the\r
10071                  * displayed options (useful for language strings such as 'All').\r
10072                  *\r
10073                  * Note that the `pageLength` property will be automatically set to the\r
10074                  * first value given in this array, unless `pageLength` is also provided.\r
10075                  *  @type array\r
10076                  *  @default [ 10, 25, 50, 100 ]\r
10077                  *\r
10078                  *  @dtopt Option\r
10079                  *  @name DataTable.defaults.lengthMenu\r
10080                  *\r
10081                  *  @example\r
10082                  *    $(document).ready( function() {\r
10083                  *      $('#example').dataTable( {\r
10084                  *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]\r
10085                  *      } );\r
10086                  *    } );\r
10087                  */\r
10088                 "aLengthMenu": [ 10, 25, 50, 100 ],\r
10089         \r
10090         \r
10091                 /**\r
10092                  * The `columns` option in the initialisation parameter allows you to define\r
10093                  * details about the way individual columns behave. For a full list of\r
10094                  * column options that can be set, please see\r
10095                  * {@link DataTable.defaults.column}. Note that if you use `columns` to\r
10096                  * define your columns, you must have an entry in the array for every single\r
10097                  * column that you have in your table (these can be null if you don't which\r
10098                  * to specify any options).\r
10099                  *  @member\r
10100                  *\r
10101                  *  @name DataTable.defaults.column\r
10102                  */\r
10103                 "aoColumns": null,\r
10104         \r
10105                 /**\r
10106                  * Very similar to `columns`, `columnDefs` allows you to target a specific\r
10107                  * column, multiple columns, or all columns, using the `targets` property of\r
10108                  * each object in the array. This allows great flexibility when creating\r
10109                  * tables, as the `columnDefs` arrays can be of any length, targeting the\r
10110                  * columns you specifically want. `columnDefs` may use any of the column\r
10111                  * options available: {@link DataTable.defaults.column}, but it _must_\r
10112                  * have `targets` defined in each object in the array. Values in the `targets`\r
10113                  * array may be:\r
10114                  *   <ul>\r
10115                  *     <li>a string - class name will be matched on the TH for the column</li>\r
10116                  *     <li>0 or a positive integer - column index counting from the left</li>\r
10117                  *     <li>a negative integer - column index counting from the right</li>\r
10118                  *     <li>the string "_all" - all columns (i.e. assign a default)</li>\r
10119                  *   </ul>\r
10120                  *  @member\r
10121                  *\r
10122                  *  @name DataTable.defaults.columnDefs\r
10123                  */\r
10124                 "aoColumnDefs": null,\r
10125         \r
10126         \r
10127                 /**\r
10128                  * Basically the same as `search`, this parameter defines the individual column\r
10129                  * filtering state at initialisation time. The array must be of the same size\r
10130                  * as the number of columns, and each element be an object with the parameters\r
10131                  * `search` and `escapeRegex` (the latter is optional). 'null' is also\r
10132                  * accepted and the default will be used.\r
10133                  *  @type array\r
10134                  *  @default []\r
10135                  *\r
10136                  *  @dtopt Option\r
10137                  *  @name DataTable.defaults.searchCols\r
10138                  *\r
10139                  *  @example\r
10140                  *    $(document).ready( function() {\r
10141                  *      $('#example').dataTable( {\r
10142                  *        "searchCols": [\r
10143                  *          null,\r
10144                  *          { "search": "My filter" },\r
10145                  *          null,\r
10146                  *          { "search": "^[0-9]", "escapeRegex": false }\r
10147                  *        ]\r
10148                  *      } );\r
10149                  *    } )\r
10150                  */\r
10151                 "aoSearchCols": [],\r
10152         \r
10153         \r
10154                 /**\r
10155                  * An array of CSS classes that should be applied to displayed rows. This\r
10156                  * array may be of any length, and DataTables will apply each class\r
10157                  * sequentially, looping when required.\r
10158                  *  @type array\r
10159                  *  @default null <i>Will take the values determined by the `oClasses.stripe*`\r
10160                  *    options</i>\r
10161                  *\r
10162                  *  @dtopt Option\r
10163                  *  @name DataTable.defaults.stripeClasses\r
10164                  *\r
10165                  *  @example\r
10166                  *    $(document).ready( function() {\r
10167                  *      $('#example').dataTable( {\r
10168                  *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]\r
10169                  *      } );\r
10170                  *    } )\r
10171                  */\r
10172                 "asStripeClasses": null,\r
10173         \r
10174         \r
10175                 /**\r
10176                  * Enable or disable automatic column width calculation. This can be disabled\r
10177                  * as an optimisation (it takes some time to calculate the widths) if the\r
10178                  * tables widths are passed in using `columns`.\r
10179                  *  @type boolean\r
10180                  *  @default true\r
10181                  *\r
10182                  *  @dtopt Features\r
10183                  *  @name DataTable.defaults.autoWidth\r
10184                  *\r
10185                  *  @example\r
10186                  *    $(document).ready( function () {\r
10187                  *      $('#example').dataTable( {\r
10188                  *        "autoWidth": false\r
10189                  *      } );\r
10190                  *    } );\r
10191                  */\r
10192                 "bAutoWidth": true,\r
10193         \r
10194         \r
10195                 /**\r
10196                  * Deferred rendering can provide DataTables with a huge speed boost when you\r
10197                  * are using an Ajax or JS data source for the table. This option, when set to\r
10198                  * true, will cause DataTables to defer the creation of the table elements for\r
10199                  * each row until they are needed for a draw - saving a significant amount of\r
10200                  * time.\r
10201                  *  @type boolean\r
10202                  *  @default false\r
10203                  *\r
10204                  *  @dtopt Features\r
10205                  *  @name DataTable.defaults.deferRender\r
10206                  *\r
10207                  *  @example\r
10208                  *    $(document).ready( function() {\r
10209                  *      $('#example').dataTable( {\r
10210                  *        "ajax": "sources/arrays.txt",\r
10211                  *        "deferRender": true\r
10212                  *      } );\r
10213                  *    } );\r
10214                  */\r
10215                 "bDeferRender": false,\r
10216         \r
10217         \r
10218                 /**\r
10219                  * Replace a DataTable which matches the given selector and replace it with\r
10220                  * one which has the properties of the new initialisation object passed. If no\r
10221                  * table matches the selector, then the new DataTable will be constructed as\r
10222                  * per normal.\r
10223                  *  @type boolean\r
10224                  *  @default false\r
10225                  *\r
10226                  *  @dtopt Options\r
10227                  *  @name DataTable.defaults.destroy\r
10228                  *\r
10229                  *  @example\r
10230                  *    $(document).ready( function() {\r
10231                  *      $('#example').dataTable( {\r
10232                  *        "srollY": "200px",\r
10233                  *        "paginate": false\r
10234                  *      } );\r
10235                  *\r
10236                  *      // Some time later....\r
10237                  *      $('#example').dataTable( {\r
10238                  *        "filter": false,\r
10239                  *        "destroy": true\r
10240                  *      } );\r
10241                  *    } );\r
10242                  */\r
10243                 "bDestroy": false,\r
10244         \r
10245         \r
10246                 /**\r
10247                  * Enable or disable filtering of data. Filtering in DataTables is "smart" in\r
10248                  * that it allows the end user to input multiple words (space separated) and\r
10249                  * will match a row containing those words, even if not in the order that was\r
10250                  * specified (this allow matching across multiple columns). Note that if you\r
10251                  * wish to use filtering in DataTables this must remain 'true' - to remove the\r
10252                  * default filtering input box and retain filtering abilities, please use\r
10253                  * {@link DataTable.defaults.dom}.\r
10254                  *  @type boolean\r
10255                  *  @default true\r
10256                  *\r
10257                  *  @dtopt Features\r
10258                  *  @name DataTable.defaults.searching\r
10259                  *\r
10260                  *  @example\r
10261                  *    $(document).ready( function () {\r
10262                  *      $('#example').dataTable( {\r
10263                  *        "searching": false\r
10264                  *      } );\r
10265                  *    } );\r
10266                  */\r
10267                 "bFilter": true,\r
10268         \r
10269         \r
10270                 /**\r
10271                  * Enable or disable the table information display. This shows information\r
10272                  * about the data that is currently visible on the page, including information\r
10273                  * about filtered data if that action is being performed.\r
10274                  *  @type boolean\r
10275                  *  @default true\r
10276                  *\r
10277                  *  @dtopt Features\r
10278                  *  @name DataTable.defaults.info\r
10279                  *\r
10280                  *  @example\r
10281                  *    $(document).ready( function () {\r
10282                  *      $('#example').dataTable( {\r
10283                  *        "info": false\r
10284                  *      } );\r
10285                  *    } );\r
10286                  */\r
10287                 "bInfo": true,\r
10288         \r
10289         \r
10290                 /**\r
10291                  * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some\r
10292                  * slightly different and additional mark-up from what DataTables has\r
10293                  * traditionally used).\r
10294                  *  @type boolean\r
10295                  *  @default false\r
10296                  *\r
10297                  *  @dtopt Features\r
10298                  *  @name DataTable.defaults.jQueryUI\r
10299                  *\r
10300                  *  @example\r
10301                  *    $(document).ready( function() {\r
10302                  *      $('#example').dataTable( {\r
10303                  *        "jQueryUI": true\r
10304                  *      } );\r
10305                  *    } );\r
10306                  */\r
10307                 "bJQueryUI": false,\r
10308         \r
10309         \r
10310                 /**\r
10311                  * Allows the end user to select the size of a formatted page from a select\r
10312                  * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).\r
10313                  *  @type boolean\r
10314                  *  @default true\r
10315                  *\r
10316                  *  @dtopt Features\r
10317                  *  @name DataTable.defaults.lengthChange\r
10318                  *\r
10319                  *  @example\r
10320                  *    $(document).ready( function () {\r
10321                  *      $('#example').dataTable( {\r
10322                  *        "lengthChange": false\r
10323                  *      } );\r
10324                  *    } );\r
10325                  */\r
10326                 "bLengthChange": true,\r
10327         \r
10328         \r
10329                 /**\r
10330                  * Enable or disable pagination.\r
10331                  *  @type boolean\r
10332                  *  @default true\r
10333                  *\r
10334                  *  @dtopt Features\r
10335                  *  @name DataTable.defaults.paging\r
10336                  *\r
10337                  *  @example\r
10338                  *    $(document).ready( function () {\r
10339                  *      $('#example').dataTable( {\r
10340                  *        "paging": false\r
10341                  *      } );\r
10342                  *    } );\r
10343                  */\r
10344                 "bPaginate": true,\r
10345         \r
10346         \r
10347                 /**\r
10348                  * Enable or disable the display of a 'processing' indicator when the table is\r
10349                  * being processed (e.g. a sort). This is particularly useful for tables with\r
10350                  * large amounts of data where it can take a noticeable amount of time to sort\r
10351                  * the entries.\r
10352                  *  @type boolean\r
10353                  *  @default false\r
10354                  *\r
10355                  *  @dtopt Features\r
10356                  *  @name DataTable.defaults.processing\r
10357                  *\r
10358                  *  @example\r
10359                  *    $(document).ready( function () {\r
10360                  *      $('#example').dataTable( {\r
10361                  *        "processing": true\r
10362                  *      } );\r
10363                  *    } );\r
10364                  */\r
10365                 "bProcessing": false,\r
10366         \r
10367         \r
10368                 /**\r
10369                  * Retrieve the DataTables object for the given selector. Note that if the\r
10370                  * table has already been initialised, this parameter will cause DataTables\r
10371                  * to simply return the object that has already been set up - it will not take\r
10372                  * account of any changes you might have made to the initialisation object\r
10373                  * passed to DataTables (setting this parameter to true is an acknowledgement\r
10374                  * that you understand this). `destroy` can be used to reinitialise a table if\r
10375                  * you need.\r
10376                  *  @type boolean\r
10377                  *  @default false\r
10378                  *\r
10379                  *  @dtopt Options\r
10380                  *  @name DataTable.defaults.retrieve\r
10381                  *\r
10382                  *  @example\r
10383                  *    $(document).ready( function() {\r
10384                  *      initTable();\r
10385                  *      tableActions();\r
10386                  *    } );\r
10387                  *\r
10388                  *    function initTable ()\r
10389                  *    {\r
10390                  *      return $('#example').dataTable( {\r
10391                  *        "scrollY": "200px",\r
10392                  *        "paginate": false,\r
10393                  *        "retrieve": true\r
10394                  *      } );\r
10395                  *    }\r
10396                  *\r
10397                  *    function tableActions ()\r
10398                  *    {\r
10399                  *      var table = initTable();\r
10400                  *      // perform API operations with oTable\r
10401                  *    }\r
10402                  */\r
10403                 "bRetrieve": false,\r
10404         \r
10405         \r
10406                 /**\r
10407                  * When vertical (y) scrolling is enabled, DataTables will force the height of\r
10408                  * the table's viewport to the given height at all times (useful for layout).\r
10409                  * However, this can look odd when filtering data down to a small data set,\r
10410                  * and the footer is left "floating" further down. This parameter (when\r
10411                  * enabled) will cause DataTables to collapse the table's viewport down when\r
10412                  * the result set will fit within the given Y height.\r
10413                  *  @type boolean\r
10414                  *  @default false\r
10415                  *\r
10416                  *  @dtopt Options\r
10417                  *  @name DataTable.defaults.scrollCollapse\r
10418                  *\r
10419                  *  @example\r
10420                  *    $(document).ready( function() {\r
10421                  *      $('#example').dataTable( {\r
10422                  *        "scrollY": "200",\r
10423                  *        "scrollCollapse": true\r
10424                  *      } );\r
10425                  *    } );\r
10426                  */\r
10427                 "bScrollCollapse": false,\r
10428         \r
10429         \r
10430                 /**\r
10431                  * Configure DataTables to use server-side processing. Note that the\r
10432                  * `ajax` parameter must also be given in order to give DataTables a\r
10433                  * source to obtain the required data for each draw.\r
10434                  *  @type boolean\r
10435                  *  @default false\r
10436                  *\r
10437                  *  @dtopt Features\r
10438                  *  @dtopt Server-side\r
10439                  *  @name DataTable.defaults.serverSide\r
10440                  *\r
10441                  *  @example\r
10442                  *    $(document).ready( function () {\r
10443                  *      $('#example').dataTable( {\r
10444                  *        "serverSide": true,\r
10445                  *        "ajax": "xhr.php"\r
10446                  *      } );\r
10447                  *    } );\r
10448                  */\r
10449                 "bServerSide": false,\r
10450         \r
10451         \r
10452                 /**\r
10453                  * Enable or disable sorting of columns. Sorting of individual columns can be\r
10454                  * disabled by the `sortable` option for each column.\r
10455                  *  @type boolean\r
10456                  *  @default true\r
10457                  *\r
10458                  *  @dtopt Features\r
10459                  *  @name DataTable.defaults.ordering\r
10460                  *\r
10461                  *  @example\r
10462                  *    $(document).ready( function () {\r
10463                  *      $('#example').dataTable( {\r
10464                  *        "ordering": false\r
10465                  *      } );\r
10466                  *    } );\r
10467                  */\r
10468                 "bSort": true,\r
10469         \r
10470         \r
10471                 /**\r
10472                  * Enable or display DataTables' ability to sort multiple columns at the\r
10473                  * same time (activated by shift-click by the user).\r
10474                  *  @type boolean\r
10475                  *  @default true\r
10476                  *\r
10477                  *  @dtopt Options\r
10478                  *  @name DataTable.defaults.orderMulti\r
10479                  *\r
10480                  *  @example\r
10481                  *    // Disable multiple column sorting ability\r
10482                  *    $(document).ready( function () {\r
10483                  *      $('#example').dataTable( {\r
10484                  *        "orderMulti": false\r
10485                  *      } );\r
10486                  *    } );\r
10487                  */\r
10488                 "bSortMulti": true,\r
10489         \r
10490         \r
10491                 /**\r
10492                  * Allows control over whether DataTables should use the top (true) unique\r
10493                  * cell that is found for a single column, or the bottom (false - default).\r
10494                  * This is useful when using complex headers.\r
10495                  *  @type boolean\r
10496                  *  @default false\r
10497                  *\r
10498                  *  @dtopt Options\r
10499                  *  @name DataTable.defaults.orderCellsTop\r
10500                  *\r
10501                  *  @example\r
10502                  *    $(document).ready( function() {\r
10503                  *      $('#example').dataTable( {\r
10504                  *        "orderCellsTop": true\r
10505                  *      } );\r
10506                  *    } );\r
10507                  */\r
10508                 "bSortCellsTop": false,\r
10509         \r
10510         \r
10511                 /**\r
10512                  * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and\r
10513                  * `sorting\_3` to the columns which are currently being sorted on. This is\r
10514                  * presented as a feature switch as it can increase processing time (while\r
10515                  * classes are removed and added) so for large data sets you might want to\r
10516                  * turn this off.\r
10517                  *  @type boolean\r
10518                  *  @default true\r
10519                  *\r
10520                  *  @dtopt Features\r
10521                  *  @name DataTable.defaults.orderClasses\r
10522                  *\r
10523                  *  @example\r
10524                  *    $(document).ready( function () {\r
10525                  *      $('#example').dataTable( {\r
10526                  *        "orderClasses": false\r
10527                  *      } );\r
10528                  *    } );\r
10529                  */\r
10530                 "bSortClasses": true,\r
10531         \r
10532         \r
10533                 /**\r
10534                  * Enable or disable state saving. When enabled HTML5 `localStorage` will be\r
10535                  * used to save table display information such as pagination information,\r
10536                  * display length, filtering and sorting. As such when the end user reloads\r
10537                  * the page the display display will match what thy had previously set up.\r
10538                  *\r
10539                  * Due to the use of `localStorage` the default state saving is not supported\r
10540                  * in IE6 or 7. If state saving is required in those browsers, use\r
10541                  * `stateSaveCallback` to provide a storage solution such as cookies.\r
10542                  *  @type boolean\r
10543                  *  @default false\r
10544                  *\r
10545                  *  @dtopt Features\r
10546                  *  @name DataTable.defaults.stateSave\r
10547                  *\r
10548                  *  @example\r
10549                  *    $(document).ready( function () {\r
10550                  *      $('#example').dataTable( {\r
10551                  *        "stateSave": true\r
10552                  *      } );\r
10553                  *    } );\r
10554                  */\r
10555                 "bStateSave": false,\r
10556         \r
10557         \r
10558                 /**\r
10559                  * This function is called when a TR element is created (and all TD child\r
10560                  * elements have been inserted), or registered if using a DOM source, allowing\r
10561                  * manipulation of the TR element (adding classes etc).\r
10562                  *  @type function\r
10563                  *  @param {node} row "TR" element for the current row\r
10564                  *  @param {array} data Raw data array for this row\r
10565                  *  @param {int} dataIndex The index of this row in the internal aoData array\r
10566                  *\r
10567                  *  @dtopt Callbacks\r
10568                  *  @name DataTable.defaults.createdRow\r
10569                  *\r
10570                  *  @example\r
10571                  *    $(document).ready( function() {\r
10572                  *      $('#example').dataTable( {\r
10573                  *        "createdRow": function( row, data, dataIndex ) {\r
10574                  *          // Bold the grade for all 'A' grade browsers\r
10575                  *          if ( data[4] == "A" )\r
10576                  *          {\r
10577                  *            $('td:eq(4)', row).html( '<b>A</b>' );\r
10578                  *          }\r
10579                  *        }\r
10580                  *      } );\r
10581                  *    } );\r
10582                  */\r
10583                 "fnCreatedRow": null,\r
10584         \r
10585         \r
10586                 /**\r
10587                  * This function is called on every 'draw' event, and allows you to\r
10588                  * dynamically modify any aspect you want about the created DOM.\r
10589                  *  @type function\r
10590                  *  @param {object} settings DataTables settings object\r
10591                  *\r
10592                  *  @dtopt Callbacks\r
10593                  *  @name DataTable.defaults.drawCallback\r
10594                  *\r
10595                  *  @example\r
10596                  *    $(document).ready( function() {\r
10597                  *      $('#example').dataTable( {\r
10598                  *        "drawCallback": function( settings ) {\r
10599                  *          alert( 'DataTables has redrawn the table' );\r
10600                  *        }\r
10601                  *      } );\r
10602                  *    } );\r
10603                  */\r
10604                 "fnDrawCallback": null,\r
10605         \r
10606         \r
10607                 /**\r
10608                  * Identical to fnHeaderCallback() but for the table footer this function\r
10609                  * allows you to modify the table footer on every 'draw' event.\r
10610                  *  @type function\r
10611                  *  @param {node} foot "TR" element for the footer\r
10612                  *  @param {array} data Full table data (as derived from the original HTML)\r
10613                  *  @param {int} start Index for the current display starting point in the\r
10614                  *    display array\r
10615                  *  @param {int} end Index for the current display ending point in the\r
10616                  *    display array\r
10617                  *  @param {array int} display Index array to translate the visual position\r
10618                  *    to the full data array\r
10619                  *\r
10620                  *  @dtopt Callbacks\r
10621                  *  @name DataTable.defaults.footerCallback\r
10622                  *\r
10623                  *  @example\r
10624                  *    $(document).ready( function() {\r
10625                  *      $('#example').dataTable( {\r
10626                  *        "footerCallback": function( tfoot, data, start, end, display ) {\r
10627                  *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;\r
10628                  *        }\r
10629                  *      } );\r
10630                  *    } )\r
10631                  */\r
10632                 "fnFooterCallback": null,\r
10633         \r
10634         \r
10635                 /**\r
10636                  * When rendering large numbers in the information element for the table\r
10637                  * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers\r
10638                  * to have a comma separator for the 'thousands' units (e.g. 1 million is\r
10639                  * rendered as "1,000,000") to help readability for the end user. This\r
10640                  * function will override the default method DataTables uses.\r
10641                  *  @type function\r
10642                  *  @member\r
10643                  *  @param {int} toFormat number to be formatted\r
10644                  *  @returns {string} formatted string for DataTables to show the number\r
10645                  *\r
10646                  *  @dtopt Callbacks\r
10647                  *  @name DataTable.defaults.formatNumber\r
10648                  *\r
10649                  *  @example\r
10650                  *    // Format a number using a single quote for the separator (note that\r
10651                  *    // this can also be done with the language.thousands option)\r
10652                  *    $(document).ready( function() {\r
10653                  *      $('#example').dataTable( {\r
10654                  *        "formatNumber": function ( toFormat ) {\r
10655                  *          return toFormat.toString().replace(\r
10656                  *            /\B(?=(\d{3})+(?!\d))/g, "'"\r
10657                  *          );\r
10658                  *        };\r
10659                  *      } );\r
10660                  *    } );\r
10661                  */\r
10662                 "fnFormatNumber": function ( toFormat ) {\r
10663                         return toFormat.toString().replace(\r
10664                                 /\B(?=(\d{3})+(?!\d))/g,\r
10665                                 this.oLanguage.sThousands\r
10666                         );\r
10667                 },\r
10668         \r
10669         \r
10670                 /**\r
10671                  * This function is called on every 'draw' event, and allows you to\r
10672                  * dynamically modify the header row. This can be used to calculate and\r
10673                  * display useful information about the table.\r
10674                  *  @type function\r
10675                  *  @param {node} head "TR" element for the header\r
10676                  *  @param {array} data Full table data (as derived from the original HTML)\r
10677                  *  @param {int} start Index for the current display starting point in the\r
10678                  *    display array\r
10679                  *  @param {int} end Index for the current display ending point in the\r
10680                  *    display array\r
10681                  *  @param {array int} display Index array to translate the visual position\r
10682                  *    to the full data array\r
10683                  *\r
10684                  *  @dtopt Callbacks\r
10685                  *  @name DataTable.defaults.headerCallback\r
10686                  *\r
10687                  *  @example\r
10688                  *    $(document).ready( function() {\r
10689                  *      $('#example').dataTable( {\r
10690                  *        "fheaderCallback": function( head, data, start, end, display ) {\r
10691                  *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";\r
10692                  *        }\r
10693                  *      } );\r
10694                  *    } )\r
10695                  */\r
10696                 "fnHeaderCallback": null,\r
10697         \r
10698         \r
10699                 /**\r
10700                  * The information element can be used to convey information about the current\r
10701                  * state of the table. Although the internationalisation options presented by\r
10702                  * DataTables are quite capable of dealing with most customisations, there may\r
10703                  * be times where you wish to customise the string further. This callback\r
10704                  * allows you to do exactly that.\r
10705                  *  @type function\r
10706                  *  @param {object} oSettings DataTables settings object\r
10707                  *  @param {int} start Starting position in data for the draw\r
10708                  *  @param {int} end End position in data for the draw\r
10709                  *  @param {int} max Total number of rows in the table (regardless of\r
10710                  *    filtering)\r
10711                  *  @param {int} total Total number of rows in the data set, after filtering\r
10712                  *  @param {string} pre The string that DataTables has formatted using it's\r
10713                  *    own rules\r
10714                  *  @returns {string} The string to be displayed in the information element.\r
10715                  *\r
10716                  *  @dtopt Callbacks\r
10717                  *  @name DataTable.defaults.infoCallback\r
10718                  *\r
10719                  *  @example\r
10720                  *    $('#example').dataTable( {\r
10721                  *      "infoCallback": function( settings, start, end, max, total, pre ) {\r
10722                  *        return start +" to "+ end;\r
10723                  *      }\r
10724                  *    } );\r
10725                  */\r
10726                 "fnInfoCallback": null,\r
10727         \r
10728         \r
10729                 /**\r
10730                  * Called when the table has been initialised. Normally DataTables will\r
10731                  * initialise sequentially and there will be no need for this function,\r
10732                  * however, this does not hold true when using external language information\r
10733                  * since that is obtained using an async XHR call.\r
10734                  *  @type function\r
10735                  *  @param {object} settings DataTables settings object\r
10736                  *  @param {object} json The JSON object request from the server - only\r
10737                  *    present if client-side Ajax sourced data is used\r
10738                  *\r
10739                  *  @dtopt Callbacks\r
10740                  *  @name DataTable.defaults.initComplete\r
10741                  *\r
10742                  *  @example\r
10743                  *    $(document).ready( function() {\r
10744                  *      $('#example').dataTable( {\r
10745                  *        "initComplete": function(settings, json) {\r
10746                  *          alert( 'DataTables has finished its initialisation.' );\r
10747                  *        }\r
10748                  *      } );\r
10749                  *    } )\r
10750                  */\r
10751                 "fnInitComplete": null,\r
10752         \r
10753         \r
10754                 /**\r
10755                  * Called at the very start of each table draw and can be used to cancel the\r
10756                  * draw by returning false, any other return (including undefined) results in\r
10757                  * the full draw occurring).\r
10758                  *  @type function\r
10759                  *  @param {object} settings DataTables settings object\r
10760                  *  @returns {boolean} False will cancel the draw, anything else (including no\r
10761                  *    return) will allow it to complete.\r
10762                  *\r
10763                  *  @dtopt Callbacks\r
10764                  *  @name DataTable.defaults.preDrawCallback\r
10765                  *\r
10766                  *  @example\r
10767                  *    $(document).ready( function() {\r
10768                  *      $('#example').dataTable( {\r
10769                  *        "preDrawCallback": function( settings ) {\r
10770                  *          if ( $('#test').val() == 1 ) {\r
10771                  *            return false;\r
10772                  *          }\r
10773                  *        }\r
10774                  *      } );\r
10775                  *    } );\r
10776                  */\r
10777                 "fnPreDrawCallback": null,\r
10778         \r
10779         \r
10780                 /**\r
10781                  * This function allows you to 'post process' each row after it have been\r
10782                  * generated for each table draw, but before it is rendered on screen. This\r
10783                  * function might be used for setting the row class name etc.\r
10784                  *  @type function\r
10785                  *  @param {node} row "TR" element for the current row\r
10786                  *  @param {array} data Raw data array for this row\r
10787                  *  @param {int} displayIndex The display index for the current table draw\r
10788                  *  @param {int} displayIndexFull The index of the data in the full list of\r
10789                  *    rows (after filtering)\r
10790                  *\r
10791                  *  @dtopt Callbacks\r
10792                  *  @name DataTable.defaults.rowCallback\r
10793                  *\r
10794                  *  @example\r
10795                  *    $(document).ready( function() {\r
10796                  *      $('#example').dataTable( {\r
10797                  *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {\r
10798                  *          // Bold the grade for all 'A' grade browsers\r
10799                  *          if ( data[4] == "A" ) {\r
10800                  *            $('td:eq(4)', row).html( '<b>A</b>' );\r
10801                  *          }\r
10802                  *        }\r
10803                  *      } );\r
10804                  *    } );\r
10805                  */\r
10806                 "fnRowCallback": null,\r
10807         \r
10808         \r
10809                 /**\r
10810                  * __Deprecated__ The functionality provided by this parameter has now been\r
10811                  * superseded by that provided through `ajax`, which should be used instead.\r
10812                  *\r
10813                  * This parameter allows you to override the default function which obtains\r
10814                  * the data from the server so something more suitable for your application.\r
10815                  * For example you could use POST data, or pull information from a Gears or\r
10816                  * AIR database.\r
10817                  *  @type function\r
10818                  *  @member\r
10819                  *  @param {string} source HTTP source to obtain the data from (`ajax`)\r
10820                  *  @param {array} data A key/value pair object containing the data to send\r
10821                  *    to the server\r
10822                  *  @param {function} callback to be called on completion of the data get\r
10823                  *    process that will draw the data on the page.\r
10824                  *  @param {object} settings DataTables settings object\r
10825                  *\r
10826                  *  @dtopt Callbacks\r
10827                  *  @dtopt Server-side\r
10828                  *  @name DataTable.defaults.serverData\r
10829                  *\r
10830                  *  @deprecated 1.10. Please use `ajax` for this functionality now.\r
10831                  */\r
10832                 "fnServerData": null,\r
10833         \r
10834         \r
10835                 /**\r
10836                  * __Deprecated__ The functionality provided by this parameter has now been\r
10837                  * superseded by that provided through `ajax`, which should be used instead.\r
10838                  *\r
10839                  *  It is often useful to send extra data to the server when making an Ajax\r
10840                  * request - for example custom filtering information, and this callback\r
10841                  * function makes it trivial to send extra information to the server. The\r
10842                  * passed in parameter is the data set that has been constructed by\r
10843                  * DataTables, and you can add to this or modify it as you require.\r
10844                  *  @type function\r
10845                  *  @param {array} data Data array (array of objects which are name/value\r
10846                  *    pairs) that has been constructed by DataTables and will be sent to the\r
10847                  *    server. In the case of Ajax sourced data with server-side processing\r
10848                  *    this will be an empty array, for server-side processing there will be a\r
10849                  *    significant number of parameters!\r
10850                  *  @returns {undefined} Ensure that you modify the data array passed in,\r
10851                  *    as this is passed by reference.\r
10852                  *\r
10853                  *  @dtopt Callbacks\r
10854                  *  @dtopt Server-side\r
10855                  *  @name DataTable.defaults.serverParams\r
10856                  *\r
10857                  *  @deprecated 1.10. Please use `ajax` for this functionality now.\r
10858                  */\r
10859                 "fnServerParams": null,\r
10860         \r
10861         \r
10862                 /**\r
10863                  * Load the table state. With this function you can define from where, and how, the\r
10864                  * state of a table is loaded. By default DataTables will load from `localStorage`\r
10865                  * but you might wish to use a server-side database or cookies.\r
10866                  *  @type function\r
10867                  *  @member\r
10868                  *  @param {object} settings DataTables settings object\r
10869                  *  @return {object} The DataTables state object to be loaded\r
10870                  *\r
10871                  *  @dtopt Callbacks\r
10872                  *  @name DataTable.defaults.stateLoadCallback\r
10873                  *\r
10874                  *  @example\r
10875                  *    $(document).ready( function() {\r
10876                  *      $('#example').dataTable( {\r
10877                  *        "stateSave": true,\r
10878                  *        "stateLoadCallback": function (settings) {\r
10879                  *          var o;\r
10880                  *\r
10881                  *          // Send an Ajax request to the server to get the data. Note that\r
10882                  *          // this is a synchronous request.\r
10883                  *          $.ajax( {\r
10884                  *            "url": "/state_load",\r
10885                  *            "async": false,\r
10886                  *            "dataType": "json",\r
10887                  *            "success": function (json) {\r
10888                  *              o = json;\r
10889                  *            }\r
10890                  *          } );\r
10891                  *\r
10892                  *          return o;\r
10893                  *        }\r
10894                  *      } );\r
10895                  *    } );\r
10896                  */\r
10897                 "fnStateLoadCallback": function ( settings ) {\r
10898                         try {\r
10899                                 return JSON.parse(\r
10900                                         (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(\r
10901                                                 'DataTables_'+settings.sInstance+'_'+location.pathname\r
10902                                         )\r
10903                                 );\r
10904                         } catch (e) {}\r
10905                 },\r
10906         \r
10907         \r
10908                 /**\r
10909                  * Callback which allows modification of the saved state prior to loading that state.\r
10910                  * This callback is called when the table is loading state from the stored data, but\r
10911                  * prior to the settings object being modified by the saved state. Note that for\r
10912                  * plug-in authors, you should use the `stateLoadParams` event to load parameters for\r
10913                  * a plug-in.\r
10914                  *  @type function\r
10915                  *  @param {object} settings DataTables settings object\r
10916                  *  @param {object} data The state object that is to be loaded\r
10917                  *\r
10918                  *  @dtopt Callbacks\r
10919                  *  @name DataTable.defaults.stateLoadParams\r
10920                  *\r
10921                  *  @example\r
10922                  *    // Remove a saved filter, so filtering is never loaded\r
10923                  *    $(document).ready( function() {\r
10924                  *      $('#example').dataTable( {\r
10925                  *        "stateSave": true,\r
10926                  *        "stateLoadParams": function (settings, data) {\r
10927                  *          data.oSearch.sSearch = "";\r
10928                  *        }\r
10929                  *      } );\r
10930                  *    } );\r
10931                  *\r
10932                  *  @example\r
10933                  *    // Disallow state loading by returning false\r
10934                  *    $(document).ready( function() {\r
10935                  *      $('#example').dataTable( {\r
10936                  *        "stateSave": true,\r
10937                  *        "stateLoadParams": function (settings, data) {\r
10938                  *          return false;\r
10939                  *        }\r
10940                  *      } );\r
10941                  *    } );\r
10942                  */\r
10943                 "fnStateLoadParams": null,\r
10944         \r
10945         \r
10946                 /**\r
10947                  * Callback that is called when the state has been loaded from the state saving method\r
10948                  * and the DataTables settings object has been modified as a result of the loaded state.\r
10949                  *  @type function\r
10950                  *  @param {object} settings DataTables settings object\r
10951                  *  @param {object} data The state object that was loaded\r
10952                  *\r
10953                  *  @dtopt Callbacks\r
10954                  *  @name DataTable.defaults.stateLoaded\r
10955                  *\r
10956                  *  @example\r
10957                  *    // Show an alert with the filtering value that was saved\r
10958                  *    $(document).ready( function() {\r
10959                  *      $('#example').dataTable( {\r
10960                  *        "stateSave": true,\r
10961                  *        "stateLoaded": function (settings, data) {\r
10962                  *          alert( 'Saved filter was: '+data.oSearch.sSearch );\r
10963                  *        }\r
10964                  *      } );\r
10965                  *    } );\r
10966                  */\r
10967                 "fnStateLoaded": null,\r
10968         \r
10969         \r
10970                 /**\r
10971                  * Save the table state. This function allows you to define where and how the state\r
10972                  * information for the table is stored By default DataTables will use `localStorage`\r
10973                  * but you might wish to use a server-side database or cookies.\r
10974                  *  @type function\r
10975                  *  @member\r
10976                  *  @param {object} settings DataTables settings object\r
10977                  *  @param {object} data The state object to be saved\r
10978                  *\r
10979                  *  @dtopt Callbacks\r
10980                  *  @name DataTable.defaults.stateSaveCallback\r
10981                  *\r
10982                  *  @example\r
10983                  *    $(document).ready( function() {\r
10984                  *      $('#example').dataTable( {\r
10985                  *        "stateSave": true,\r
10986                  *        "stateSaveCallback": function (settings, data) {\r
10987                  *          // Send an Ajax request to the server with the state object\r
10988                  *          $.ajax( {\r
10989                  *            "url": "/state_save",\r
10990                  *            "data": data,\r
10991                  *            "dataType": "json",\r
10992                  *            "method": "POST"\r
10993                  *            "success": function () {}\r
10994                  *          } );\r
10995                  *        }\r
10996                  *      } );\r
10997                  *    } );\r
10998                  */\r
10999                 "fnStateSaveCallback": function ( settings, data ) {\r
11000                         try {\r
11001                                 (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(\r
11002                                         'DataTables_'+settings.sInstance+'_'+location.pathname,\r
11003                                         JSON.stringify( data )\r
11004                                 );\r
11005                         } catch (e) {}\r
11006                 },\r
11007         \r
11008         \r
11009                 /**\r
11010                  * Callback which allows modification of the state to be saved. Called when the table\r
11011                  * has changed state a new state save is required. This method allows modification of\r
11012                  * the state saving object prior to actually doing the save, including addition or\r
11013                  * other state properties or modification. Note that for plug-in authors, you should\r
11014                  * use the `stateSaveParams` event to save parameters for a plug-in.\r
11015                  *  @type function\r
11016                  *  @param {object} settings DataTables settings object\r
11017                  *  @param {object} data The state object to be saved\r
11018                  *\r
11019                  *  @dtopt Callbacks\r
11020                  *  @name DataTable.defaults.stateSaveParams\r
11021                  *\r
11022                  *  @example\r
11023                  *    // Remove a saved filter, so filtering is never saved\r
11024                  *    $(document).ready( function() {\r
11025                  *      $('#example').dataTable( {\r
11026                  *        "stateSave": true,\r
11027                  *        "stateSaveParams": function (settings, data) {\r
11028                  *          data.oSearch.sSearch = "";\r
11029                  *        }\r
11030                  *      } );\r
11031                  *    } );\r
11032                  */\r
11033                 "fnStateSaveParams": null,\r
11034         \r
11035         \r
11036                 /**\r
11037                  * Duration for which the saved state information is considered valid. After this period\r
11038                  * has elapsed the state will be returned to the default.\r
11039                  * Value is given in seconds.\r
11040                  *  @type int\r
11041                  *  @default 7200 <i>(2 hours)</i>\r
11042                  *\r
11043                  *  @dtopt Options\r
11044                  *  @name DataTable.defaults.stateDuration\r
11045                  *\r
11046                  *  @example\r
11047                  *    $(document).ready( function() {\r
11048                  *      $('#example').dataTable( {\r
11049                  *        "stateDuration": 60*60*24; // 1 day\r
11050                  *      } );\r
11051                  *    } )\r
11052                  */\r
11053                 "iStateDuration": 7200,\r
11054         \r
11055         \r
11056                 /**\r
11057                  * When enabled DataTables will not make a request to the server for the first\r
11058                  * page draw - rather it will use the data already on the page (no sorting etc\r
11059                  * will be applied to it), thus saving on an XHR at load time. `deferLoading`\r
11060                  * is used to indicate that deferred loading is required, but it is also used\r
11061                  * to tell DataTables how many records there are in the full table (allowing\r
11062                  * the information element and pagination to be displayed correctly). In the case\r
11063                  * where a filtering is applied to the table on initial load, this can be\r
11064                  * indicated by giving the parameter as an array, where the first element is\r
11065                  * the number of records available after filtering and the second element is the\r
11066                  * number of records without filtering (allowing the table information element\r
11067                  * to be shown correctly).\r
11068                  *  @type int | array\r
11069                  *  @default null\r
11070                  *\r
11071                  *  @dtopt Options\r
11072                  *  @name DataTable.defaults.deferLoading\r
11073                  *\r
11074                  *  @example\r
11075                  *    // 57 records available in the table, no filtering applied\r
11076                  *    $(document).ready( function() {\r
11077                  *      $('#example').dataTable( {\r
11078                  *        "serverSide": true,\r
11079                  *        "ajax": "scripts/server_processing.php",\r
11080                  *        "deferLoading": 57\r
11081                  *      } );\r
11082                  *    } );\r
11083                  *\r
11084                  *  @example\r
11085                  *    // 57 records after filtering, 100 without filtering (an initial filter applied)\r
11086                  *    $(document).ready( function() {\r
11087                  *      $('#example').dataTable( {\r
11088                  *        "serverSide": true,\r
11089                  *        "ajax": "scripts/server_processing.php",\r
11090                  *        "deferLoading": [ 57, 100 ],\r
11091                  *        "search": {\r
11092                  *          "search": "my_filter"\r
11093                  *        }\r
11094                  *      } );\r
11095                  *    } );\r
11096                  */\r
11097                 "iDeferLoading": null,\r
11098         \r
11099         \r
11100                 /**\r
11101                  * Number of rows to display on a single page when using pagination. If\r
11102                  * feature enabled (`lengthChange`) then the end user will be able to override\r
11103                  * this to a custom setting using a pop-up menu.\r
11104                  *  @type int\r
11105                  *  @default 10\r
11106                  *\r
11107                  *  @dtopt Options\r
11108                  *  @name DataTable.defaults.pageLength\r
11109                  *\r
11110                  *  @example\r
11111                  *    $(document).ready( function() {\r
11112                  *      $('#example').dataTable( {\r
11113                  *        "pageLength": 50\r
11114                  *      } );\r
11115                  *    } )\r
11116                  */\r
11117                 "iDisplayLength": 10,\r
11118         \r
11119         \r
11120                 /**\r
11121                  * Define the starting point for data display when using DataTables with\r
11122                  * pagination. Note that this parameter is the number of records, rather than\r
11123                  * the page number, so if you have 10 records per page and want to start on\r
11124                  * the third page, it should be "20".\r
11125                  *  @type int\r
11126                  *  @default 0\r
11127                  *\r
11128                  *  @dtopt Options\r
11129                  *  @name DataTable.defaults.displayStart\r
11130                  *\r
11131                  *  @example\r
11132                  *    $(document).ready( function() {\r
11133                  *      $('#example').dataTable( {\r
11134                  *        "displayStart": 20\r
11135                  *      } );\r
11136                  *    } )\r
11137                  */\r
11138                 "iDisplayStart": 0,\r
11139         \r
11140         \r
11141                 /**\r
11142                  * By default DataTables allows keyboard navigation of the table (sorting, paging,\r
11143                  * and filtering) by adding a `tabindex` attribute to the required elements. This\r
11144                  * allows you to tab through the controls and press the enter key to activate them.\r
11145                  * The tabindex is default 0, meaning that the tab follows the flow of the document.\r
11146                  * You can overrule this using this parameter if you wish. Use a value of -1 to\r
11147                  * disable built-in keyboard navigation.\r
11148                  *  @type int\r
11149                  *  @default 0\r
11150                  *\r
11151                  *  @dtopt Options\r
11152                  *  @name DataTable.defaults.tabIndex\r
11153                  *\r
11154                  *  @example\r
11155                  *    $(document).ready( function() {\r
11156                  *      $('#example').dataTable( {\r
11157                  *        "tabIndex": 1\r
11158                  *      } );\r
11159                  *    } );\r
11160                  */\r
11161                 "iTabIndex": 0,\r
11162         \r
11163         \r
11164                 /**\r
11165                  * Classes that DataTables assigns to the various components and features\r
11166                  * that it adds to the HTML table. This allows classes to be configured\r
11167                  * during initialisation in addition to through the static\r
11168                  * {@link DataTable.ext.oStdClasses} object).\r
11169                  *  @namespace\r
11170                  *  @name DataTable.defaults.classes\r
11171                  */\r
11172                 "oClasses": {},\r
11173         \r
11174         \r
11175                 /**\r
11176                  * All strings that DataTables uses in the user interface that it creates\r
11177                  * are defined in this object, allowing you to modified them individually or\r
11178                  * completely replace them all as required.\r
11179                  *  @namespace\r
11180                  *  @name DataTable.defaults.language\r
11181                  */\r
11182                 "oLanguage": {\r
11183                         /**\r
11184                          * Strings that are used for WAI-ARIA labels and controls only (these are not\r
11185                          * actually visible on the page, but will be read by screenreaders, and thus\r
11186                          * must be internationalised as well).\r
11187                          *  @namespace\r
11188                          *  @name DataTable.defaults.language.aria\r
11189                          */\r
11190                         "oAria": {\r
11191                                 /**\r
11192                                  * ARIA label that is added to the table headers when the column may be\r
11193                                  * sorted ascending by activing the column (click or return when focused).\r
11194                                  * Note that the column header is prefixed to this string.\r
11195                                  *  @type string\r
11196                                  *  @default : activate to sort column ascending\r
11197                                  *\r
11198                                  *  @dtopt Language\r
11199                                  *  @name DataTable.defaults.language.aria.sortAscending\r
11200                                  *\r
11201                                  *  @example\r
11202                                  *    $(document).ready( function() {\r
11203                                  *      $('#example').dataTable( {\r
11204                                  *        "language": {\r
11205                                  *          "aria": {\r
11206                                  *            "sortAscending": " - click/return to sort ascending"\r
11207                                  *          }\r
11208                                  *        }\r
11209                                  *      } );\r
11210                                  *    } );\r
11211                                  */\r
11212                                 "sSortAscending": ": activate to sort column ascending",\r
11213         \r
11214                                 /**\r
11215                                  * ARIA label that is added to the table headers when the column may be\r
11216                                  * sorted descending by activing the column (click or return when focused).\r
11217                                  * Note that the column header is prefixed to this string.\r
11218                                  *  @type string\r
11219                                  *  @default : activate to sort column ascending\r
11220                                  *\r
11221                                  *  @dtopt Language\r
11222                                  *  @name DataTable.defaults.language.aria.sortDescending\r
11223                                  *\r
11224                                  *  @example\r
11225                                  *    $(document).ready( function() {\r
11226                                  *      $('#example').dataTable( {\r
11227                                  *        "language": {\r
11228                                  *          "aria": {\r
11229                                  *            "sortDescending": " - click/return to sort descending"\r
11230                                  *          }\r
11231                                  *        }\r
11232                                  *      } );\r
11233                                  *    } );\r
11234                                  */\r
11235                                 "sSortDescending": ": activate to sort column descending"\r
11236                         },\r
11237         \r
11238                         /**\r
11239                          * Pagination string used by DataTables for the built-in pagination\r
11240                          * control types.\r
11241                          *  @namespace\r
11242                          *  @name DataTable.defaults.language.paginate\r
11243                          */\r
11244                         "oPaginate": {\r
11245                                 /**\r
11246                                  * Text to use when using the 'full_numbers' type of pagination for the\r
11247                                  * button to take the user to the first page.\r
11248                                  *  @type string\r
11249                                  *  @default First\r
11250                                  *\r
11251                                  *  @dtopt Language\r
11252                                  *  @name DataTable.defaults.language.paginate.first\r
11253                                  *\r
11254                                  *  @example\r
11255                                  *    $(document).ready( function() {\r
11256                                  *      $('#example').dataTable( {\r
11257                                  *        "language": {\r
11258                                  *          "paginate": {\r
11259                                  *            "first": "First page"\r
11260                                  *          }\r
11261                                  *        }\r
11262                                  *      } );\r
11263                                  *    } );\r
11264                                  */\r
11265                                 "sFirst": "First",\r
11266         \r
11267         \r
11268                                 /**\r
11269                                  * Text to use when using the 'full_numbers' type of pagination for the\r
11270                                  * button to take the user to the last page.\r
11271                                  *  @type string\r
11272                                  *  @default Last\r
11273                                  *\r
11274                                  *  @dtopt Language\r
11275                                  *  @name DataTable.defaults.language.paginate.last\r
11276                                  *\r
11277                                  *  @example\r
11278                                  *    $(document).ready( function() {\r
11279                                  *      $('#example').dataTable( {\r
11280                                  *        "language": {\r
11281                                  *          "paginate": {\r
11282                                  *            "last": "Last page"\r
11283                                  *          }\r
11284                                  *        }\r
11285                                  *      } );\r
11286                                  *    } );\r
11287                                  */\r
11288                                 "sLast": "Last",\r
11289         \r
11290         \r
11291                                 /**\r
11292                                  * Text to use for the 'next' pagination button (to take the user to the\r
11293                                  * next page).\r
11294                                  *  @type string\r
11295                                  *  @default Next\r
11296                                  *\r
11297                                  *  @dtopt Language\r
11298                                  *  @name DataTable.defaults.language.paginate.next\r
11299                                  *\r
11300                                  *  @example\r
11301                                  *    $(document).ready( function() {\r
11302                                  *      $('#example').dataTable( {\r
11303                                  *        "language": {\r
11304                                  *          "paginate": {\r
11305                                  *            "next": "Next page"\r
11306                                  *          }\r
11307                                  *        }\r
11308                                  *      } );\r
11309                                  *    } );\r
11310                                  */\r
11311                                 "sNext": "Next",\r
11312         \r
11313         \r
11314                                 /**\r
11315                                  * Text to use for the 'previous' pagination button (to take the user to\r
11316                                  * the previous page).\r
11317                                  *  @type string\r
11318                                  *  @default Previous\r
11319                                  *\r
11320                                  *  @dtopt Language\r
11321                                  *  @name DataTable.defaults.language.paginate.previous\r
11322                                  *\r
11323                                  *  @example\r
11324                                  *    $(document).ready( function() {\r
11325                                  *      $('#example').dataTable( {\r
11326                                  *        "language": {\r
11327                                  *          "paginate": {\r
11328                                  *            "previous": "Previous page"\r
11329                                  *          }\r
11330                                  *        }\r
11331                                  *      } );\r
11332                                  *    } );\r
11333                                  */\r
11334                                 "sPrevious": "Previous"\r
11335                         },\r
11336         \r
11337                         /**\r
11338                          * This string is shown in preference to `zeroRecords` when the table is\r
11339                          * empty of data (regardless of filtering). Note that this is an optional\r
11340                          * parameter - if it is not given, the value of `zeroRecords` will be used\r
11341                          * instead (either the default or given value).\r
11342                          *  @type string\r
11343                          *  @default No data available in table\r
11344                          *\r
11345                          *  @dtopt Language\r
11346                          *  @name DataTable.defaults.language.emptyTable\r
11347                          *\r
11348                          *  @example\r
11349                          *    $(document).ready( function() {\r
11350                          *      $('#example').dataTable( {\r
11351                          *        "language": {\r
11352                          *          "emptyTable": "No data available in table"\r
11353                          *        }\r
11354                          *      } );\r
11355                          *    } );\r
11356                          */\r
11357                         "sEmptyTable": "No data available in table",\r
11358         \r
11359         \r
11360                         /**\r
11361                          * This string gives information to the end user about the information\r
11362                          * that is current on display on the page. The following tokens can be\r
11363                          * used in the string and will be dynamically replaced as the table\r
11364                          * display updates. This tokens can be placed anywhere in the string, or\r
11365                          * removed as needed by the language requires:\r
11366                          *\r
11367                          * * `\_START\_` - Display index of the first record on the current page\r
11368                          * * `\_END\_` - Display index of the last record on the current page\r
11369                          * * `\_TOTAL\_` - Number of records in the table after filtering\r
11370                          * * `\_MAX\_` - Number of records in the table without filtering\r
11371                          * * `\_PAGE\_` - Current page number\r
11372                          * * `\_PAGES\_` - Total number of pages of data in the table\r
11373                          *\r
11374                          *  @type string\r
11375                          *  @default Showing _START_ to _END_ of _TOTAL_ entries\r
11376                          *\r
11377                          *  @dtopt Language\r
11378                          *  @name DataTable.defaults.language.info\r
11379                          *\r
11380                          *  @example\r
11381                          *    $(document).ready( function() {\r
11382                          *      $('#example').dataTable( {\r
11383                          *        "language": {\r
11384                          *          "info": "Showing page _PAGE_ of _PAGES_"\r
11385                          *        }\r
11386                          *      } );\r
11387                          *    } );\r
11388                          */\r
11389                         "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",\r
11390         \r
11391         \r
11392                         /**\r
11393                          * Display information string for when the table is empty. Typically the\r
11394                          * format of this string should match `info`.\r
11395                          *  @type string\r
11396                          *  @default Showing 0 to 0 of 0 entries\r
11397                          *\r
11398                          *  @dtopt Language\r
11399                          *  @name DataTable.defaults.language.infoEmpty\r
11400                          *\r
11401                          *  @example\r
11402                          *    $(document).ready( function() {\r
11403                          *      $('#example').dataTable( {\r
11404                          *        "language": {\r
11405                          *          "infoEmpty": "No entries to show"\r
11406                          *        }\r
11407                          *      } );\r
11408                          *    } );\r
11409                          */\r
11410                         "sInfoEmpty": "Showing 0 to 0 of 0 entries",\r
11411         \r
11412         \r
11413                         /**\r
11414                          * When a user filters the information in a table, this string is appended\r
11415                          * to the information (`info`) to give an idea of how strong the filtering\r
11416                          * is. The variable _MAX_ is dynamically updated.\r
11417                          *  @type string\r
11418                          *  @default (filtered from _MAX_ total entries)\r
11419                          *\r
11420                          *  @dtopt Language\r
11421                          *  @name DataTable.defaults.language.infoFiltered\r
11422                          *\r
11423                          *  @example\r
11424                          *    $(document).ready( function() {\r
11425                          *      $('#example').dataTable( {\r
11426                          *        "language": {\r
11427                          *          "infoFiltered": " - filtering from _MAX_ records"\r
11428                          *        }\r
11429                          *      } );\r
11430                          *    } );\r
11431                          */\r
11432                         "sInfoFiltered": "(filtered from _MAX_ total entries)",\r
11433         \r
11434         \r
11435                         /**\r
11436                          * If can be useful to append extra information to the info string at times,\r
11437                          * and this variable does exactly that. This information will be appended to\r
11438                          * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are\r
11439                          * being used) at all times.\r
11440                          *  @type string\r
11441                          *  @default <i>Empty string</i>\r
11442                          *\r
11443                          *  @dtopt Language\r
11444                          *  @name DataTable.defaults.language.infoPostFix\r
11445                          *\r
11446                          *  @example\r
11447                          *    $(document).ready( function() {\r
11448                          *      $('#example').dataTable( {\r
11449                          *        "language": {\r
11450                          *          "infoPostFix": "All records shown are derived from real information."\r
11451                          *        }\r
11452                          *      } );\r
11453                          *    } );\r
11454                          */\r
11455                         "sInfoPostFix": "",\r
11456         \r
11457         \r
11458                         /**\r
11459                          * This decimal place operator is a little different from the other\r
11460                          * language options since DataTables doesn't output floating point\r
11461                          * numbers, so it won't ever use this for display of a number. Rather,\r
11462                          * what this parameter does is modify the sort methods of the table so\r
11463                          * that numbers which are in a format which has a character other than\r
11464                          * a period (`.`) as a decimal place will be sorted numerically.\r
11465                          *\r
11466                          * Note that numbers with different decimal places cannot be shown in\r
11467                          * the same table and still be sortable, the table must be consistent.\r
11468                          * However, multiple different tables on the page can use different\r
11469                          * decimal place characters.\r
11470                          *  @type string\r
11471                          *  @default \r
11472                          *\r
11473                          *  @dtopt Language\r
11474                          *  @name DataTable.defaults.language.decimal\r
11475                          *\r
11476                          *  @example\r
11477                          *    $(document).ready( function() {\r
11478                          *      $('#example').dataTable( {\r
11479                          *        "language": {\r
11480                          *          "decimal": ","\r
11481                          *          "thousands": "."\r
11482                          *        }\r
11483                          *      } );\r
11484                          *    } );\r
11485                          */\r
11486                         "sDecimal": "",\r
11487         \r
11488         \r
11489                         /**\r
11490                          * DataTables has a build in number formatter (`formatNumber`) which is\r
11491                          * used to format large numbers that are used in the table information.\r
11492                          * By default a comma is used, but this can be trivially changed to any\r
11493                          * character you wish with this parameter.\r
11494                          *  @type string\r
11495                          *  @default ,\r
11496                          *\r
11497                          *  @dtopt Language\r
11498                          *  @name DataTable.defaults.language.thousands\r
11499                          *\r
11500                          *  @example\r
11501                          *    $(document).ready( function() {\r
11502                          *      $('#example').dataTable( {\r
11503                          *        "language": {\r
11504                          *          "thousands": "'"\r
11505                          *        }\r
11506                          *      } );\r
11507                          *    } );\r
11508                          */\r
11509                         "sThousands": ",",\r
11510         \r
11511         \r
11512                         /**\r
11513                          * Detail the action that will be taken when the drop down menu for the\r
11514                          * pagination length option is changed. The '_MENU_' variable is replaced\r
11515                          * with a default select list of 10, 25, 50 and 100, and can be replaced\r
11516                          * with a custom select box if required.\r
11517                          *  @type string\r
11518                          *  @default Show _MENU_ entries\r
11519                          *\r
11520                          *  @dtopt Language\r
11521                          *  @name DataTable.defaults.language.lengthMenu\r
11522                          *\r
11523                          *  @example\r
11524                          *    // Language change only\r
11525                          *    $(document).ready( function() {\r
11526                          *      $('#example').dataTable( {\r
11527                          *        "language": {\r
11528                          *          "lengthMenu": "Display _MENU_ records"\r
11529                          *        }\r
11530                          *      } );\r
11531                          *    } );\r
11532                          *\r
11533                          *  @example\r
11534                          *    // Language and options change\r
11535                          *    $(document).ready( function() {\r
11536                          *      $('#example').dataTable( {\r
11537                          *        "language": {\r
11538                          *          "lengthMenu": 'Display <select>'+\r
11539                          *            '<option value="10">10</option>'+\r
11540                          *            '<option value="20">20</option>'+\r
11541                          *            '<option value="30">30</option>'+\r
11542                          *            '<option value="40">40</option>'+\r
11543                          *            '<option value="50">50</option>'+\r
11544                          *            '<option value="-1">All</option>'+\r
11545                          *            '</select> records'\r
11546                          *        }\r
11547                          *      } );\r
11548                          *    } );\r
11549                          */\r
11550                         "sLengthMenu": "Show _MENU_ entries",\r
11551         \r
11552         \r
11553                         /**\r
11554                          * When using Ajax sourced data and during the first draw when DataTables is\r
11555                          * gathering the data, this message is shown in an empty row in the table to\r
11556                          * indicate to the end user the the data is being loaded. Note that this\r
11557                          * parameter is not used when loading data by server-side processing, just\r
11558                          * Ajax sourced data with client-side processing.\r
11559                          *  @type string\r
11560                          *  @default Loading...\r
11561                          *\r
11562                          *  @dtopt Language\r
11563                          *  @name DataTable.defaults.language.loadingRecords\r
11564                          *\r
11565                          *  @example\r
11566                          *    $(document).ready( function() {\r
11567                          *      $('#example').dataTable( {\r
11568                          *        "language": {\r
11569                          *          "loadingRecords": "Please wait - loading..."\r
11570                          *        }\r
11571                          *      } );\r
11572                          *    } );\r
11573                          */\r
11574                         "sLoadingRecords": "Loading...",\r
11575         \r
11576         \r
11577                         /**\r
11578                          * Text which is displayed when the table is processing a user action\r
11579                          * (usually a sort command or similar).\r
11580                          *  @type string\r
11581                          *  @default Processing...\r
11582                          *\r
11583                          *  @dtopt Language\r
11584                          *  @name DataTable.defaults.language.processing\r
11585                          *\r
11586                          *  @example\r
11587                          *    $(document).ready( function() {\r
11588                          *      $('#example').dataTable( {\r
11589                          *        "language": {\r
11590                          *          "processing": "DataTables is currently busy"\r
11591                          *        }\r
11592                          *      } );\r
11593                          *    } );\r
11594                          */\r
11595                         "sProcessing": "Processing...",\r
11596         \r
11597         \r
11598                         /**\r
11599                          * Details the actions that will be taken when the user types into the\r
11600                          * filtering input text box. The variable "_INPUT_", if used in the string,\r
11601                          * is replaced with the HTML text box for the filtering input allowing\r
11602                          * control over where it appears in the string. If "_INPUT_" is not given\r
11603                          * then the input box is appended to the string automatically.\r
11604                          *  @type string\r
11605                          *  @default Search:\r
11606                          *\r
11607                          *  @dtopt Language\r
11608                          *  @name DataTable.defaults.language.search\r
11609                          *\r
11610                          *  @example\r
11611                          *    // Input text box will be appended at the end automatically\r
11612                          *    $(document).ready( function() {\r
11613                          *      $('#example').dataTable( {\r
11614                          *        "language": {\r
11615                          *          "search": "Filter records:"\r
11616                          *        }\r
11617                          *      } );\r
11618                          *    } );\r
11619                          *\r
11620                          *  @example\r
11621                          *    // Specify where the filter should appear\r
11622                          *    $(document).ready( function() {\r
11623                          *      $('#example').dataTable( {\r
11624                          *        "language": {\r
11625                          *          "search": "Apply filter _INPUT_ to table"\r
11626                          *        }\r
11627                          *      } );\r
11628                          *    } );\r
11629                          */\r
11630                         "sSearch": "Search:",\r
11631         \r
11632         \r
11633                         /**\r
11634                          * Assign a `placeholder` attribute to the search `input` element\r
11635                          *  @type string\r
11636                          *  @default \r
11637                          *\r
11638                          *  @dtopt Language\r
11639                          *  @name DataTable.defaults.language.searchPlaceholder\r
11640                          */\r
11641                         "sSearchPlaceholder": "",\r
11642         \r
11643         \r
11644                         /**\r
11645                          * All of the language information can be stored in a file on the\r
11646                          * server-side, which DataTables will look up if this parameter is passed.\r
11647                          * It must store the URL of the language file, which is in a JSON format,\r
11648                          * and the object has the same properties as the oLanguage object in the\r
11649                          * initialiser object (i.e. the above parameters). Please refer to one of\r
11650                          * the example language files to see how this works in action.\r
11651                          *  @type string\r
11652                          *  @default <i>Empty string - i.e. disabled</i>\r
11653                          *\r
11654                          *  @dtopt Language\r
11655                          *  @name DataTable.defaults.language.url\r
11656                          *\r
11657                          *  @example\r
11658                          *    $(document).ready( function() {\r
11659                          *      $('#example').dataTable( {\r
11660                          *        "language": {\r
11661                          *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"\r
11662                          *        }\r
11663                          *      } );\r
11664                          *    } );\r
11665                          */\r
11666                         "sUrl": "",\r
11667         \r
11668         \r
11669                         /**\r
11670                          * Text shown inside the table records when the is no information to be\r
11671                          * displayed after filtering. `emptyTable` is shown when there is simply no\r
11672                          * information in the table at all (regardless of filtering).\r
11673                          *  @type string\r
11674                          *  @default No matching records found\r
11675                          *\r
11676                          *  @dtopt Language\r
11677                          *  @name DataTable.defaults.language.zeroRecords\r
11678                          *\r
11679                          *  @example\r
11680                          *    $(document).ready( function() {\r
11681                          *      $('#example').dataTable( {\r
11682                          *        "language": {\r
11683                          *          "zeroRecords": "No records to display"\r
11684                          *        }\r
11685                          *      } );\r
11686                          *    } );\r
11687                          */\r
11688                         "sZeroRecords": "No matching records found"\r
11689                 },\r
11690         \r
11691         \r
11692                 /**\r
11693                  * This parameter allows you to have define the global filtering state at\r
11694                  * initialisation time. As an object the `search` parameter must be\r
11695                  * defined, but all other parameters are optional. When `regex` is true,\r
11696                  * the search string will be treated as a regular expression, when false\r
11697                  * (default) it will be treated as a straight string. When `smart`\r
11698                  * DataTables will use it's smart filtering methods (to word match at\r
11699                  * any point in the data), when false this will not be done.\r
11700                  *  @namespace\r
11701                  *  @extends DataTable.models.oSearch\r
11702                  *\r
11703                  *  @dtopt Options\r
11704                  *  @name DataTable.defaults.search\r
11705                  *\r
11706                  *  @example\r
11707                  *    $(document).ready( function() {\r
11708                  *      $('#example').dataTable( {\r
11709                  *        "search": {"search": "Initial search"}\r
11710                  *      } );\r
11711                  *    } )\r
11712                  */\r
11713                 "oSearch": $.extend( {}, DataTable.models.oSearch ),\r
11714         \r
11715         \r
11716                 /**\r
11717                  * __Deprecated__ The functionality provided by this parameter has now been\r
11718                  * superseded by that provided through `ajax`, which should be used instead.\r
11719                  *\r
11720                  * By default DataTables will look for the property `data` (or `aaData` for\r
11721                  * compatibility with DataTables 1.9-) when obtaining data from an Ajax\r
11722                  * source or for server-side processing - this parameter allows that\r
11723                  * property to be changed. You can use Javascript dotted object notation to\r
11724                  * get a data source for multiple levels of nesting.\r
11725                  *  @type string\r
11726                  *  @default data\r
11727                  *\r
11728                  *  @dtopt Options\r
11729                  *  @dtopt Server-side\r
11730                  *  @name DataTable.defaults.ajaxDataProp\r
11731                  *\r
11732                  *  @deprecated 1.10. Please use `ajax` for this functionality now.\r
11733                  */\r
11734                 "sAjaxDataProp": "data",\r
11735         \r
11736         \r
11737                 /**\r
11738                  * __Deprecated__ The functionality provided by this parameter has now been\r
11739                  * superseded by that provided through `ajax`, which should be used instead.\r
11740                  *\r
11741                  * You can instruct DataTables to load data from an external\r
11742                  * source using this parameter (use aData if you want to pass data in you\r
11743                  * already have). Simply provide a url a JSON object can be obtained from.\r
11744                  *  @type string\r
11745                  *  @default null\r
11746                  *\r
11747                  *  @dtopt Options\r
11748                  *  @dtopt Server-side\r
11749                  *  @name DataTable.defaults.ajaxSource\r
11750                  *\r
11751                  *  @deprecated 1.10. Please use `ajax` for this functionality now.\r
11752                  */\r
11753                 "sAjaxSource": null,\r
11754         \r
11755         \r
11756                 /**\r
11757                  * This initialisation variable allows you to specify exactly where in the\r
11758                  * DOM you want DataTables to inject the various controls it adds to the page\r
11759                  * (for example you might want the pagination controls at the top of the\r
11760                  * table). DIV elements (with or without a custom class) can also be added to\r
11761                  * aid styling. The follow syntax is used:\r
11762                  *   <ul>\r
11763                  *     <li>The following options are allowed:\r
11764                  *       <ul>\r
11765                  *         <li>'l' - Length changing</li>\r
11766                  *         <li>'f' - Filtering input</li>\r
11767                  *         <li>'t' - The table!</li>\r
11768                  *         <li>'i' - Information</li>\r
11769                  *         <li>'p' - Pagination</li>\r
11770                  *         <li>'r' - pRocessing</li>\r
11771                  *       </ul>\r
11772                  *     </li>\r
11773                  *     <li>The following constants are allowed:\r
11774                  *       <ul>\r
11775                  *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>\r
11776                  *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>\r
11777                  *       </ul>\r
11778                  *     </li>\r
11779                  *     <li>The following syntax is expected:\r
11780                  *       <ul>\r
11781                  *         <li>'&lt;' and '&gt;' - div elements</li>\r
11782                  *         <li>'&lt;"class" and '&gt;' - div with a class</li>\r
11783                  *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>\r
11784                  *       </ul>\r
11785                  *     </li>\r
11786                  *     <li>Examples:\r
11787                  *       <ul>\r
11788                  *         <li>'&lt;"wrapper"flipt&gt;'</li>\r
11789                  *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>\r
11790                  *       </ul>\r
11791                  *     </li>\r
11792                  *   </ul>\r
11793                  *  @type string\r
11794                  *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>\r
11795                  *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>\r
11796                  *\r
11797                  *  @dtopt Options\r
11798                  *  @name DataTable.defaults.dom\r
11799                  *\r
11800                  *  @example\r
11801                  *    $(document).ready( function() {\r
11802                  *      $('#example').dataTable( {\r
11803                  *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'\r
11804                  *      } );\r
11805                  *    } );\r
11806                  */\r
11807                 "sDom": "lfrtip",\r
11808         \r
11809         \r
11810                 /**\r
11811                  * Search delay option. This will throttle full table searches that use the\r
11812                  * DataTables provided search input element (it does not effect calls to\r
11813                  * `dt-api search()`, providing a delay before the search is made.\r
11814                  *  @type integer\r
11815                  *  @default 0\r
11816                  *\r
11817                  *  @dtopt Options\r
11818                  *  @name DataTable.defaults.searchDelay\r
11819                  *\r
11820                  *  @example\r
11821                  *    $(document).ready( function() {\r
11822                  *      $('#example').dataTable( {\r
11823                  *        "searchDelay": 200\r
11824                  *      } );\r
11825                  *    } )\r
11826                  */\r
11827                 "searchDelay": null,\r
11828         \r
11829         \r
11830                 /**\r
11831                  * DataTables features four different built-in options for the buttons to\r
11832                  * display for pagination control:\r
11833                  *\r
11834                  * * `simple` - 'Previous' and 'Next' buttons only\r
11835                  * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers\r
11836                  * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons\r
11837                  * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus\r
11838                  *   page numbers\r
11839                  *  \r
11840                  * Further methods can be added using {@link DataTable.ext.oPagination}.\r
11841                  *  @type string\r
11842                  *  @default simple_numbers\r
11843                  *\r
11844                  *  @dtopt Options\r
11845                  *  @name DataTable.defaults.pagingType\r
11846                  *\r
11847                  *  @example\r
11848                  *    $(document).ready( function() {\r
11849                  *      $('#example').dataTable( {\r
11850                  *        "pagingType": "full_numbers"\r
11851                  *      } );\r
11852                  *    } )\r
11853                  */\r
11854                 "sPaginationType": "simple_numbers",\r
11855         \r
11856         \r
11857                 /**\r
11858                  * Enable horizontal scrolling. When a table is too wide to fit into a\r
11859                  * certain layout, or you have a large number of columns in the table, you\r
11860                  * can enable x-scrolling to show the table in a viewport, which can be\r
11861                  * scrolled. This property can be `true` which will allow the table to\r
11862                  * scroll horizontally when needed, or any CSS unit, or a number (in which\r
11863                  * case it will be treated as a pixel measurement). Setting as simply `true`\r
11864                  * is recommended.\r
11865                  *  @type boolean|string\r
11866                  *  @default <i>blank string - i.e. disabled</i>\r
11867                  *\r
11868                  *  @dtopt Features\r
11869                  *  @name DataTable.defaults.scrollX\r
11870                  *\r
11871                  *  @example\r
11872                  *    $(document).ready( function() {\r
11873                  *      $('#example').dataTable( {\r
11874                  *        "scrollX": true,\r
11875                  *        "scrollCollapse": true\r
11876                  *      } );\r
11877                  *    } );\r
11878                  */\r
11879                 "sScrollX": "",\r
11880         \r
11881         \r
11882                 /**\r
11883                  * This property can be used to force a DataTable to use more width than it\r
11884                  * might otherwise do when x-scrolling is enabled. For example if you have a\r
11885                  * table which requires to be well spaced, this parameter is useful for\r
11886                  * "over-sizing" the table, and thus forcing scrolling. This property can by\r
11887                  * any CSS unit, or a number (in which case it will be treated as a pixel\r
11888                  * measurement).\r
11889                  *  @type string\r
11890                  *  @default <i>blank string - i.e. disabled</i>\r
11891                  *\r
11892                  *  @dtopt Options\r
11893                  *  @name DataTable.defaults.scrollXInner\r
11894                  *\r
11895                  *  @example\r
11896                  *    $(document).ready( function() {\r
11897                  *      $('#example').dataTable( {\r
11898                  *        "scrollX": "100%",\r
11899                  *        "scrollXInner": "110%"\r
11900                  *      } );\r
11901                  *    } );\r
11902                  */\r
11903                 "sScrollXInner": "",\r
11904         \r
11905         \r
11906                 /**\r
11907                  * Enable vertical scrolling. Vertical scrolling will constrain the DataTable\r
11908                  * to the given height, and enable scrolling for any data which overflows the\r
11909                  * current viewport. This can be used as an alternative to paging to display\r
11910                  * a lot of data in a small area (although paging and scrolling can both be\r
11911                  * enabled at the same time). This property can be any CSS unit, or a number\r
11912                  * (in which case it will be treated as a pixel measurement).\r
11913                  *  @type string\r
11914                  *  @default <i>blank string - i.e. disabled</i>\r
11915                  *\r
11916                  *  @dtopt Features\r
11917                  *  @name DataTable.defaults.scrollY\r
11918                  *\r
11919                  *  @example\r
11920                  *    $(document).ready( function() {\r
11921                  *      $('#example').dataTable( {\r
11922                  *        "scrollY": "200px",\r
11923                  *        "paginate": false\r
11924                  *      } );\r
11925                  *    } );\r
11926                  */\r
11927                 "sScrollY": "",\r
11928         \r
11929         \r
11930                 /**\r
11931                  * __Deprecated__ The functionality provided by this parameter has now been\r
11932                  * superseded by that provided through `ajax`, which should be used instead.\r
11933                  *\r
11934                  * Set the HTTP method that is used to make the Ajax call for server-side\r
11935                  * processing or Ajax sourced data.\r
11936                  *  @type string\r
11937                  *  @default GET\r
11938                  *\r
11939                  *  @dtopt Options\r
11940                  *  @dtopt Server-side\r
11941                  *  @name DataTable.defaults.serverMethod\r
11942                  *\r
11943                  *  @deprecated 1.10. Please use `ajax` for this functionality now.\r
11944                  */\r
11945                 "sServerMethod": "GET",\r
11946         \r
11947         \r
11948                 /**\r
11949                  * DataTables makes use of renderers when displaying HTML elements for\r
11950                  * a table. These renderers can be added or modified by plug-ins to\r
11951                  * generate suitable mark-up for a site. For example the Bootstrap\r
11952                  * integration plug-in for DataTables uses a paging button renderer to\r
11953                  * display pagination buttons in the mark-up required by Bootstrap.\r
11954                  *\r
11955                  * For further information about the renderers available see\r
11956                  * DataTable.ext.renderer\r
11957                  *  @type string|object\r
11958                  *  @default null\r
11959                  *\r
11960                  *  @name DataTable.defaults.renderer\r
11961                  *\r
11962                  */\r
11963                 "renderer": null,\r
11964         \r
11965         \r
11966                 /**\r
11967                  * Set the data property name that DataTables should use to get a row's id\r
11968                  * to set as the `id` property in the node.\r
11969                  *  @type string\r
11970                  *  @default DT_RowId\r
11971                  *\r
11972                  *  @name DataTable.defaults.rowId\r
11973                  */\r
11974                 "rowId": "DT_RowId"\r
11975         };\r
11976         \r
11977         _fnHungarianMap( DataTable.defaults );\r
11978         \r
11979         \r
11980         \r
11981         /*\r
11982          * Developer note - See note in model.defaults.js about the use of Hungarian\r
11983          * notation and camel case.\r
11984          */\r
11985         \r
11986         /**\r
11987          * Column options that can be given to DataTables at initialisation time.\r
11988          *  @namespace\r
11989          */\r
11990         DataTable.defaults.column = {\r
11991                 /**\r
11992                  * Define which column(s) an order will occur on for this column. This\r
11993                  * allows a column's ordering to take multiple columns into account when\r
11994                  * doing a sort or use the data from a different column. For example first\r
11995                  * name / last name columns make sense to do a multi-column sort over the\r
11996                  * two columns.\r
11997                  *  @type array|int\r
11998                  *  @default null <i>Takes the value of the column index automatically</i>\r
11999                  *\r
12000                  *  @name DataTable.defaults.column.orderData\r
12001                  *  @dtopt Columns\r
12002                  *\r
12003                  *  @example\r
12004                  *    // Using `columnDefs`\r
12005                  *    $(document).ready( function() {\r
12006                  *      $('#example').dataTable( {\r
12007                  *        "columnDefs": [\r
12008                  *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },\r
12009                  *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },\r
12010                  *          { "orderData": 2, "targets": [ 2 ] }\r
12011                  *        ]\r
12012                  *      } );\r
12013                  *    } );\r
12014                  *\r
12015                  *  @example\r
12016                  *    // Using `columns`\r
12017                  *    $(document).ready( function() {\r
12018                  *      $('#example').dataTable( {\r
12019                  *        "columns": [\r
12020                  *          { "orderData": [ 0, 1 ] },\r
12021                  *          { "orderData": [ 1, 0 ] },\r
12022                  *          { "orderData": 2 },\r
12023                  *          null,\r
12024                  *          null\r
12025                  *        ]\r
12026                  *      } );\r
12027                  *    } );\r
12028                  */\r
12029                 "aDataSort": null,\r
12030                 "iDataSort": -1,\r
12031         \r
12032         \r
12033                 /**\r
12034                  * You can control the default ordering direction, and even alter the\r
12035                  * behaviour of the sort handler (i.e. only allow ascending ordering etc)\r
12036                  * using this parameter.\r
12037                  *  @type array\r
12038                  *  @default [ 'asc', 'desc' ]\r
12039                  *\r
12040                  *  @name DataTable.defaults.column.orderSequence\r
12041                  *  @dtopt Columns\r
12042                  *\r
12043                  *  @example\r
12044                  *    // Using `columnDefs`\r
12045                  *    $(document).ready( function() {\r
12046                  *      $('#example').dataTable( {\r
12047                  *        "columnDefs": [\r
12048                  *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },\r
12049                  *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },\r
12050                  *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }\r
12051                  *        ]\r
12052                  *      } );\r
12053                  *    } );\r
12054                  *\r
12055                  *  @example\r
12056                  *    // Using `columns`\r
12057                  *    $(document).ready( function() {\r
12058                  *      $('#example').dataTable( {\r
12059                  *        "columns": [\r
12060                  *          null,\r
12061                  *          { "orderSequence": [ "asc" ] },\r
12062                  *          { "orderSequence": [ "desc", "asc", "asc" ] },\r
12063                  *          { "orderSequence": [ "desc" ] },\r
12064                  *          null\r
12065                  *        ]\r
12066                  *      } );\r
12067                  *    } );\r
12068                  */\r
12069                 "asSorting": [ 'asc', 'desc' ],\r
12070         \r
12071         \r
12072                 /**\r
12073                  * Enable or disable filtering on the data in this column.\r
12074                  *  @type boolean\r
12075                  *  @default true\r
12076                  *\r
12077                  *  @name DataTable.defaults.column.searchable\r
12078                  *  @dtopt Columns\r
12079                  *\r
12080                  *  @example\r
12081                  *    // Using `columnDefs`\r
12082                  *    $(document).ready( function() {\r
12083                  *      $('#example').dataTable( {\r
12084                  *        "columnDefs": [\r
12085                  *          { "searchable": false, "targets": [ 0 ] }\r
12086                  *        ] } );\r
12087                  *    } );\r
12088                  *\r
12089                  *  @example\r
12090                  *    // Using `columns`\r
12091                  *    $(document).ready( function() {\r
12092                  *      $('#example').dataTable( {\r
12093                  *        "columns": [\r
12094                  *          { "searchable": false },\r
12095                  *          null,\r
12096                  *          null,\r
12097                  *          null,\r
12098                  *          null\r
12099                  *        ] } );\r
12100                  *    } );\r
12101                  */\r
12102                 "bSearchable": true,\r
12103         \r
12104         \r
12105                 /**\r
12106                  * Enable or disable ordering on this column.\r
12107                  *  @type boolean\r
12108                  *  @default true\r
12109                  *\r
12110                  *  @name DataTable.defaults.column.orderable\r
12111                  *  @dtopt Columns\r
12112                  *\r
12113                  *  @example\r
12114                  *    // Using `columnDefs`\r
12115                  *    $(document).ready( function() {\r
12116                  *      $('#example').dataTable( {\r
12117                  *        "columnDefs": [\r
12118                  *          { "orderable": false, "targets": [ 0 ] }\r
12119                  *        ] } );\r
12120                  *    } );\r
12121                  *\r
12122                  *  @example\r
12123                  *    // Using `columns`\r
12124                  *    $(document).ready( function() {\r
12125                  *      $('#example').dataTable( {\r
12126                  *        "columns": [\r
12127                  *          { "orderable": false },\r
12128                  *          null,\r
12129                  *          null,\r
12130                  *          null,\r
12131                  *          null\r
12132                  *        ] } );\r
12133                  *    } );\r
12134                  */\r
12135                 "bSortable": true,\r
12136         \r
12137         \r
12138                 /**\r
12139                  * Enable or disable the display of this column.\r
12140                  *  @type boolean\r
12141                  *  @default true\r
12142                  *\r
12143                  *  @name DataTable.defaults.column.visible\r
12144                  *  @dtopt Columns\r
12145                  *\r
12146                  *  @example\r
12147                  *    // Using `columnDefs`\r
12148                  *    $(document).ready( function() {\r
12149                  *      $('#example').dataTable( {\r
12150                  *        "columnDefs": [\r
12151                  *          { "visible": false, "targets": [ 0 ] }\r
12152                  *        ] } );\r
12153                  *    } );\r
12154                  *\r
12155                  *  @example\r
12156                  *    // Using `columns`\r
12157                  *    $(document).ready( function() {\r
12158                  *      $('#example').dataTable( {\r
12159                  *        "columns": [\r
12160                  *          { "visible": false },\r
12161                  *          null,\r
12162                  *          null,\r
12163                  *          null,\r
12164                  *          null\r
12165                  *        ] } );\r
12166                  *    } );\r
12167                  */\r
12168                 "bVisible": true,\r
12169         \r
12170         \r
12171                 /**\r
12172                  * Developer definable function that is called whenever a cell is created (Ajax source,\r
12173                  * etc) or processed for input (DOM source). This can be used as a compliment to mRender\r
12174                  * allowing you to modify the DOM element (add background colour for example) when the\r
12175                  * element is available.\r
12176                  *  @type function\r
12177                  *  @param {element} td The TD node that has been created\r
12178                  *  @param {*} cellData The Data for the cell\r
12179                  *  @param {array|object} rowData The data for the whole row\r
12180                  *  @param {int} row The row index for the aoData data store\r
12181                  *  @param {int} col The column index for aoColumns\r
12182                  *\r
12183                  *  @name DataTable.defaults.column.createdCell\r
12184                  *  @dtopt Columns\r
12185                  *\r
12186                  *  @example\r
12187                  *    $(document).ready( function() {\r
12188                  *      $('#example').dataTable( {\r
12189                  *        "columnDefs": [ {\r
12190                  *          "targets": [3],\r
12191                  *          "createdCell": function (td, cellData, rowData, row, col) {\r
12192                  *            if ( cellData == "1.7" ) {\r
12193                  *              $(td).css('color', 'blue')\r
12194                  *            }\r
12195                  *          }\r
12196                  *        } ]\r
12197                  *      });\r
12198                  *    } );\r
12199                  */\r
12200                 "fnCreatedCell": null,\r
12201         \r
12202         \r
12203                 /**\r
12204                  * This parameter has been replaced by `data` in DataTables to ensure naming\r
12205                  * consistency. `dataProp` can still be used, as there is backwards\r
12206                  * compatibility in DataTables for this option, but it is strongly\r
12207                  * recommended that you use `data` in preference to `dataProp`.\r
12208                  *  @name DataTable.defaults.column.dataProp\r
12209                  */\r
12210         \r
12211         \r
12212                 /**\r
12213                  * This property can be used to read data from any data source property,\r
12214                  * including deeply nested objects / properties. `data` can be given in a\r
12215                  * number of different ways which effect its behaviour:\r
12216                  *\r
12217                  * * `integer` - treated as an array index for the data source. This is the\r
12218                  *   default that DataTables uses (incrementally increased for each column).\r
12219                  * * `string` - read an object property from the data source. There are\r
12220                  *   three 'special' options that can be used in the string to alter how\r
12221                  *   DataTables reads the data from the source object:\r
12222                  *    * `.` - Dotted Javascript notation. Just as you use a `.` in\r
12223                  *      Javascript to read from nested objects, so to can the options\r
12224                  *      specified in `data`. For example: `browser.version` or\r
12225                  *      `browser.name`. If your object parameter name contains a period, use\r
12226                  *      `\\` to escape it - i.e. `first\\.name`.\r
12227                  *    * `[]` - Array notation. DataTables can automatically combine data\r
12228                  *      from and array source, joining the data with the characters provided\r
12229                  *      between the two brackets. For example: `name[, ]` would provide a\r
12230                  *      comma-space separated list from the source array. If no characters\r
12231                  *      are provided between the brackets, the original array source is\r
12232                  *      returned.\r
12233                  *    * `()` - Function notation. Adding `()` to the end of a parameter will\r
12234                  *      execute a function of the name given. For example: `browser()` for a\r
12235                  *      simple function on the data source, `browser.version()` for a\r
12236                  *      function in a nested property or even `browser().version` to get an\r
12237                  *      object property if the function called returns an object. Note that\r
12238                  *      function notation is recommended for use in `render` rather than\r
12239                  *      `data` as it is much simpler to use as a renderer.\r
12240                  * * `null` - use the original data source for the row rather than plucking\r
12241                  *   data directly from it. This action has effects on two other\r
12242                  *   initialisation options:\r
12243                  *    * `defaultContent` - When null is given as the `data` option and\r
12244                  *      `defaultContent` is specified for the column, the value defined by\r
12245                  *      `defaultContent` will be used for the cell.\r
12246                  *    * `render` - When null is used for the `data` option and the `render`\r
12247                  *      option is specified for the column, the whole data source for the\r
12248                  *      row is used for the renderer.\r
12249                  * * `function` - the function given will be executed whenever DataTables\r
12250                  *   needs to set or get the data for a cell in the column. The function\r
12251                  *   takes three parameters:\r
12252                  *    * Parameters:\r
12253                  *      * `{array|object}` The data source for the row\r
12254                  *      * `{string}` The type call data requested - this will be 'set' when\r
12255                  *        setting data or 'filter', 'display', 'type', 'sort' or undefined\r
12256                  *        when gathering data. Note that when `undefined` is given for the\r
12257                  *        type DataTables expects to get the raw data for the object back<\r
12258                  *      * `{*}` Data to set when the second parameter is 'set'.\r
12259                  *    * Return:\r
12260                  *      * The return value from the function is not required when 'set' is\r
12261                  *        the type of call, but otherwise the return is what will be used\r
12262                  *        for the data requested.\r
12263                  *\r
12264                  * Note that `data` is a getter and setter option. If you just require\r
12265                  * formatting of data for output, you will likely want to use `render` which\r
12266                  * is simply a getter and thus simpler to use.\r
12267                  *\r
12268                  * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The\r
12269                  * name change reflects the flexibility of this property and is consistent\r
12270                  * with the naming of mRender. If 'mDataProp' is given, then it will still\r
12271                  * be used by DataTables, as it automatically maps the old name to the new\r
12272                  * if required.\r
12273                  *\r
12274                  *  @type string|int|function|null\r
12275                  *  @default null <i>Use automatically calculated column index</i>\r
12276                  *\r
12277                  *  @name DataTable.defaults.column.data\r
12278                  *  @dtopt Columns\r
12279                  *\r
12280                  *  @example\r
12281                  *    // Read table data from objects\r
12282                  *    // JSON structure for each row:\r
12283                  *    //   {\r
12284                  *    //      "engine": {value},\r
12285                  *    //      "browser": {value},\r
12286                  *    //      "platform": {value},\r
12287                  *    //      "version": {value},\r
12288                  *    //      "grade": {value}\r
12289                  *    //   }\r
12290                  *    $(document).ready( function() {\r
12291                  *      $('#example').dataTable( {\r
12292                  *        "ajaxSource": "sources/objects.txt",\r
12293                  *        "columns": [\r
12294                  *          { "data": "engine" },\r
12295                  *          { "data": "browser" },\r
12296                  *          { "data": "platform" },\r
12297                  *          { "data": "version" },\r
12298                  *          { "data": "grade" }\r
12299                  *        ]\r
12300                  *      } );\r
12301                  *    } );\r
12302                  *\r
12303                  *  @example\r
12304                  *    // Read information from deeply nested objects\r
12305                  *    // JSON structure for each row:\r
12306                  *    //   {\r
12307                  *    //      "engine": {value},\r
12308                  *    //      "browser": {value},\r
12309                  *    //      "platform": {\r
12310                  *    //         "inner": {value}\r
12311                  *    //      },\r
12312                  *    //      "details": [\r
12313                  *    //         {value}, {value}\r
12314                  *    //      ]\r
12315                  *    //   }\r
12316                  *    $(document).ready( function() {\r
12317                  *      $('#example').dataTable( {\r
12318                  *        "ajaxSource": "sources/deep.txt",\r
12319                  *        "columns": [\r
12320                  *          { "data": "engine" },\r
12321                  *          { "data": "browser" },\r
12322                  *          { "data": "platform.inner" },\r
12323                  *          { "data": "platform.details.0" },\r
12324                  *          { "data": "platform.details.1" }\r
12325                  *        ]\r
12326                  *      } );\r
12327                  *    } );\r
12328                  *\r
12329                  *  @example\r
12330                  *    // Using `data` as a function to provide different information for\r
12331                  *    // sorting, filtering and display. In this case, currency (price)\r
12332                  *    $(document).ready( function() {\r
12333                  *      $('#example').dataTable( {\r
12334                  *        "columnDefs": [ {\r
12335                  *          "targets": [ 0 ],\r
12336                  *          "data": function ( source, type, val ) {\r
12337                  *            if (type === 'set') {\r
12338                  *              source.price = val;\r
12339                  *              // Store the computed dislay and filter values for efficiency\r
12340                  *              source.price_display = val=="" ? "" : "$"+numberFormat(val);\r
12341                  *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;\r
12342                  *              return;\r
12343                  *            }\r
12344                  *            else if (type === 'display') {\r
12345                  *              return source.price_display;\r
12346                  *            }\r
12347                  *            else if (type === 'filter') {\r
12348                  *              return source.price_filter;\r
12349                  *            }\r
12350                  *            // 'sort', 'type' and undefined all just use the integer\r
12351                  *            return source.price;\r
12352                  *          }\r
12353                  *        } ]\r
12354                  *      } );\r
12355                  *    } );\r
12356                  *\r
12357                  *  @example\r
12358                  *    // Using default content\r
12359                  *    $(document).ready( function() {\r
12360                  *      $('#example').dataTable( {\r
12361                  *        "columnDefs": [ {\r
12362                  *          "targets": [ 0 ],\r
12363                  *          "data": null,\r
12364                  *          "defaultContent": "Click to edit"\r
12365                  *        } ]\r
12366                  *      } );\r
12367                  *    } );\r
12368                  *\r
12369                  *  @example\r
12370                  *    // Using array notation - outputting a list from an array\r
12371                  *    $(document).ready( function() {\r
12372                  *      $('#example').dataTable( {\r
12373                  *        "columnDefs": [ {\r
12374                  *          "targets": [ 0 ],\r
12375                  *          "data": "name[, ]"\r
12376                  *        } ]\r
12377                  *      } );\r
12378                  *    } );\r
12379                  *\r
12380                  */\r
12381                 "mData": null,\r
12382         \r
12383         \r
12384                 /**\r
12385                  * This property is the rendering partner to `data` and it is suggested that\r
12386                  * when you want to manipulate data for display (including filtering,\r
12387                  * sorting etc) without altering the underlying data for the table, use this\r
12388                  * property. `render` can be considered to be the the read only companion to\r
12389                  * `data` which is read / write (then as such more complex). Like `data`\r
12390                  * this option can be given in a number of different ways to effect its\r
12391                  * behaviour:\r
12392                  *\r
12393                  * * `integer` - treated as an array index for the data source. This is the\r
12394                  *   default that DataTables uses (incrementally increased for each column).\r
12395                  * * `string` - read an object property from the data source. There are\r
12396                  *   three 'special' options that can be used in the string to alter how\r
12397                  *   DataTables reads the data from the source object:\r
12398                  *    * `.` - Dotted Javascript notation. Just as you use a `.` in\r
12399                  *      Javascript to read from nested objects, so to can the options\r
12400                  *      specified in `data`. For example: `browser.version` or\r
12401                  *      `browser.name`. If your object parameter name contains a period, use\r
12402                  *      `\\` to escape it - i.e. `first\\.name`.\r
12403                  *    * `[]` - Array notation. DataTables can automatically combine data\r
12404                  *      from and array source, joining the data with the characters provided\r
12405                  *      between the two brackets. For example: `name[, ]` would provide a\r
12406                  *      comma-space separated list from the source array. If no characters\r
12407                  *      are provided between the brackets, the original array source is\r
12408                  *      returned.\r
12409                  *    * `()` - Function notation. Adding `()` to the end of a parameter will\r
12410                  *      execute a function of the name given. For example: `browser()` for a\r
12411                  *      simple function on the data source, `browser.version()` for a\r
12412                  *      function in a nested property or even `browser().version` to get an\r
12413                  *      object property if the function called returns an object.\r
12414                  * * `object` - use different data for the different data types requested by\r
12415                  *   DataTables ('filter', 'display', 'type' or 'sort'). The property names\r
12416                  *   of the object is the data type the property refers to and the value can\r
12417                  *   defined using an integer, string or function using the same rules as\r
12418                  *   `render` normally does. Note that an `_` option _must_ be specified.\r
12419                  *   This is the default value to use if you haven't specified a value for\r
12420                  *   the data type requested by DataTables.\r
12421                  * * `function` - the function given will be executed whenever DataTables\r
12422                  *   needs to set or get the data for a cell in the column. The function\r
12423                  *   takes three parameters:\r
12424                  *    * Parameters:\r
12425                  *      * {array|object} The data source for the row (based on `data`)\r
12426                  *      * {string} The type call data requested - this will be 'filter',\r
12427                  *        'display', 'type' or 'sort'.\r
12428                  *      * {array|object} The full data source for the row (not based on\r
12429                  *        `data`)\r
12430                  *    * Return:\r
12431                  *      * The return value from the function is what will be used for the\r
12432                  *        data requested.\r
12433                  *\r
12434                  *  @type string|int|function|object|null\r
12435                  *  @default null Use the data source value.\r
12436                  *\r
12437                  *  @name DataTable.defaults.column.render\r
12438                  *  @dtopt Columns\r
12439                  *\r
12440                  *  @example\r
12441                  *    // Create a comma separated list from an array of objects\r
12442                  *    $(document).ready( function() {\r
12443                  *      $('#example').dataTable( {\r
12444                  *        "ajaxSource": "sources/deep.txt",\r
12445                  *        "columns": [\r
12446                  *          { "data": "engine" },\r
12447                  *          { "data": "browser" },\r
12448                  *          {\r
12449                  *            "data": "platform",\r
12450                  *            "render": "[, ].name"\r
12451                  *          }\r
12452                  *        ]\r
12453                  *      } );\r
12454                  *    } );\r
12455                  *\r
12456                  *  @example\r
12457                  *    // Execute a function to obtain data\r
12458                  *    $(document).ready( function() {\r
12459                  *      $('#example').dataTable( {\r
12460                  *        "columnDefs": [ {\r
12461                  *          "targets": [ 0 ],\r
12462                  *          "data": null, // Use the full data source object for the renderer's source\r
12463                  *          "render": "browserName()"\r
12464                  *        } ]\r
12465                  *      } );\r
12466                  *    } );\r
12467                  *\r
12468                  *  @example\r
12469                  *    // As an object, extracting different data for the different types\r
12470                  *    // This would be used with a data source such as:\r
12471                  *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }\r
12472                  *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`\r
12473                  *    // (which has both forms) is used for filtering for if a user inputs either format, while\r
12474                  *    // the formatted phone number is the one that is shown in the table.\r
12475                  *    $(document).ready( function() {\r
12476                  *      $('#example').dataTable( {\r
12477                  *        "columnDefs": [ {\r
12478                  *          "targets": [ 0 ],\r
12479                  *          "data": null, // Use the full data source object for the renderer's source\r
12480                  *          "render": {\r
12481                  *            "_": "phone",\r
12482                  *            "filter": "phone_filter",\r
12483                  *            "display": "phone_display"\r
12484                  *          }\r
12485                  *        } ]\r
12486                  *      } );\r
12487                  *    } );\r
12488                  *\r
12489                  *  @example\r
12490                  *    // Use as a function to create a link from the data source\r
12491                  *    $(document).ready( function() {\r
12492                  *      $('#example').dataTable( {\r
12493                  *        "columnDefs": [ {\r
12494                  *          "targets": [ 0 ],\r
12495                  *          "data": "download_link",\r
12496                  *          "render": function ( data, type, full ) {\r
12497                  *            return '<a href="'+data+'">Download</a>';\r
12498                  *          }\r
12499                  *        } ]\r
12500                  *      } );\r
12501                  *    } );\r
12502                  */\r
12503                 "mRender": null,\r
12504         \r
12505         \r
12506                 /**\r
12507                  * Change the cell type created for the column - either TD cells or TH cells. This\r
12508                  * can be useful as TH cells have semantic meaning in the table body, allowing them\r
12509                  * to act as a header for a row (you may wish to add scope='row' to the TH elements).\r
12510                  *  @type string\r
12511                  *  @default td\r
12512                  *\r
12513                  *  @name DataTable.defaults.column.cellType\r
12514                  *  @dtopt Columns\r
12515                  *\r
12516                  *  @example\r
12517                  *    // Make the first column use TH cells\r
12518                  *    $(document).ready( function() {\r
12519                  *      $('#example').dataTable( {\r
12520                  *        "columnDefs": [ {\r
12521                  *          "targets": [ 0 ],\r
12522                  *          "cellType": "th"\r
12523                  *        } ]\r
12524                  *      } );\r
12525                  *    } );\r
12526                  */\r
12527                 "sCellType": "td",\r
12528         \r
12529         \r
12530                 /**\r
12531                  * Class to give to each cell in this column.\r
12532                  *  @type string\r
12533                  *  @default <i>Empty string</i>\r
12534                  *\r
12535                  *  @name DataTable.defaults.column.class\r
12536                  *  @dtopt Columns\r
12537                  *\r
12538                  *  @example\r
12539                  *    // Using `columnDefs`\r
12540                  *    $(document).ready( function() {\r
12541                  *      $('#example').dataTable( {\r
12542                  *        "columnDefs": [\r
12543                  *          { "class": "my_class", "targets": [ 0 ] }\r
12544                  *        ]\r
12545                  *      } );\r
12546                  *    } );\r
12547                  *\r
12548                  *  @example\r
12549                  *    // Using `columns`\r
12550                  *    $(document).ready( function() {\r
12551                  *      $('#example').dataTable( {\r
12552                  *        "columns": [\r
12553                  *          { "class": "my_class" },\r
12554                  *          null,\r
12555                  *          null,\r
12556                  *          null,\r
12557                  *          null\r
12558                  *        ]\r
12559                  *      } );\r
12560                  *    } );\r
12561                  */\r
12562                 "sClass": "",\r
12563         \r
12564                 /**\r
12565                  * When DataTables calculates the column widths to assign to each column,\r
12566                  * it finds the longest string in each column and then constructs a\r
12567                  * temporary table and reads the widths from that. The problem with this\r
12568                  * is that "mmm" is much wider then "iiii", but the latter is a longer\r
12569                  * string - thus the calculation can go wrong (doing it properly and putting\r
12570                  * it into an DOM object and measuring that is horribly(!) slow). Thus as\r
12571                  * a "work around" we provide this option. It will append its value to the\r
12572                  * text that is found to be the longest string for the column - i.e. padding.\r
12573                  * Generally you shouldn't need this!\r
12574                  *  @type string\r
12575                  *  @default <i>Empty string<i>\r
12576                  *\r
12577                  *  @name DataTable.defaults.column.contentPadding\r
12578                  *  @dtopt Columns\r
12579                  *\r
12580                  *  @example\r
12581                  *    // Using `columns`\r
12582                  *    $(document).ready( function() {\r
12583                  *      $('#example').dataTable( {\r
12584                  *        "columns": [\r
12585                  *          null,\r
12586                  *          null,\r
12587                  *          null,\r
12588                  *          {\r
12589                  *            "contentPadding": "mmm"\r
12590                  *          }\r
12591                  *        ]\r
12592                  *      } );\r
12593                  *    } );\r
12594                  */\r
12595                 "sContentPadding": "",\r
12596         \r
12597         \r
12598                 /**\r
12599                  * Allows a default value to be given for a column's data, and will be used\r
12600                  * whenever a null data source is encountered (this can be because `data`\r
12601                  * is set to null, or because the data source itself is null).\r
12602                  *  @type string\r
12603                  *  @default null\r
12604                  *\r
12605                  *  @name DataTable.defaults.column.defaultContent\r
12606                  *  @dtopt Columns\r
12607                  *\r
12608                  *  @example\r
12609                  *    // Using `columnDefs`\r
12610                  *    $(document).ready( function() {\r
12611                  *      $('#example').dataTable( {\r
12612                  *        "columnDefs": [\r
12613                  *          {\r
12614                  *            "data": null,\r
12615                  *            "defaultContent": "Edit",\r
12616                  *            "targets": [ -1 ]\r
12617                  *          }\r
12618                  *        ]\r
12619                  *      } );\r
12620                  *    } );\r
12621                  *\r
12622                  *  @example\r
12623                  *    // Using `columns`\r
12624                  *    $(document).ready( function() {\r
12625                  *      $('#example').dataTable( {\r
12626                  *        "columns": [\r
12627                  *          null,\r
12628                  *          null,\r
12629                  *          null,\r
12630                  *          {\r
12631                  *            "data": null,\r
12632                  *            "defaultContent": "Edit"\r
12633                  *          }\r
12634                  *        ]\r
12635                  *      } );\r
12636                  *    } );\r
12637                  */\r
12638                 "sDefaultContent": null,\r
12639         \r
12640         \r
12641                 /**\r
12642                  * This parameter is only used in DataTables' server-side processing. It can\r
12643                  * be exceptionally useful to know what columns are being displayed on the\r
12644                  * client side, and to map these to database fields. When defined, the names\r
12645                  * also allow DataTables to reorder information from the server if it comes\r
12646                  * back in an unexpected order (i.e. if you switch your columns around on the\r
12647                  * client-side, your server-side code does not also need updating).\r
12648                  *  @type string\r
12649                  *  @default <i>Empty string</i>\r
12650                  *\r
12651                  *  @name DataTable.defaults.column.name\r
12652                  *  @dtopt Columns\r
12653                  *\r
12654                  *  @example\r
12655                  *    // Using `columnDefs`\r
12656                  *    $(document).ready( function() {\r
12657                  *      $('#example').dataTable( {\r
12658                  *        "columnDefs": [\r
12659                  *          { "name": "engine", "targets": [ 0 ] },\r
12660                  *          { "name": "browser", "targets": [ 1 ] },\r
12661                  *          { "name": "platform", "targets": [ 2 ] },\r
12662                  *          { "name": "version", "targets": [ 3 ] },\r
12663                  *          { "name": "grade", "targets": [ 4 ] }\r
12664                  *        ]\r
12665                  *      } );\r
12666                  *    } );\r
12667                  *\r
12668                  *  @example\r
12669                  *    // Using `columns`\r
12670                  *    $(document).ready( function() {\r
12671                  *      $('#example').dataTable( {\r
12672                  *        "columns": [\r
12673                  *          { "name": "engine" },\r
12674                  *          { "name": "browser" },\r
12675                  *          { "name": "platform" },\r
12676                  *          { "name": "version" },\r
12677                  *          { "name": "grade" }\r
12678                  *        ]\r
12679                  *      } );\r
12680                  *    } );\r
12681                  */\r
12682                 "sName": "",\r
12683         \r
12684         \r
12685                 /**\r
12686                  * Defines a data source type for the ordering which can be used to read\r
12687                  * real-time information from the table (updating the internally cached\r
12688                  * version) prior to ordering. This allows ordering to occur on user\r
12689                  * editable elements such as form inputs.\r
12690                  *  @type string\r
12691                  *  @default std\r
12692                  *\r
12693                  *  @name DataTable.defaults.column.orderDataType\r
12694                  *  @dtopt Columns\r
12695                  *\r
12696                  *  @example\r
12697                  *    // Using `columnDefs`\r
12698                  *    $(document).ready( function() {\r
12699                  *      $('#example').dataTable( {\r
12700                  *        "columnDefs": [\r
12701                  *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },\r
12702                  *          { "type": "numeric", "targets": [ 3 ] },\r
12703                  *          { "orderDataType": "dom-select", "targets": [ 4 ] },\r
12704                  *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }\r
12705                  *        ]\r
12706                  *      } );\r
12707                  *    } );\r
12708                  *\r
12709                  *  @example\r
12710                  *    // Using `columns`\r
12711                  *    $(document).ready( function() {\r
12712                  *      $('#example').dataTable( {\r
12713                  *        "columns": [\r
12714                  *          null,\r
12715                  *          null,\r
12716                  *          { "orderDataType": "dom-text" },\r
12717                  *          { "orderDataType": "dom-text", "type": "numeric" },\r
12718                  *          { "orderDataType": "dom-select" },\r
12719                  *          { "orderDataType": "dom-checkbox" }\r
12720                  *        ]\r
12721                  *      } );\r
12722                  *    } );\r
12723                  */\r
12724                 "sSortDataType": "std",\r
12725         \r
12726         \r
12727                 /**\r
12728                  * The title of this column.\r
12729                  *  @type string\r
12730                  *  @default null <i>Derived from the 'TH' value for this column in the\r
12731                  *    original HTML table.</i>\r
12732                  *\r
12733                  *  @name DataTable.defaults.column.title\r
12734                  *  @dtopt Columns\r
12735                  *\r
12736                  *  @example\r
12737                  *    // Using `columnDefs`\r
12738                  *    $(document).ready( function() {\r
12739                  *      $('#example').dataTable( {\r
12740                  *        "columnDefs": [\r
12741                  *          { "title": "My column title", "targets": [ 0 ] }\r
12742                  *        ]\r
12743                  *      } );\r
12744                  *    } );\r
12745                  *\r
12746                  *  @example\r
12747                  *    // Using `columns`\r
12748                  *    $(document).ready( function() {\r
12749                  *      $('#example').dataTable( {\r
12750                  *        "columns": [\r
12751                  *          { "title": "My column title" },\r
12752                  *          null,\r
12753                  *          null,\r
12754                  *          null,\r
12755                  *          null\r
12756                  *        ]\r
12757                  *      } );\r
12758                  *    } );\r
12759                  */\r
12760                 "sTitle": null,\r
12761         \r
12762         \r
12763                 /**\r
12764                  * The type allows you to specify how the data for this column will be\r
12765                  * ordered. Four types (string, numeric, date and html (which will strip\r
12766                  * HTML tags before ordering)) are currently available. Note that only date\r
12767                  * formats understood by Javascript's Date() object will be accepted as type\r
12768                  * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',\r
12769                  * 'numeric', 'date' or 'html' (by default). Further types can be adding\r
12770                  * through plug-ins.\r
12771                  *  @type string\r
12772                  *  @default null <i>Auto-detected from raw data</i>\r
12773                  *\r
12774                  *  @name DataTable.defaults.column.type\r
12775                  *  @dtopt Columns\r
12776                  *\r
12777                  *  @example\r
12778                  *    // Using `columnDefs`\r
12779                  *    $(document).ready( function() {\r
12780                  *      $('#example').dataTable( {\r
12781                  *        "columnDefs": [\r
12782                  *          { "type": "html", "targets": [ 0 ] }\r
12783                  *        ]\r
12784                  *      } );\r
12785                  *    } );\r
12786                  *\r
12787                  *  @example\r
12788                  *    // Using `columns`\r
12789                  *    $(document).ready( function() {\r
12790                  *      $('#example').dataTable( {\r
12791                  *        "columns": [\r
12792                  *          { "type": "html" },\r
12793                  *          null,\r
12794                  *          null,\r
12795                  *          null,\r
12796                  *          null\r
12797                  *        ]\r
12798                  *      } );\r
12799                  *    } );\r
12800                  */\r
12801                 "sType": null,\r
12802         \r
12803         \r
12804                 /**\r
12805                  * Defining the width of the column, this parameter may take any CSS value\r
12806                  * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not\r
12807                  * been given a specific width through this interface ensuring that the table\r
12808                  * remains readable.\r
12809                  *  @type string\r
12810                  *  @default null <i>Automatic</i>\r
12811                  *\r
12812                  *  @name DataTable.defaults.column.width\r
12813                  *  @dtopt Columns\r
12814                  *\r
12815                  *  @example\r
12816                  *    // Using `columnDefs`\r
12817                  *    $(document).ready( function() {\r
12818                  *      $('#example').dataTable( {\r
12819                  *        "columnDefs": [\r
12820                  *          { "width": "20%", "targets": [ 0 ] }\r
12821                  *        ]\r
12822                  *      } );\r
12823                  *    } );\r
12824                  *\r
12825                  *  @example\r
12826                  *    // Using `columns`\r
12827                  *    $(document).ready( function() {\r
12828                  *      $('#example').dataTable( {\r
12829                  *        "columns": [\r
12830                  *          { "width": "20%" },\r
12831                  *          null,\r
12832                  *          null,\r
12833                  *          null,\r
12834                  *          null\r
12835                  *        ]\r
12836                  *      } );\r
12837                  *    } );\r
12838                  */\r
12839                 "sWidth": null\r
12840         };\r
12841         \r
12842         _fnHungarianMap( DataTable.defaults.column );\r
12843         \r
12844         \r
12845         \r
12846         /**\r
12847          * DataTables settings object - this holds all the information needed for a\r
12848          * given table, including configuration, data and current application of the\r
12849          * table options. DataTables does not have a single instance for each DataTable\r
12850          * with the settings attached to that instance, but rather instances of the\r
12851          * DataTable "class" are created on-the-fly as needed (typically by a\r
12852          * $().dataTable() call) and the settings object is then applied to that\r
12853          * instance.\r
12854          *\r
12855          * Note that this object is related to {@link DataTable.defaults} but this\r
12856          * one is the internal data store for DataTables's cache of columns. It should\r
12857          * NOT be manipulated outside of DataTables. Any configuration should be done\r
12858          * through the initialisation options.\r
12859          *  @namespace\r
12860          *  @todo Really should attach the settings object to individual instances so we\r
12861          *    don't need to create new instances on each $().dataTable() call (if the\r
12862          *    table already exists). It would also save passing oSettings around and\r
12863          *    into every single function. However, this is a very significant\r
12864          *    architecture change for DataTables and will almost certainly break\r
12865          *    backwards compatibility with older installations. This is something that\r
12866          *    will be done in 2.0.\r
12867          */\r
12868         DataTable.models.oSettings = {\r
12869                 /**\r
12870                  * Primary features of DataTables and their enablement state.\r
12871                  *  @namespace\r
12872                  */\r
12873                 "oFeatures": {\r
12874         \r
12875                         /**\r
12876                          * Flag to say if DataTables should automatically try to calculate the\r
12877                          * optimum table and columns widths (true) or not (false).\r
12878                          * Note that this parameter will be set by the initialisation routine. To\r
12879                          * set a default use {@link DataTable.defaults}.\r
12880                          *  @type boolean\r
12881                          */\r
12882                         "bAutoWidth": null,\r
12883         \r
12884                         /**\r
12885                          * Delay the creation of TR and TD elements until they are actually\r
12886                          * needed by a driven page draw. This can give a significant speed\r
12887                          * increase for Ajax source and Javascript source data, but makes no\r
12888                          * difference at all fro DOM and server-side processing tables.\r
12889                          * Note that this parameter will be set by the initialisation routine. To\r
12890                          * set a default use {@link DataTable.defaults}.\r
12891                          *  @type boolean\r
12892                          */\r
12893                         "bDeferRender": null,\r
12894         \r
12895                         /**\r
12896                          * Enable filtering on the table or not. Note that if this is disabled\r
12897                          * then there is no filtering at all on the table, including fnFilter.\r
12898                          * To just remove the filtering input use sDom and remove the 'f' option.\r
12899                          * Note that this parameter will be set by the initialisation routine. To\r
12900                          * set a default use {@link DataTable.defaults}.\r
12901                          *  @type boolean\r
12902                          */\r
12903                         "bFilter": null,\r
12904         \r
12905                         /**\r
12906                          * Table information element (the 'Showing x of y records' div) enable\r
12907                          * flag.\r
12908                          * Note that this parameter will be set by the initialisation routine. To\r
12909                          * set a default use {@link DataTable.defaults}.\r
12910                          *  @type boolean\r
12911                          */\r
12912                         "bInfo": null,\r
12913         \r
12914                         /**\r
12915                          * Present a user control allowing the end user to change the page size\r
12916                          * when pagination is enabled.\r
12917                          * Note that this parameter will be set by the initialisation routine. To\r
12918                          * set a default use {@link DataTable.defaults}.\r
12919                          *  @type boolean\r
12920                          */\r
12921                         "bLengthChange": null,\r
12922         \r
12923                         /**\r
12924                          * Pagination enabled or not. Note that if this is disabled then length\r
12925                          * changing must also be disabled.\r
12926                          * Note that this parameter will be set by the initialisation routine. To\r
12927                          * set a default use {@link DataTable.defaults}.\r
12928                          *  @type boolean\r
12929                          */\r
12930                         "bPaginate": null,\r
12931         \r
12932                         /**\r
12933                          * Processing indicator enable flag whenever DataTables is enacting a\r
12934                          * user request - typically an Ajax request for server-side processing.\r
12935                          * Note that this parameter will be set by the initialisation routine. To\r
12936                          * set a default use {@link DataTable.defaults}.\r
12937                          *  @type boolean\r
12938                          */\r
12939                         "bProcessing": null,\r
12940         \r
12941                         /**\r
12942                          * Server-side processing enabled flag - when enabled DataTables will\r
12943                          * get all data from the server for every draw - there is no filtering,\r
12944                          * sorting or paging done on the client-side.\r
12945                          * Note that this parameter will be set by the initialisation routine. To\r
12946                          * set a default use {@link DataTable.defaults}.\r
12947                          *  @type boolean\r
12948                          */\r
12949                         "bServerSide": null,\r
12950         \r
12951                         /**\r
12952                          * Sorting enablement flag.\r
12953                          * Note that this parameter will be set by the initialisation routine. To\r
12954                          * set a default use {@link DataTable.defaults}.\r
12955                          *  @type boolean\r
12956                          */\r
12957                         "bSort": null,\r
12958         \r
12959                         /**\r
12960                          * Multi-column sorting\r
12961                          * Note that this parameter will be set by the initialisation routine. To\r
12962                          * set a default use {@link DataTable.defaults}.\r
12963                          *  @type boolean\r
12964                          */\r
12965                         "bSortMulti": null,\r
12966         \r
12967                         /**\r
12968                          * Apply a class to the columns which are being sorted to provide a\r
12969                          * visual highlight or not. This can slow things down when enabled since\r
12970                          * there is a lot of DOM interaction.\r
12971                          * Note that this parameter will be set by the initialisation routine. To\r
12972                          * set a default use {@link DataTable.defaults}.\r
12973                          *  @type boolean\r
12974                          */\r
12975                         "bSortClasses": null,\r
12976         \r
12977                         /**\r
12978                          * State saving enablement flag.\r
12979                          * Note that this parameter will be set by the initialisation routine. To\r
12980                          * set a default use {@link DataTable.defaults}.\r
12981                          *  @type boolean\r
12982                          */\r
12983                         "bStateSave": null\r
12984                 },\r
12985         \r
12986         \r
12987                 /**\r
12988                  * Scrolling settings for a table.\r
12989                  *  @namespace\r
12990                  */\r
12991                 "oScroll": {\r
12992                         /**\r
12993                          * When the table is shorter in height than sScrollY, collapse the\r
12994                          * table container down to the height of the table (when true).\r
12995                          * Note that this parameter will be set by the initialisation routine. To\r
12996                          * set a default use {@link DataTable.defaults}.\r
12997                          *  @type boolean\r
12998                          */\r
12999                         "bCollapse": null,\r
13000         \r
13001                         /**\r
13002                          * Width of the scrollbar for the web-browser's platform. Calculated\r
13003                          * during table initialisation.\r
13004                          *  @type int\r
13005                          *  @default 0\r
13006                          */\r
13007                         "iBarWidth": 0,\r
13008         \r
13009                         /**\r
13010                          * Viewport width for horizontal scrolling. Horizontal scrolling is\r
13011                          * disabled if an empty string.\r
13012                          * Note that this parameter will be set by the initialisation routine. To\r
13013                          * set a default use {@link DataTable.defaults}.\r
13014                          *  @type string\r
13015                          */\r
13016                         "sX": null,\r
13017         \r
13018                         /**\r
13019                          * Width to expand the table to when using x-scrolling. Typically you\r
13020                          * should not need to use this.\r
13021                          * Note that this parameter will be set by the initialisation routine. To\r
13022                          * set a default use {@link DataTable.defaults}.\r
13023                          *  @type string\r
13024                          *  @deprecated\r
13025                          */\r
13026                         "sXInner": null,\r
13027         \r
13028                         /**\r
13029                          * Viewport height for vertical scrolling. Vertical scrolling is disabled\r
13030                          * if an empty string.\r
13031                          * Note that this parameter will be set by the initialisation routine. To\r
13032                          * set a default use {@link DataTable.defaults}.\r
13033                          *  @type string\r
13034                          */\r
13035                         "sY": null\r
13036                 },\r
13037         \r
13038                 /**\r
13039                  * Language information for the table.\r
13040                  *  @namespace\r
13041                  *  @extends DataTable.defaults.oLanguage\r
13042                  */\r
13043                 "oLanguage": {\r
13044                         /**\r
13045                          * Information callback function. See\r
13046                          * {@link DataTable.defaults.fnInfoCallback}\r
13047                          *  @type function\r
13048                          *  @default null\r
13049                          */\r
13050                         "fnInfoCallback": null\r
13051                 },\r
13052         \r
13053                 /**\r
13054                  * Browser support parameters\r
13055                  *  @namespace\r
13056                  */\r
13057                 "oBrowser": {\r
13058                         /**\r
13059                          * Indicate if the browser incorrectly calculates width:100% inside a\r
13060                          * scrolling element (IE6/7)\r
13061                          *  @type boolean\r
13062                          *  @default false\r
13063                          */\r
13064                         "bScrollOversize": false,\r
13065         \r
13066                         /**\r
13067                          * Determine if the vertical scrollbar is on the right or left of the\r
13068                          * scrolling container - needed for rtl language layout, although not\r
13069                          * all browsers move the scrollbar (Safari).\r
13070                          *  @type boolean\r
13071                          *  @default false\r
13072                          */\r
13073                         "bScrollbarLeft": false,\r
13074         \r
13075                         /**\r
13076                          * Flag for if `getBoundingClientRect` is fully supported or not\r
13077                          *  @type boolean\r
13078                          *  @default false\r
13079                          */\r
13080                         "bBounding": false,\r
13081         \r
13082                         /**\r
13083                          * Browser scrollbar width\r
13084                          *  @type integer\r
13085                          *  @default 0\r
13086                          */\r
13087                         "barWidth": 0\r
13088                 },\r
13089         \r
13090         \r
13091                 "ajax": null,\r
13092         \r
13093         \r
13094                 /**\r
13095                  * Array referencing the nodes which are used for the features. The\r
13096                  * parameters of this object match what is allowed by sDom - i.e.\r
13097                  *   <ul>\r
13098                  *     <li>'l' - Length changing</li>\r
13099                  *     <li>'f' - Filtering input</li>\r
13100                  *     <li>'t' - The table!</li>\r
13101                  *     <li>'i' - Information</li>\r
13102                  *     <li>'p' - Pagination</li>\r
13103                  *     <li>'r' - pRocessing</li>\r
13104                  *   </ul>\r
13105                  *  @type array\r
13106                  *  @default []\r
13107                  */\r
13108                 "aanFeatures": [],\r
13109         \r
13110                 /**\r
13111                  * Store data information - see {@link DataTable.models.oRow} for detailed\r
13112                  * information.\r
13113                  *  @type array\r
13114                  *  @default []\r
13115                  */\r
13116                 "aoData": [],\r
13117         \r
13118                 /**\r
13119                  * Array of indexes which are in the current display (after filtering etc)\r
13120                  *  @type array\r
13121                  *  @default []\r
13122                  */\r
13123                 "aiDisplay": [],\r
13124         \r
13125                 /**\r
13126                  * Array of indexes for display - no filtering\r
13127                  *  @type array\r
13128                  *  @default []\r
13129                  */\r
13130                 "aiDisplayMaster": [],\r
13131         \r
13132                 /**\r
13133                  * Map of row ids to data indexes\r
13134                  *  @type object\r
13135                  *  @default {}\r
13136                  */\r
13137                 "aIds": {},\r
13138         \r
13139                 /**\r
13140                  * Store information about each column that is in use\r
13141                  *  @type array\r
13142                  *  @default []\r
13143                  */\r
13144                 "aoColumns": [],\r
13145         \r
13146                 /**\r
13147                  * Store information about the table's header\r
13148                  *  @type array\r
13149                  *  @default []\r
13150                  */\r
13151                 "aoHeader": [],\r
13152         \r
13153                 /**\r
13154                  * Store information about the table's footer\r
13155                  *  @type array\r
13156                  *  @default []\r
13157                  */\r
13158                 "aoFooter": [],\r
13159         \r
13160                 /**\r
13161                  * Store the applied global search information in case we want to force a\r
13162                  * research or compare the old search to a new one.\r
13163                  * Note that this parameter will be set by the initialisation routine. To\r
13164                  * set a default use {@link DataTable.defaults}.\r
13165                  *  @namespace\r
13166                  *  @extends DataTable.models.oSearch\r
13167                  */\r
13168                 "oPreviousSearch": {},\r
13169         \r
13170                 /**\r
13171                  * Store the applied search for each column - see\r
13172                  * {@link DataTable.models.oSearch} for the format that is used for the\r
13173                  * filtering information for each column.\r
13174                  *  @type array\r
13175                  *  @default []\r
13176                  */\r
13177                 "aoPreSearchCols": [],\r
13178         \r
13179                 /**\r
13180                  * Sorting that is applied to the table. Note that the inner arrays are\r
13181                  * used in the following manner:\r
13182                  * <ul>\r
13183                  *   <li>Index 0 - column number</li>\r
13184                  *   <li>Index 1 - current sorting direction</li>\r
13185                  * </ul>\r
13186                  * Note that this parameter will be set by the initialisation routine. To\r
13187                  * set a default use {@link DataTable.defaults}.\r
13188                  *  @type array\r
13189                  *  @todo These inner arrays should really be objects\r
13190                  */\r
13191                 "aaSorting": null,\r
13192         \r
13193                 /**\r
13194                  * Sorting that is always applied to the table (i.e. prefixed in front of\r
13195                  * aaSorting).\r
13196                  * Note that this parameter will be set by the initialisation routine. To\r
13197                  * set a default use {@link DataTable.defaults}.\r
13198                  *  @type array\r
13199                  *  @default []\r
13200                  */\r
13201                 "aaSortingFixed": [],\r
13202         \r
13203                 /**\r
13204                  * Classes to use for the striping of a table.\r
13205                  * Note that this parameter will be set by the initialisation routine. To\r
13206                  * set a default use {@link DataTable.defaults}.\r
13207                  *  @type array\r
13208                  *  @default []\r
13209                  */\r
13210                 "asStripeClasses": null,\r
13211         \r
13212                 /**\r
13213                  * If restoring a table - we should restore its striping classes as well\r
13214                  *  @type array\r
13215                  *  @default []\r
13216                  */\r
13217                 "asDestroyStripes": [],\r
13218         \r
13219                 /**\r
13220                  * If restoring a table - we should restore its width\r
13221                  *  @type int\r
13222                  *  @default 0\r
13223                  */\r
13224                 "sDestroyWidth": 0,\r
13225         \r
13226                 /**\r
13227                  * Callback functions array for every time a row is inserted (i.e. on a draw).\r
13228                  *  @type array\r
13229                  *  @default []\r
13230                  */\r
13231                 "aoRowCallback": [],\r
13232         \r
13233                 /**\r
13234                  * Callback functions for the header on each draw.\r
13235                  *  @type array\r
13236                  *  @default []\r
13237                  */\r
13238                 "aoHeaderCallback": [],\r
13239         \r
13240                 /**\r
13241                  * Callback function for the footer on each draw.\r
13242                  *  @type array\r
13243                  *  @default []\r
13244                  */\r
13245                 "aoFooterCallback": [],\r
13246         \r
13247                 /**\r
13248                  * Array of callback functions for draw callback functions\r
13249                  *  @type array\r
13250                  *  @default []\r
13251                  */\r
13252                 "aoDrawCallback": [],\r
13253         \r
13254                 /**\r
13255                  * Array of callback functions for row created function\r
13256                  *  @type array\r
13257                  *  @default []\r
13258                  */\r
13259                 "aoRowCreatedCallback": [],\r
13260         \r
13261                 /**\r
13262                  * Callback functions for just before the table is redrawn. A return of\r
13263                  * false will be used to cancel the draw.\r
13264                  *  @type array\r
13265                  *  @default []\r
13266                  */\r
13267                 "aoPreDrawCallback": [],\r
13268         \r
13269                 /**\r
13270                  * Callback functions for when the table has been initialised.\r
13271                  *  @type array\r
13272                  *  @default []\r
13273                  */\r
13274                 "aoInitComplete": [],\r
13275         \r
13276         \r
13277                 /**\r
13278                  * Callbacks for modifying the settings to be stored for state saving, prior to\r
13279                  * saving state.\r
13280                  *  @type array\r
13281                  *  @default []\r
13282                  */\r
13283                 "aoStateSaveParams": [],\r
13284         \r
13285                 /**\r
13286                  * Callbacks for modifying the settings that have been stored for state saving\r
13287                  * prior to using the stored values to restore the state.\r
13288                  *  @type array\r
13289                  *  @default []\r
13290                  */\r
13291                 "aoStateLoadParams": [],\r
13292         \r
13293                 /**\r
13294                  * Callbacks for operating on the settings object once the saved state has been\r
13295                  * loaded\r
13296                  *  @type array\r
13297                  *  @default []\r
13298                  */\r
13299                 "aoStateLoaded": [],\r
13300         \r
13301                 /**\r
13302                  * Cache the table ID for quick access\r
13303                  *  @type string\r
13304                  *  @default <i>Empty string</i>\r
13305                  */\r
13306                 "sTableId": "",\r
13307         \r
13308                 /**\r
13309                  * The TABLE node for the main table\r
13310                  *  @type node\r
13311                  *  @default null\r
13312                  */\r
13313                 "nTable": null,\r
13314         \r
13315                 /**\r
13316                  * Permanent ref to the thead element\r
13317                  *  @type node\r
13318                  *  @default null\r
13319                  */\r
13320                 "nTHead": null,\r
13321         \r
13322                 /**\r
13323                  * Permanent ref to the tfoot element - if it exists\r
13324                  *  @type node\r
13325                  *  @default null\r
13326                  */\r
13327                 "nTFoot": null,\r
13328         \r
13329                 /**\r
13330                  * Permanent ref to the tbody element\r
13331                  *  @type node\r
13332                  *  @default null\r
13333                  */\r
13334                 "nTBody": null,\r
13335         \r
13336                 /**\r
13337                  * Cache the wrapper node (contains all DataTables controlled elements)\r
13338                  *  @type node\r
13339                  *  @default null\r
13340                  */\r
13341                 "nTableWrapper": null,\r
13342         \r
13343                 /**\r
13344                  * Indicate if when using server-side processing the loading of data\r
13345                  * should be deferred until the second draw.\r
13346                  * Note that this parameter will be set by the initialisation routine. To\r
13347                  * set a default use {@link DataTable.defaults}.\r
13348                  *  @type boolean\r
13349                  *  @default false\r
13350                  */\r
13351                 "bDeferLoading": false,\r
13352         \r
13353                 /**\r
13354                  * Indicate if all required information has been read in\r
13355                  *  @type boolean\r
13356                  *  @default false\r
13357                  */\r
13358                 "bInitialised": false,\r
13359         \r
13360                 /**\r
13361                  * Information about open rows. Each object in the array has the parameters\r
13362                  * 'nTr' and 'nParent'\r
13363                  *  @type array\r
13364                  *  @default []\r
13365                  */\r
13366                 "aoOpenRows": [],\r
13367         \r
13368                 /**\r
13369                  * Dictate the positioning of DataTables' control elements - see\r
13370                  * {@link DataTable.model.oInit.sDom}.\r
13371                  * Note that this parameter will be set by the initialisation routine. To\r
13372                  * set a default use {@link DataTable.defaults}.\r
13373                  *  @type string\r
13374                  *  @default null\r
13375                  */\r
13376                 "sDom": null,\r
13377         \r
13378                 /**\r
13379                  * Search delay (in mS)\r
13380                  *  @type integer\r
13381                  *  @default null\r
13382                  */\r
13383                 "searchDelay": null,\r
13384         \r
13385                 /**\r
13386                  * Which type of pagination should be used.\r
13387                  * Note that this parameter will be set by the initialisation routine. To\r
13388                  * set a default use {@link DataTable.defaults}.\r
13389                  *  @type string\r
13390                  *  @default two_button\r
13391                  */\r
13392                 "sPaginationType": "two_button",\r
13393         \r
13394                 /**\r
13395                  * The state duration (for `stateSave`) in seconds.\r
13396                  * Note that this parameter will be set by the initialisation routine. To\r
13397                  * set a default use {@link DataTable.defaults}.\r
13398                  *  @type int\r
13399                  *  @default 0\r
13400                  */\r
13401                 "iStateDuration": 0,\r
13402         \r
13403                 /**\r
13404                  * Array of callback functions for state saving. Each array element is an\r
13405                  * object with the following parameters:\r
13406                  *   <ul>\r
13407                  *     <li>function:fn - function to call. Takes two parameters, oSettings\r
13408                  *       and the JSON string to save that has been thus far created. Returns\r
13409                  *       a JSON string to be inserted into a json object\r
13410                  *       (i.e. '"param": [ 0, 1, 2]')</li>\r
13411                  *     <li>string:sName - name of callback</li>\r
13412                  *   </ul>\r
13413                  *  @type array\r
13414                  *  @default []\r
13415                  */\r
13416                 "aoStateSave": [],\r
13417         \r
13418                 /**\r
13419                  * Array of callback functions for state loading. Each array element is an\r
13420                  * object with the following parameters:\r
13421                  *   <ul>\r
13422                  *     <li>function:fn - function to call. Takes two parameters, oSettings\r
13423                  *       and the object stored. May return false to cancel state loading</li>\r
13424                  *     <li>string:sName - name of callback</li>\r
13425                  *   </ul>\r
13426                  *  @type array\r
13427                  *  @default []\r
13428                  */\r
13429                 "aoStateLoad": [],\r
13430         \r
13431                 /**\r
13432                  * State that was saved. Useful for back reference\r
13433                  *  @type object\r
13434                  *  @default null\r
13435                  */\r
13436                 "oSavedState": null,\r
13437         \r
13438                 /**\r
13439                  * State that was loaded. Useful for back reference\r
13440                  *  @type object\r
13441                  *  @default null\r
13442                  */\r
13443                 "oLoadedState": null,\r
13444         \r
13445                 /**\r
13446                  * Source url for AJAX data for the table.\r
13447                  * Note that this parameter will be set by the initialisation routine. To\r
13448                  * set a default use {@link DataTable.defaults}.\r
13449                  *  @type string\r
13450                  *  @default null\r
13451                  */\r
13452                 "sAjaxSource": null,\r
13453         \r
13454                 /**\r
13455                  * Property from a given object from which to read the table data from. This\r
13456                  * can be an empty string (when not server-side processing), in which case\r
13457                  * it is  assumed an an array is given directly.\r
13458                  * Note that this parameter will be set by the initialisation routine. To\r
13459                  * set a default use {@link DataTable.defaults}.\r
13460                  *  @type string\r
13461                  */\r
13462                 "sAjaxDataProp": null,\r
13463         \r
13464                 /**\r
13465                  * Note if draw should be blocked while getting data\r
13466                  *  @type boolean\r
13467                  *  @default true\r
13468                  */\r
13469                 "bAjaxDataGet": true,\r
13470         \r
13471                 /**\r
13472                  * The last jQuery XHR object that was used for server-side data gathering.\r
13473                  * This can be used for working with the XHR information in one of the\r
13474                  * callbacks\r
13475                  *  @type object\r
13476                  *  @default null\r
13477                  */\r
13478                 "jqXHR": null,\r
13479         \r
13480                 /**\r
13481                  * JSON returned from the server in the last Ajax request\r
13482                  *  @type object\r
13483                  *  @default undefined\r
13484                  */\r
13485                 "json": undefined,\r
13486         \r
13487                 /**\r
13488                  * Data submitted as part of the last Ajax request\r
13489                  *  @type object\r
13490                  *  @default undefined\r
13491                  */\r
13492                 "oAjaxData": undefined,\r
13493         \r
13494                 /**\r
13495                  * Function to get the server-side data.\r
13496                  * Note that this parameter will be set by the initialisation routine. To\r
13497                  * set a default use {@link DataTable.defaults}.\r
13498                  *  @type function\r
13499                  */\r
13500                 "fnServerData": null,\r
13501         \r
13502                 /**\r
13503                  * Functions which are called prior to sending an Ajax request so extra\r
13504                  * parameters can easily be sent to the server\r
13505                  *  @type array\r
13506                  *  @default []\r
13507                  */\r
13508                 "aoServerParams": [],\r
13509         \r
13510                 /**\r
13511                  * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if\r
13512                  * required).\r
13513                  * Note that this parameter will be set by the initialisation routine. To\r
13514                  * set a default use {@link DataTable.defaults}.\r
13515                  *  @type string\r
13516                  */\r
13517                 "sServerMethod": null,\r
13518         \r
13519                 /**\r
13520                  * Format numbers for display.\r
13521                  * Note that this parameter will be set by the initialisation routine. To\r
13522                  * set a default use {@link DataTable.defaults}.\r
13523                  *  @type function\r
13524                  */\r
13525                 "fnFormatNumber": null,\r
13526         \r
13527                 /**\r
13528                  * List of options that can be used for the user selectable length menu.\r
13529                  * Note that this parameter will be set by the initialisation routine. To\r
13530                  * set a default use {@link DataTable.defaults}.\r
13531                  *  @type array\r
13532                  *  @default []\r
13533                  */\r
13534                 "aLengthMenu": null,\r
13535         \r
13536                 /**\r
13537                  * Counter for the draws that the table does. Also used as a tracker for\r
13538                  * server-side processing\r
13539                  *  @type int\r
13540                  *  @default 0\r
13541                  */\r
13542                 "iDraw": 0,\r
13543         \r
13544                 /**\r
13545                  * Indicate if a redraw is being done - useful for Ajax\r
13546                  *  @type boolean\r
13547                  *  @default false\r
13548                  */\r
13549                 "bDrawing": false,\r
13550         \r
13551                 /**\r
13552                  * Draw index (iDraw) of the last error when parsing the returned data\r
13553                  *  @type int\r
13554                  *  @default -1\r
13555                  */\r
13556                 "iDrawError": -1,\r
13557         \r
13558                 /**\r
13559                  * Paging display length\r
13560                  *  @type int\r
13561                  *  @default 10\r
13562                  */\r
13563                 "_iDisplayLength": 10,\r
13564         \r
13565                 /**\r
13566                  * Paging start point - aiDisplay index\r
13567                  *  @type int\r
13568                  *  @default 0\r
13569                  */\r
13570                 "_iDisplayStart": 0,\r
13571         \r
13572                 /**\r
13573                  * Server-side processing - number of records in the result set\r
13574                  * (i.e. before filtering), Use fnRecordsTotal rather than\r
13575                  * this property to get the value of the number of records, regardless of\r
13576                  * the server-side processing setting.\r
13577                  *  @type int\r
13578                  *  @default 0\r
13579                  *  @private\r
13580                  */\r
13581                 "_iRecordsTotal": 0,\r
13582         \r
13583                 /**\r
13584                  * Server-side processing - number of records in the current display set\r
13585                  * (i.e. after filtering). Use fnRecordsDisplay rather than\r
13586                  * this property to get the value of the number of records, regardless of\r
13587                  * the server-side processing setting.\r
13588                  *  @type boolean\r
13589                  *  @default 0\r
13590                  *  @private\r
13591                  */\r
13592                 "_iRecordsDisplay": 0,\r
13593         \r
13594                 /**\r
13595                  * Flag to indicate if jQuery UI marking and classes should be used.\r
13596                  * Note that this parameter will be set by the initialisation routine. To\r
13597                  * set a default use {@link DataTable.defaults}.\r
13598                  *  @type boolean\r
13599                  */\r
13600                 "bJUI": null,\r
13601         \r
13602                 /**\r
13603                  * The classes to use for the table\r
13604                  *  @type object\r
13605                  *  @default {}\r
13606                  */\r
13607                 "oClasses": {},\r
13608         \r
13609                 /**\r
13610                  * Flag attached to the settings object so you can check in the draw\r
13611                  * callback if filtering has been done in the draw. Deprecated in favour of\r
13612                  * events.\r
13613                  *  @type boolean\r
13614                  *  @default false\r
13615                  *  @deprecated\r
13616                  */\r
13617                 "bFiltered": false,\r
13618         \r
13619                 /**\r
13620                  * Flag attached to the settings object so you can check in the draw\r
13621                  * callback if sorting has been done in the draw. Deprecated in favour of\r
13622                  * events.\r
13623                  *  @type boolean\r
13624                  *  @default false\r
13625                  *  @deprecated\r
13626                  */\r
13627                 "bSorted": false,\r
13628         \r
13629                 /**\r
13630                  * Indicate that if multiple rows are in the header and there is more than\r
13631                  * one unique cell per column, if the top one (true) or bottom one (false)\r
13632                  * should be used for sorting / title by DataTables.\r
13633                  * Note that this parameter will be set by the initialisation routine. To\r
13634                  * set a default use {@link DataTable.defaults}.\r
13635                  *  @type boolean\r
13636                  */\r
13637                 "bSortCellsTop": null,\r
13638         \r
13639                 /**\r
13640                  * Initialisation object that is used for the table\r
13641                  *  @type object\r
13642                  *  @default null\r
13643                  */\r
13644                 "oInit": null,\r
13645         \r
13646                 /**\r
13647                  * Destroy callback functions - for plug-ins to attach themselves to the\r
13648                  * destroy so they can clean up markup and events.\r
13649                  *  @type array\r
13650                  *  @default []\r
13651                  */\r
13652                 "aoDestroyCallback": [],\r
13653         \r
13654         \r
13655                 /**\r
13656                  * Get the number of records in the current record set, before filtering\r
13657                  *  @type function\r
13658                  */\r
13659                 "fnRecordsTotal": function ()\r
13660                 {\r
13661                         return _fnDataSource( this ) == 'ssp' ?\r
13662                                 this._iRecordsTotal * 1 :\r
13663                                 this.aiDisplayMaster.length;\r
13664                 },\r
13665         \r
13666                 /**\r
13667                  * Get the number of records in the current record set, after filtering\r
13668                  *  @type function\r
13669                  */\r
13670                 "fnRecordsDisplay": function ()\r
13671                 {\r
13672                         return _fnDataSource( this ) == 'ssp' ?\r
13673                                 this._iRecordsDisplay * 1 :\r
13674                                 this.aiDisplay.length;\r
13675                 },\r
13676         \r
13677                 /**\r
13678                  * Get the display end point - aiDisplay index\r
13679                  *  @type function\r
13680                  */\r
13681                 "fnDisplayEnd": function ()\r
13682                 {\r
13683                         var\r
13684                                 len      = this._iDisplayLength,\r
13685                                 start    = this._iDisplayStart,\r
13686                                 calc     = start + len,\r
13687                                 records  = this.aiDisplay.length,\r
13688                                 features = this.oFeatures,\r
13689                                 paginate = features.bPaginate;\r
13690         \r
13691                         if ( features.bServerSide ) {\r
13692                                 return paginate === false || len === -1 ?\r
13693                                         start + records :\r
13694                                         Math.min( start+len, this._iRecordsDisplay );\r
13695                         }\r
13696                         else {\r
13697                                 return ! paginate || calc>records || len===-1 ?\r
13698                                         records :\r
13699                                         calc;\r
13700                         }\r
13701                 },\r
13702         \r
13703                 /**\r
13704                  * The DataTables object for this table\r
13705                  *  @type object\r
13706                  *  @default null\r
13707                  */\r
13708                 "oInstance": null,\r
13709         \r
13710                 /**\r
13711                  * Unique identifier for each instance of the DataTables object. If there\r
13712                  * is an ID on the table node, then it takes that value, otherwise an\r
13713                  * incrementing internal counter is used.\r
13714                  *  @type string\r
13715                  *  @default null\r
13716                  */\r
13717                 "sInstance": null,\r
13718         \r
13719                 /**\r
13720                  * tabindex attribute value that is added to DataTables control elements, allowing\r
13721                  * keyboard navigation of the table and its controls.\r
13722                  */\r
13723                 "iTabIndex": 0,\r
13724         \r
13725                 /**\r
13726                  * DIV container for the footer scrolling table if scrolling\r
13727                  */\r
13728                 "nScrollHead": null,\r
13729         \r
13730                 /**\r
13731                  * DIV container for the footer scrolling table if scrolling\r
13732                  */\r
13733                 "nScrollFoot": null,\r
13734         \r
13735                 /**\r
13736                  * Last applied sort\r
13737                  *  @type array\r
13738                  *  @default []\r
13739                  */\r
13740                 "aLastSort": [],\r
13741         \r
13742                 /**\r
13743                  * Stored plug-in instances\r
13744                  *  @type object\r
13745                  *  @default {}\r
13746                  */\r
13747                 "oPlugins": {},\r
13748         \r
13749                 /**\r
13750                  * Function used to get a row's id from the row's data\r
13751                  *  @type function\r
13752                  *  @default null\r
13753                  */\r
13754                 "rowIdFn": null,\r
13755         \r
13756                 /**\r
13757                  * Data location where to store a row's id\r
13758                  *  @type string\r
13759                  *  @default null\r
13760                  */\r
13761                 "rowId": null\r
13762         };\r
13763 \r
13764         /**\r
13765          * Extension object for DataTables that is used to provide all extension\r
13766          * options.\r
13767          *\r
13768          * Note that the `DataTable.ext` object is available through\r
13769          * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is\r
13770          * also aliased to `jQuery.fn.dataTableExt` for historic reasons.\r
13771          *  @namespace\r
13772          *  @extends DataTable.models.ext\r
13773          */\r
13774         \r
13775         \r
13776         /**\r
13777          * DataTables extensions\r
13778          * \r
13779          * This namespace acts as a collection area for plug-ins that can be used to\r
13780          * extend DataTables capabilities. Indeed many of the build in methods\r
13781          * use this method to provide their own capabilities (sorting methods for\r
13782          * example).\r
13783          *\r
13784          * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy\r
13785          * reasons\r
13786          *\r
13787          *  @namespace\r
13788          */\r
13789         DataTable.ext = _ext = {\r
13790                 /**\r
13791                  * Buttons. For use with the Buttons extension for DataTables. This is\r
13792                  * defined here so other extensions can define buttons regardless of load\r
13793                  * order. It is _not_ used by DataTables core.\r
13794                  *\r
13795                  *  @type object\r
13796                  *  @default {}\r
13797                  */\r
13798                 buttons: {},\r
13799         \r
13800         \r
13801                 /**\r
13802                  * Element class names\r
13803                  *\r
13804                  *  @type object\r
13805                  *  @default {}\r
13806                  */\r
13807                 classes: {},\r
13808         \r
13809         \r
13810                 /**\r
13811                  * DataTables build type (expanded by the download builder)\r
13812                  *\r
13813                  *  @type string\r
13814                  */\r
13815                 builder: "-source-",\r
13816         \r
13817         \r
13818                 /**\r
13819                  * Error reporting.\r
13820                  * \r
13821                  * How should DataTables report an error. Can take the value 'alert',\r
13822                  * 'throw', 'none' or a function.\r
13823                  *\r
13824                  *  @type string|function\r
13825                  *  @default alert\r
13826                  */\r
13827                 errMode: "alert",\r
13828         \r
13829         \r
13830                 /**\r
13831                  * Feature plug-ins.\r
13832                  * \r
13833                  * This is an array of objects which describe the feature plug-ins that are\r
13834                  * available to DataTables. These feature plug-ins are then available for\r
13835                  * use through the `dom` initialisation option.\r
13836                  * \r
13837                  * Each feature plug-in is described by an object which must have the\r
13838                  * following properties:\r
13839                  * \r
13840                  * * `fnInit` - function that is used to initialise the plug-in,\r
13841                  * * `cFeature` - a character so the feature can be enabled by the `dom`\r
13842                  *   instillation option. This is case sensitive.\r
13843                  *\r
13844                  * The `fnInit` function has the following input parameters:\r
13845                  *\r
13846                  * 1. `{object}` DataTables settings object: see\r
13847                  *    {@link DataTable.models.oSettings}\r
13848                  *\r
13849                  * And the following return is expected:\r
13850                  * \r
13851                  * * {node|null} The element which contains your feature. Note that the\r
13852                  *   return may also be void if your plug-in does not require to inject any\r
13853                  *   DOM elements into DataTables control (`dom`) - for example this might\r
13854                  *   be useful when developing a plug-in which allows table control via\r
13855                  *   keyboard entry\r
13856                  *\r
13857                  *  @type array\r
13858                  *\r
13859                  *  @example\r
13860                  *    $.fn.dataTable.ext.features.push( {\r
13861                  *      "fnInit": function( oSettings ) {\r
13862                  *        return new TableTools( { "oDTSettings": oSettings } );\r
13863                  *      },\r
13864                  *      "cFeature": "T"\r
13865                  *    } );\r
13866                  */\r
13867                 feature: [],\r
13868         \r
13869         \r
13870                 /**\r
13871                  * Row searching.\r
13872                  * \r
13873                  * This method of searching is complimentary to the default type based\r
13874                  * searching, and a lot more comprehensive as it allows you complete control\r
13875                  * over the searching logic. Each element in this array is a function\r
13876                  * (parameters described below) that is called for every row in the table,\r
13877                  * and your logic decides if it should be included in the searching data set\r
13878                  * or not.\r
13879                  *\r
13880                  * Searching functions have the following input parameters:\r
13881                  *\r
13882                  * 1. `{object}` DataTables settings object: see\r
13883                  *    {@link DataTable.models.oSettings}\r
13884                  * 2. `{array|object}` Data for the row to be processed (same as the\r
13885                  *    original format that was passed in as the data source, or an array\r
13886                  *    from a DOM data source\r
13887                  * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which\r
13888                  *    can be useful to retrieve the `TR` element if you need DOM interaction.\r
13889                  *\r
13890                  * And the following return is expected:\r
13891                  *\r
13892                  * * {boolean} Include the row in the searched result set (true) or not\r
13893                  *   (false)\r
13894                  *\r
13895                  * Note that as with the main search ability in DataTables, technically this\r
13896                  * is "filtering", since it is subtractive. However, for consistency in\r
13897                  * naming we call it searching here.\r
13898                  *\r
13899                  *  @type array\r
13900                  *  @default []\r
13901                  *\r
13902                  *  @example\r
13903                  *    // The following example shows custom search being applied to the\r
13904                  *    // fourth column (i.e. the data[3] index) based on two input values\r
13905                  *    // from the end-user, matching the data in a certain range.\r
13906                  *    $.fn.dataTable.ext.search.push(\r
13907                  *      function( settings, data, dataIndex ) {\r
13908                  *        var min = document.getElementById('min').value * 1;\r
13909                  *        var max = document.getElementById('max').value * 1;\r
13910                  *        var version = data[3] == "-" ? 0 : data[3]*1;\r
13911                  *\r
13912                  *        if ( min == "" && max == "" ) {\r
13913                  *          return true;\r
13914                  *        }\r
13915                  *        else if ( min == "" && version < max ) {\r
13916                  *          return true;\r
13917                  *        }\r
13918                  *        else if ( min < version && "" == max ) {\r
13919                  *          return true;\r
13920                  *        }\r
13921                  *        else if ( min < version && version < max ) {\r
13922                  *          return true;\r
13923                  *        }\r
13924                  *        return false;\r
13925                  *      }\r
13926                  *    );\r
13927                  */\r
13928                 search: [],\r
13929         \r
13930         \r
13931                 /**\r
13932                  * Selector extensions\r
13933                  *\r
13934                  * The `selector` option can be used to extend the options available for the\r
13935                  * selector modifier options (`selector-modifier` object data type) that\r
13936                  * each of the three built in selector types offer (row, column and cell +\r
13937                  * their plural counterparts). For example the Select extension uses this\r
13938                  * mechanism to provide an option to select only rows, columns and cells\r
13939                  * that have been marked as selected by the end user (`{selected: true}`),\r
13940                  * which can be used in conjunction with the existing built in selector\r
13941                  * options.\r
13942                  *\r
13943                  * Each property is an array to which functions can be pushed. The functions\r
13944                  * take three attributes:\r
13945                  *\r
13946                  * * Settings object for the host table\r
13947                  * * Options object (`selector-modifier` object type)\r
13948                  * * Array of selected item indexes\r
13949                  *\r
13950                  * The return is an array of the resulting item indexes after the custom\r
13951                  * selector has been applied.\r
13952                  *\r
13953                  *  @type object\r
13954                  */\r
13955                 selector: {\r
13956                         cell: [],\r
13957                         column: [],\r
13958                         row: []\r
13959                 },\r
13960         \r
13961         \r
13962                 /**\r
13963                  * Internal functions, exposed for used in plug-ins.\r
13964                  * \r
13965                  * Please note that you should not need to use the internal methods for\r
13966                  * anything other than a plug-in (and even then, try to avoid if possible).\r
13967                  * The internal function may change between releases.\r
13968                  *\r
13969                  *  @type object\r
13970                  *  @default {}\r
13971                  */\r
13972                 internal: {},\r
13973         \r
13974         \r
13975                 /**\r
13976                  * Legacy configuration options. Enable and disable legacy options that\r
13977                  * are available in DataTables.\r
13978                  *\r
13979                  *  @type object\r
13980                  */\r
13981                 legacy: {\r
13982                         /**\r
13983                          * Enable / disable DataTables 1.9 compatible server-side processing\r
13984                          * requests\r
13985                          *\r
13986                          *  @type boolean\r
13987                          *  @default null\r
13988                          */\r
13989                         ajax: null\r
13990                 },\r
13991         \r
13992         \r
13993                 /**\r
13994                  * Pagination plug-in methods.\r
13995                  * \r
13996                  * Each entry in this object is a function and defines which buttons should\r
13997                  * be shown by the pagination rendering method that is used for the table:\r
13998                  * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the\r
13999                  * buttons are displayed in the document, while the functions here tell it\r
14000                  * what buttons to display. This is done by returning an array of button\r
14001                  * descriptions (what each button will do).\r
14002                  *\r
14003                  * Pagination types (the four built in options and any additional plug-in\r
14004                  * options defined here) can be used through the `paginationType`\r
14005                  * initialisation parameter.\r
14006                  *\r
14007                  * The functions defined take two parameters:\r
14008                  *\r
14009                  * 1. `{int} page` The current page index\r
14010                  * 2. `{int} pages` The number of pages in the table\r
14011                  *\r
14012                  * Each function is expected to return an array where each element of the\r
14013                  * array can be one of:\r
14014                  *\r
14015                  * * `first` - Jump to first page when activated\r
14016                  * * `last` - Jump to last page when activated\r
14017                  * * `previous` - Show previous page when activated\r
14018                  * * `next` - Show next page when activated\r
14019                  * * `{int}` - Show page of the index given\r
14020                  * * `{array}` - A nested array containing the above elements to add a\r
14021                  *   containing 'DIV' element (might be useful for styling).\r
14022                  *\r
14023                  * Note that DataTables v1.9- used this object slightly differently whereby\r
14024                  * an object with two functions would be defined for each plug-in. That\r
14025                  * ability is still supported by DataTables 1.10+ to provide backwards\r
14026                  * compatibility, but this option of use is now decremented and no longer\r
14027                  * documented in DataTables 1.10+.\r
14028                  *\r
14029                  *  @type object\r
14030                  *  @default {}\r
14031                  *\r
14032                  *  @example\r
14033                  *    // Show previous, next and current page buttons only\r
14034                  *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {\r
14035                  *      return [ 'previous', page, 'next' ];\r
14036                  *    };\r
14037                  */\r
14038                 pager: {},\r
14039         \r
14040         \r
14041                 renderer: {\r
14042                         pageButton: {},\r
14043                         header: {}\r
14044                 },\r
14045         \r
14046         \r
14047                 /**\r
14048                  * Ordering plug-ins - custom data source\r
14049                  * \r
14050                  * The extension options for ordering of data available here is complimentary\r
14051                  * to the default type based ordering that DataTables typically uses. It\r
14052                  * allows much greater control over the the data that is being used to\r
14053                  * order a column, but is necessarily therefore more complex.\r
14054                  * \r
14055                  * This type of ordering is useful if you want to do ordering based on data\r
14056                  * live from the DOM (for example the contents of an 'input' element) rather\r
14057                  * than just the static string that DataTables knows of.\r
14058                  * \r
14059                  * The way these plug-ins work is that you create an array of the values you\r
14060                  * wish to be ordering for the column in question and then return that\r
14061                  * array. The data in the array much be in the index order of the rows in\r
14062                  * the table (not the currently ordering order!). Which order data gathering\r
14063                  * function is run here depends on the `dt-init columns.orderDataType`\r
14064                  * parameter that is used for the column (if any).\r
14065                  *\r
14066                  * The functions defined take two parameters:\r
14067                  *\r
14068                  * 1. `{object}` DataTables settings object: see\r
14069                  *    {@link DataTable.models.oSettings}\r
14070                  * 2. `{int}` Target column index\r
14071                  *\r
14072                  * Each function is expected to return an array:\r
14073                  *\r
14074                  * * `{array}` Data for the column to be ordering upon\r
14075                  *\r
14076                  *  @type array\r
14077                  *\r
14078                  *  @example\r
14079                  *    // Ordering using `input` node values\r
14080                  *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )\r
14081                  *    {\r
14082                  *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {\r
14083                  *        return $('input', td).val();\r
14084                  *      } );\r
14085                  *    }\r
14086                  */\r
14087                 order: {},\r
14088         \r
14089         \r
14090                 /**\r
14091                  * Type based plug-ins.\r
14092                  *\r
14093                  * Each column in DataTables has a type assigned to it, either by automatic\r
14094                  * detection or by direct assignment using the `type` option for the column.\r
14095                  * The type of a column will effect how it is ordering and search (plug-ins\r
14096                  * can also make use of the column type if required).\r
14097                  *\r
14098                  * @namespace\r
14099                  */\r
14100                 type: {\r
14101                         /**\r
14102                          * Type detection functions.\r
14103                          *\r
14104                          * The functions defined in this object are used to automatically detect\r
14105                          * a column's type, making initialisation of DataTables super easy, even\r
14106                          * when complex data is in the table.\r
14107                          *\r
14108                          * The functions defined take two parameters:\r
14109                          *\r
14110                      *  1. `{*}` Data from the column cell to be analysed\r
14111                      *  2. `{settings}` DataTables settings object. This can be used to\r
14112                      *     perform context specific type detection - for example detection\r
14113                      *     based on language settings such as using a comma for a decimal\r
14114                      *     place. Generally speaking the options from the settings will not\r
14115                      *     be required\r
14116                          *\r
14117                          * Each function is expected to return:\r
14118                          *\r
14119                          * * `{string|null}` Data type detected, or null if unknown (and thus\r
14120                          *   pass it on to the other type detection functions.\r
14121                          *\r
14122                          *  @type array\r
14123                          *\r
14124                          *  @example\r
14125                          *    // Currency type detection plug-in:\r
14126                          *    $.fn.dataTable.ext.type.detect.push(\r
14127                          *      function ( data, settings ) {\r
14128                          *        // Check the numeric part\r
14129                          *        if ( ! $.isNumeric( data.substring(1) ) ) {\r
14130                          *          return null;\r
14131                          *        }\r
14132                          *\r
14133                          *        // Check prefixed by currency\r
14134                          *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {\r
14135                          *          return 'currency';\r
14136                          *        }\r
14137                          *        return null;\r
14138                          *      }\r
14139                          *    );\r
14140                          */\r
14141                         detect: [],\r
14142         \r
14143         \r
14144                         /**\r
14145                          * Type based search formatting.\r
14146                          *\r
14147                          * The type based searching functions can be used to pre-format the\r
14148                          * data to be search on. For example, it can be used to strip HTML\r
14149                          * tags or to de-format telephone numbers for numeric only searching.\r
14150                          *\r
14151                          * Note that is a search is not defined for a column of a given type,\r
14152                          * no search formatting will be performed.\r
14153                          * \r
14154                          * Pre-processing of searching data plug-ins - When you assign the sType\r
14155                          * for a column (or have it automatically detected for you by DataTables\r
14156                          * or a type detection plug-in), you will typically be using this for\r
14157                          * custom sorting, but it can also be used to provide custom searching\r
14158                          * by allowing you to pre-processing the data and returning the data in\r
14159                          * the format that should be searched upon. This is done by adding\r
14160                          * functions this object with a parameter name which matches the sType\r
14161                          * for that target column. This is the corollary of <i>afnSortData</i>\r
14162                          * for searching data.\r
14163                          *\r
14164                          * The functions defined take a single parameter:\r
14165                          *\r
14166                      *  1. `{*}` Data from the column cell to be prepared for searching\r
14167                          *\r
14168                          * Each function is expected to return:\r
14169                          *\r
14170                          * * `{string|null}` Formatted string that will be used for the searching.\r
14171                          *\r
14172                          *  @type object\r
14173                          *  @default {}\r
14174                          *\r
14175                          *  @example\r
14176                          *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {\r
14177                          *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );\r
14178                          *    }\r
14179                          */\r
14180                         search: {},\r
14181         \r
14182         \r
14183                         /**\r
14184                          * Type based ordering.\r
14185                          *\r
14186                          * The column type tells DataTables what ordering to apply to the table\r
14187                          * when a column is sorted upon. The order for each type that is defined,\r
14188                          * is defined by the functions available in this object.\r
14189                          *\r
14190                          * Each ordering option can be described by three properties added to\r
14191                          * this object:\r
14192                          *\r
14193                          * * `{type}-pre` - Pre-formatting function\r
14194                          * * `{type}-asc` - Ascending order function\r
14195                          * * `{type}-desc` - Descending order function\r
14196                          *\r
14197                          * All three can be used together, only `{type}-pre` or only\r
14198                          * `{type}-asc` and `{type}-desc` together. It is generally recommended\r
14199                          * that only `{type}-pre` is used, as this provides the optimal\r
14200                          * implementation in terms of speed, although the others are provided\r
14201                          * for compatibility with existing Javascript sort functions.\r
14202                          *\r
14203                          * `{type}-pre`: Functions defined take a single parameter:\r
14204                          *\r
14205                      *  1. `{*}` Data from the column cell to be prepared for ordering\r
14206                          *\r
14207                          * And return:\r
14208                          *\r
14209                          * * `{*}` Data to be sorted upon\r
14210                          *\r
14211                          * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort\r
14212                          * functions, taking two parameters:\r
14213                          *\r
14214                      *  1. `{*}` Data to compare to the second parameter\r
14215                      *  2. `{*}` Data to compare to the first parameter\r
14216                          *\r
14217                          * And returning:\r
14218                          *\r
14219                          * * `{*}` Ordering match: <0 if first parameter should be sorted lower\r
14220                          *   than the second parameter, ===0 if the two parameters are equal and\r
14221                          *   >0 if the first parameter should be sorted height than the second\r
14222                          *   parameter.\r
14223                          * \r
14224                          *  @type object\r
14225                          *  @default {}\r
14226                          *\r
14227                          *  @example\r
14228                          *    // Numeric ordering of formatted numbers with a pre-formatter\r
14229                          *    $.extend( $.fn.dataTable.ext.type.order, {\r
14230                          *      "string-pre": function(x) {\r
14231                          *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );\r
14232                          *        return parseFloat( a );\r
14233                          *      }\r
14234                          *    } );\r
14235                          *\r
14236                          *  @example\r
14237                          *    // Case-sensitive string ordering, with no pre-formatting method\r
14238                          *    $.extend( $.fn.dataTable.ext.order, {\r
14239                          *      "string-case-asc": function(x,y) {\r
14240                          *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));\r
14241                          *      },\r
14242                          *      "string-case-desc": function(x,y) {\r
14243                          *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));\r
14244                          *      }\r
14245                          *    } );\r
14246                          */\r
14247                         order: {}\r
14248                 },\r
14249         \r
14250                 /**\r
14251                  * Unique DataTables instance counter\r
14252                  *\r
14253                  * @type int\r
14254                  * @private\r
14255                  */\r
14256                 _unique: 0,\r
14257         \r
14258         \r
14259                 //\r
14260                 // Depreciated\r
14261                 // The following properties are retained for backwards compatiblity only.\r
14262                 // The should not be used in new projects and will be removed in a future\r
14263                 // version\r
14264                 //\r
14265         \r
14266                 /**\r
14267                  * Version check function.\r
14268                  *  @type function\r
14269                  *  @depreciated Since 1.10\r
14270                  */\r
14271                 fnVersionCheck: DataTable.fnVersionCheck,\r
14272         \r
14273         \r
14274                 /**\r
14275                  * Index for what 'this' index API functions should use\r
14276                  *  @type int\r
14277                  *  @deprecated Since v1.10\r
14278                  */\r
14279                 iApiIndex: 0,\r
14280         \r
14281         \r
14282                 /**\r
14283                  * jQuery UI class container\r
14284                  *  @type object\r
14285                  *  @deprecated Since v1.10\r
14286                  */\r
14287                 oJUIClasses: {},\r
14288         \r
14289         \r
14290                 /**\r
14291                  * Software version\r
14292                  *  @type string\r
14293                  *  @deprecated Since v1.10\r
14294                  */\r
14295                 sVersion: DataTable.version\r
14296         };\r
14297         \r
14298         \r
14299         //\r
14300         // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts\r
14301         //\r
14302         $.extend( _ext, {\r
14303                 afnFiltering: _ext.search,\r
14304                 aTypes:       _ext.type.detect,\r
14305                 ofnSearch:    _ext.type.search,\r
14306                 oSort:        _ext.type.order,\r
14307                 afnSortData:  _ext.order,\r
14308                 aoFeatures:   _ext.feature,\r
14309                 oApi:         _ext.internal,\r
14310                 oStdClasses:  _ext.classes,\r
14311                 oPagination:  _ext.pager\r
14312         } );\r
14313         \r
14314         \r
14315         $.extend( DataTable.ext.classes, {\r
14316                 "sTable": "dataTable",\r
14317                 "sNoFooter": "no-footer",\r
14318         \r
14319                 /* Paging buttons */\r
14320                 "sPageButton": "paginate_button",\r
14321                 "sPageButtonActive": "current",\r
14322                 "sPageButtonDisabled": "disabled",\r
14323         \r
14324                 /* Striping classes */\r
14325                 "sStripeOdd": "odd",\r
14326                 "sStripeEven": "even",\r
14327         \r
14328                 /* Empty row */\r
14329                 "sRowEmpty": "dataTables_empty",\r
14330         \r
14331                 /* Features */\r
14332                 "sWrapper": "dataTables_wrapper",\r
14333                 "sFilter": "dataTables_filter",\r
14334                 "sInfo": "dataTables_info",\r
14335                 "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */\r
14336                 "sLength": "dataTables_length",\r
14337                 "sProcessing": "dataTables_processing",\r
14338         \r
14339                 /* Sorting */\r
14340                 "sSortAsc": "sorting_asc",\r
14341                 "sSortDesc": "sorting_desc",\r
14342                 "sSortable": "sorting", /* Sortable in both directions */\r
14343                 "sSortableAsc": "sorting_asc_disabled",\r
14344                 "sSortableDesc": "sorting_desc_disabled",\r
14345                 "sSortableNone": "sorting_disabled",\r
14346                 "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */\r
14347         \r
14348                 /* Filtering */\r
14349                 "sFilterInput": "",\r
14350         \r
14351                 /* Page length */\r
14352                 "sLengthSelect": "",\r
14353         \r
14354                 /* Scrolling */\r
14355                 "sScrollWrapper": "dataTables_scroll",\r
14356                 "sScrollHead": "dataTables_scrollHead",\r
14357                 "sScrollHeadInner": "dataTables_scrollHeadInner",\r
14358                 "sScrollBody": "dataTables_scrollBody",\r
14359                 "sScrollFoot": "dataTables_scrollFoot",\r
14360                 "sScrollFootInner": "dataTables_scrollFootInner",\r
14361         \r
14362                 /* Misc */\r
14363                 "sHeaderTH": "",\r
14364                 "sFooterTH": "",\r
14365         \r
14366                 // Deprecated\r
14367                 "sSortJUIAsc": "",\r
14368                 "sSortJUIDesc": "",\r
14369                 "sSortJUI": "",\r
14370                 "sSortJUIAscAllowed": "",\r
14371                 "sSortJUIDescAllowed": "",\r
14372                 "sSortJUIWrapper": "",\r
14373                 "sSortIcon": "",\r
14374                 "sJUIHeader": "",\r
14375                 "sJUIFooter": ""\r
14376         } );\r
14377         \r
14378         \r
14379         (function() {\r
14380         \r
14381         // Reused strings for better compression. Closure compiler appears to have a\r
14382         // weird edge case where it is trying to expand strings rather than use the\r
14383         // variable version. This results in about 200 bytes being added, for very\r
14384         // little preference benefit since it this run on script load only.\r
14385         var _empty = '';\r
14386         _empty = '';\r
14387         \r
14388         var _stateDefault = _empty + 'ui-state-default';\r
14389         var _sortIcon     = _empty + 'css_right ui-icon ui-icon-';\r
14390         var _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix';\r
14391         \r
14392         $.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, {\r
14393                 /* Full numbers paging buttons */\r
14394                 "sPageButton":         "fg-button ui-button "+_stateDefault,\r
14395                 "sPageButtonActive":   "ui-state-disabled",\r
14396                 "sPageButtonDisabled": "ui-state-disabled",\r
14397         \r
14398                 /* Features */\r
14399                 "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+\r
14400                         "ui-buttonset-multi paging_", /* Note that the type is postfixed */\r
14401         \r
14402                 /* Sorting */\r
14403                 "sSortAsc":            _stateDefault+" sorting_asc",\r
14404                 "sSortDesc":           _stateDefault+" sorting_desc",\r
14405                 "sSortable":           _stateDefault+" sorting",\r
14406                 "sSortableAsc":        _stateDefault+" sorting_asc_disabled",\r
14407                 "sSortableDesc":       _stateDefault+" sorting_desc_disabled",\r
14408                 "sSortableNone":       _stateDefault+" sorting_disabled",\r
14409                 "sSortJUIAsc":         _sortIcon+"triangle-1-n",\r
14410                 "sSortJUIDesc":        _sortIcon+"triangle-1-s",\r
14411                 "sSortJUI":            _sortIcon+"carat-2-n-s",\r
14412                 "sSortJUIAscAllowed":  _sortIcon+"carat-1-n",\r
14413                 "sSortJUIDescAllowed": _sortIcon+"carat-1-s",\r
14414                 "sSortJUIWrapper":     "DataTables_sort_wrapper",\r
14415                 "sSortIcon":           "DataTables_sort_icon",\r
14416         \r
14417                 /* Scrolling */\r
14418                 "sScrollHead": "dataTables_scrollHead "+_stateDefault,\r
14419                 "sScrollFoot": "dataTables_scrollFoot "+_stateDefault,\r
14420         \r
14421                 /* Misc */\r
14422                 "sHeaderTH":  _stateDefault,\r
14423                 "sFooterTH":  _stateDefault,\r
14424                 "sJUIHeader": _headerFooter+" ui-corner-tl ui-corner-tr",\r
14425                 "sJUIFooter": _headerFooter+" ui-corner-bl ui-corner-br"\r
14426         } );\r
14427         \r
14428         }());\r
14429         \r
14430         \r
14431         \r
14432         var extPagination = DataTable.ext.pager;\r
14433         \r
14434         function _numbers ( page, pages ) {\r
14435                 var\r
14436                         numbers = [],\r
14437                         buttons = extPagination.numbers_length,\r
14438                         half = Math.floor( buttons / 2 ),\r
14439                         i = 1;\r
14440         \r
14441                 if ( pages <= buttons ) {\r
14442                         numbers = _range( 0, pages );\r
14443                 }\r
14444                 else if ( page <= half ) {\r
14445                         numbers = _range( 0, buttons-2 );\r
14446                         numbers.push( 'ellipsis' );\r
14447                         numbers.push( pages-1 );\r
14448                 }\r
14449                 else if ( page >= pages - 1 - half ) {\r
14450                         numbers = _range( pages-(buttons-2), pages );\r
14451                         numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6\r
14452                         numbers.splice( 0, 0, 0 );\r
14453                 }\r
14454                 else {\r
14455                         numbers = _range( page-half+2, page+half-1 );\r
14456                         numbers.push( 'ellipsis' );\r
14457                         numbers.push( pages-1 );\r
14458                         numbers.splice( 0, 0, 'ellipsis' );\r
14459                         numbers.splice( 0, 0, 0 );\r
14460                 }\r
14461         \r
14462                 numbers.DT_el = 'span';\r
14463                 return numbers;\r
14464         }\r
14465         \r
14466         \r
14467         $.extend( extPagination, {\r
14468                 simple: function ( page, pages ) {\r
14469                         return [ 'previous', 'next' ];\r
14470                 },\r
14471         \r
14472                 full: function ( page, pages ) {\r
14473                         return [  'first', 'previous', 'next', 'last' ];\r
14474                 },\r
14475         \r
14476                 numbers: function ( page, pages ) {\r
14477                         return [ _numbers(page, pages) ];\r
14478                 },\r
14479         \r
14480                 simple_numbers: function ( page, pages ) {\r
14481                         return [ 'previous', _numbers(page, pages), 'next' ];\r
14482                 },\r
14483         \r
14484                 full_numbers: function ( page, pages ) {\r
14485                         return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];\r
14486                 },\r
14487         \r
14488                 // For testing and plug-ins to use\r
14489                 _numbers: _numbers,\r
14490         \r
14491                 // Number of number buttons (including ellipsis) to show. _Must be odd!_\r
14492                 numbers_length: 7\r
14493         } );\r
14494         \r
14495         \r
14496         $.extend( true, DataTable.ext.renderer, {\r
14497                 pageButton: {\r
14498                         _: function ( settings, host, idx, buttons, page, pages ) {\r
14499                                 var classes = settings.oClasses;\r
14500                                 var lang = settings.oLanguage.oPaginate;\r
14501                                 var aria = settings.oLanguage.oAria.paginate || {};\r
14502                                 var btnDisplay, btnClass, counter=0;\r
14503         \r
14504                                 var attach = function( container, buttons ) {\r
14505                                         var i, ien, node, button;\r
14506                                         var clickHandler = function ( e ) {\r
14507                                                 _fnPageChange( settings, e.data.action, true );\r
14508                                         };\r
14509         \r
14510                                         for ( i=0, ien=buttons.length ; i<ien ; i++ ) {\r
14511                                                 button = buttons[i];\r
14512         \r
14513                                                 if ( $.isArray( button ) ) {\r
14514                                                         var inner = $( '<'+(button.DT_el || 'div')+'/>' )\r
14515                                                                 .appendTo( container );\r
14516                                                         attach( inner, button );\r
14517                                                 }\r
14518                                                 else {\r
14519                                                         btnDisplay = null;\r
14520                                                         btnClass = '';\r
14521         \r
14522                                                         switch ( button ) {\r
14523                                                                 case 'ellipsis':\r
14524                                                                         container.append('<span class="ellipsis">&#x2026;</span>');\r
14525                                                                         break;\r
14526         \r
14527                                                                 case 'first':\r
14528                                                                         btnDisplay = lang.sFirst;\r
14529                                                                         btnClass = button + (page > 0 ?\r
14530                                                                                 '' : ' '+classes.sPageButtonDisabled);\r
14531                                                                         break;\r
14532         \r
14533                                                                 case 'previous':\r
14534                                                                         btnDisplay = lang.sPrevious;\r
14535                                                                         btnClass = button + (page > 0 ?\r
14536                                                                                 '' : ' '+classes.sPageButtonDisabled);\r
14537                                                                         break;\r
14538         \r
14539                                                                 case 'next':\r
14540                                                                         btnDisplay = lang.sNext;\r
14541                                                                         btnClass = button + (page < pages-1 ?\r
14542                                                                                 '' : ' '+classes.sPageButtonDisabled);\r
14543                                                                         break;\r
14544         \r
14545                                                                 case 'last':\r
14546                                                                         btnDisplay = lang.sLast;\r
14547                                                                         btnClass = button + (page < pages-1 ?\r
14548                                                                                 '' : ' '+classes.sPageButtonDisabled);\r
14549                                                                         break;\r
14550         \r
14551                                                                 default:\r
14552                                                                         btnDisplay = button + 1;\r
14553                                                                         btnClass = page === button ?\r
14554                                                                                 classes.sPageButtonActive : '';\r
14555                                                                         break;\r
14556                                                         }\r
14557         \r
14558                                                         if ( btnDisplay !== null ) {\r
14559                                                                 node = $('<a>', {\r
14560                                                                                 'class': classes.sPageButton+' '+btnClass,\r
14561                                                                                 'aria-controls': settings.sTableId,\r
14562                                                                                 'aria-label': aria[ button ],\r
14563                                                                                 'data-dt-idx': counter,\r
14564                                                                                 'tabindex': settings.iTabIndex,\r
14565                                                                                 'id': idx === 0 && typeof button === 'string' ?\r
14566                                                                                         settings.sTableId +'_'+ button :\r
14567                                                                                         null\r
14568                                                                         } )\r
14569                                                                         .html( btnDisplay )\r
14570                                                                         .appendTo( container );\r
14571         \r
14572                                                                 _fnBindAction(\r
14573                                                                         node, {action: button}, clickHandler\r
14574                                                                 );\r
14575         \r
14576                                                                 counter++;\r
14577                                                         }\r
14578                                                 }\r
14579                                         }\r
14580                                 };\r
14581         \r
14582                                 // IE9 throws an 'unknown error' if document.activeElement is used\r
14583                                 // inside an iframe or frame. Try / catch the error. Not good for\r
14584                                 // accessibility, but neither are frames.\r
14585                                 var activeEl;\r
14586         \r
14587                                 try {\r
14588                                         // Because this approach is destroying and recreating the paging\r
14589                                         // elements, focus is lost on the select button which is bad for\r
14590                                         // accessibility. So we want to restore focus once the draw has\r
14591                                         // completed\r
14592                                         activeEl = $(host).find(document.activeElement).data('dt-idx');\r
14593                                 }\r
14594                                 catch (e) {}\r
14595         \r
14596                                 attach( $(host).empty(), buttons );\r
14597         \r
14598                                 if ( activeEl ) {\r
14599                                         $(host).find( '[data-dt-idx='+activeEl+']' ).focus();\r
14600                                 }\r
14601                         }\r
14602                 }\r
14603         } );\r
14604         \r
14605         \r
14606         \r
14607         // Built in type detection. See model.ext.aTypes for information about\r
14608         // what is required from this methods.\r
14609         $.extend( DataTable.ext.type.detect, [\r
14610                 // Plain numbers - first since V8 detects some plain numbers as dates\r
14611                 // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).\r
14612                 function ( d, settings )\r
14613                 {\r
14614                         var decimal = settings.oLanguage.sDecimal;\r
14615                         return _isNumber( d, decimal ) ? 'num'+decimal : null;\r
14616                 },\r
14617         \r
14618                 // Dates (only those recognised by the browser's Date.parse)\r
14619                 function ( d, settings )\r
14620                 {\r
14621                         // V8 will remove any unknown characters at the start and end of the\r
14622                         // expression, leading to false matches such as `$245.12` or `10%` being\r
14623                         // a valid date. See forum thread 18941 for detail.\r
14624                         if ( d && !(d instanceof Date) && ( ! _re_date_start.test(d) || ! _re_date_end.test(d) ) ) {\r
14625                                 return null;\r
14626                         }\r
14627                         var parsed = Date.parse(d);\r
14628                         return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;\r
14629                 },\r
14630         \r
14631                 // Formatted numbers\r
14632                 function ( d, settings )\r
14633                 {\r
14634                         var decimal = settings.oLanguage.sDecimal;\r
14635                         return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;\r
14636                 },\r
14637         \r
14638                 // HTML numeric\r
14639                 function ( d, settings )\r
14640                 {\r
14641                         var decimal = settings.oLanguage.sDecimal;\r
14642                         return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;\r
14643                 },\r
14644         \r
14645                 // HTML numeric, formatted\r
14646                 function ( d, settings )\r
14647                 {\r
14648                         var decimal = settings.oLanguage.sDecimal;\r
14649                         return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;\r
14650                 },\r
14651         \r
14652                 // HTML (this is strict checking - there must be html)\r
14653                 function ( d, settings )\r
14654                 {\r
14655                         return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?\r
14656                                 'html' : null;\r
14657                 }\r
14658         ] );\r
14659         \r
14660         \r
14661         \r
14662         // Filter formatting functions. See model.ext.ofnSearch for information about\r
14663         // what is required from these methods.\r
14664         // \r
14665         // Note that additional search methods are added for the html numbers and\r
14666         // html formatted numbers by `_addNumericSort()` when we know what the decimal\r
14667         // place is\r
14668         \r
14669         \r
14670         $.extend( DataTable.ext.type.search, {\r
14671                 html: function ( data ) {\r
14672                         return _empty(data) ?\r
14673                                 data :\r
14674                                 typeof data === 'string' ?\r
14675                                         data\r
14676                                                 .replace( _re_new_lines, " " )\r
14677                                                 .replace( _re_html, "" ) :\r
14678                                         '';\r
14679                 },\r
14680         \r
14681                 string: function ( data ) {\r
14682                         return _empty(data) ?\r
14683                                 data :\r
14684                                 typeof data === 'string' ?\r
14685                                         data.replace( _re_new_lines, " " ) :\r
14686                                         data;\r
14687                 }\r
14688         } );\r
14689         \r
14690         \r
14691         \r
14692         var __numericReplace = function ( d, decimalPlace, re1, re2 ) {\r
14693                 if ( d !== 0 && (!d || d === '-') ) {\r
14694                         return -Infinity;\r
14695                 }\r
14696         \r
14697                 // If a decimal place other than `.` is used, it needs to be given to the\r
14698                 // function so we can detect it and replace with a `.` which is the only\r
14699                 // decimal place Javascript recognises - it is not locale aware.\r
14700                 if ( decimalPlace ) {\r
14701                         d = _numToDecimal( d, decimalPlace );\r
14702                 }\r
14703         \r
14704                 if ( d.replace ) {\r
14705                         if ( re1 ) {\r
14706                                 d = d.replace( re1, '' );\r
14707                         }\r
14708         \r
14709                         if ( re2 ) {\r
14710                                 d = d.replace( re2, '' );\r
14711                         }\r
14712                 }\r
14713         \r
14714                 return d * 1;\r
14715         };\r
14716         \r
14717         \r
14718         // Add the numeric 'deformatting' functions for sorting and search. This is done\r
14719         // in a function to provide an easy ability for the language options to add\r
14720         // additional methods if a non-period decimal place is used.\r
14721         function _addNumericSort ( decimalPlace ) {\r
14722                 $.each(\r
14723                         {\r
14724                                 // Plain numbers\r
14725                                 "num": function ( d ) {\r
14726                                         return __numericReplace( d, decimalPlace );\r
14727                                 },\r
14728         \r
14729                                 // Formatted numbers\r
14730                                 "num-fmt": function ( d ) {\r
14731                                         return __numericReplace( d, decimalPlace, _re_formatted_numeric );\r
14732                                 },\r
14733         \r
14734                                 // HTML numeric\r
14735                                 "html-num": function ( d ) {\r
14736                                         return __numericReplace( d, decimalPlace, _re_html );\r
14737                                 },\r
14738         \r
14739                                 // HTML numeric, formatted\r
14740                                 "html-num-fmt": function ( d ) {\r
14741                                         return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );\r
14742                                 }\r
14743                         },\r
14744                         function ( key, fn ) {\r
14745                                 // Add the ordering method\r
14746                                 _ext.type.order[ key+decimalPlace+'-pre' ] = fn;\r
14747         \r
14748                                 // For HTML types add a search formatter that will strip the HTML\r
14749                                 if ( key.match(/^html\-/) ) {\r
14750                                         _ext.type.search[ key+decimalPlace ] = _ext.type.search.html;\r
14751                                 }\r
14752                         }\r
14753                 );\r
14754         }\r
14755         \r
14756         \r
14757         // Default sort methods\r
14758         $.extend( _ext.type.order, {\r
14759                 // Dates\r
14760                 "date-pre": function ( d ) {\r
14761                         return Date.parse( d ) || 0;\r
14762                 },\r
14763         \r
14764                 // html\r
14765                 "html-pre": function ( a ) {\r
14766                         return _empty(a) ?\r
14767                                 '' :\r
14768                                 a.replace ?\r
14769                                         a.replace( /<.*?>/g, "" ).toLowerCase() :\r
14770                                         a+'';\r
14771                 },\r
14772         \r
14773                 // string\r
14774                 "string-pre": function ( a ) {\r
14775                         // This is a little complex, but faster than always calling toString,\r
14776                         // http://jsperf.com/tostring-v-check\r
14777                         return _empty(a) ?\r
14778                                 '' :\r
14779                                 typeof a === 'string' ?\r
14780                                         a.toLowerCase() :\r
14781                                         ! a.toString ?\r
14782                                                 '' :\r
14783                                                 a.toString();\r
14784                 },\r
14785         \r
14786                 // string-asc and -desc are retained only for compatibility with the old\r
14787                 // sort methods\r
14788                 "string-asc": function ( x, y ) {\r
14789                         return ((x < y) ? -1 : ((x > y) ? 1 : 0));\r
14790                 },\r
14791         \r
14792                 "string-desc": function ( x, y ) {\r
14793                         return ((x < y) ? 1 : ((x > y) ? -1 : 0));\r
14794                 }\r
14795         } );\r
14796         \r
14797         \r
14798         // Numeric sorting types - order doesn't matter here\r
14799         _addNumericSort( '' );\r
14800         \r
14801         \r
14802         $.extend( true, DataTable.ext.renderer, {\r
14803                 header: {\r
14804                         _: function ( settings, cell, column, classes ) {\r
14805                                 // No additional mark-up required\r
14806                                 // Attach a sort listener to update on sort - note that using the\r
14807                                 // `DT` namespace will allow the event to be removed automatically\r
14808                                 // on destroy, while the `dt` namespaced event is the one we are\r
14809                                 // listening for\r
14810                                 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {\r
14811                                         if ( settings !== ctx ) { // need to check this this is the host\r
14812                                                 return;               // table, not a nested one\r
14813                                         }\r
14814         \r
14815                                         var colIdx = column.idx;\r
14816         \r
14817                                         cell\r
14818                                                 .removeClass(\r
14819                                                         column.sSortingClass +' '+\r
14820                                                         classes.sSortAsc +' '+\r
14821                                                         classes.sSortDesc\r
14822                                                 )\r
14823                                                 .addClass( columns[ colIdx ] == 'asc' ?\r
14824                                                         classes.sSortAsc : columns[ colIdx ] == 'desc' ?\r
14825                                                                 classes.sSortDesc :\r
14826                                                                 column.sSortingClass\r
14827                                                 );\r
14828                                 } );\r
14829                         },\r
14830         \r
14831                         jqueryui: function ( settings, cell, column, classes ) {\r
14832                                 $('<div/>')\r
14833                                         .addClass( classes.sSortJUIWrapper )\r
14834                                         .append( cell.contents() )\r
14835                                         .append( $('<span/>')\r
14836                                                 .addClass( classes.sSortIcon+' '+column.sSortingClassJUI )\r
14837                                         )\r
14838                                         .appendTo( cell );\r
14839         \r
14840                                 // Attach a sort listener to update on sort\r
14841                                 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {\r
14842                                         if ( settings !== ctx ) {\r
14843                                                 return;\r
14844                                         }\r
14845         \r
14846                                         var colIdx = column.idx;\r
14847         \r
14848                                         cell\r
14849                                                 .removeClass( classes.sSortAsc +" "+classes.sSortDesc )\r
14850                                                 .addClass( columns[ colIdx ] == 'asc' ?\r
14851                                                         classes.sSortAsc : columns[ colIdx ] == 'desc' ?\r
14852                                                                 classes.sSortDesc :\r
14853                                                                 column.sSortingClass\r
14854                                                 );\r
14855         \r
14856                                         cell\r
14857                                                 .find( 'span.'+classes.sSortIcon )\r
14858                                                 .removeClass(\r
14859                                                         classes.sSortJUIAsc +" "+\r
14860                                                         classes.sSortJUIDesc +" "+\r
14861                                                         classes.sSortJUI +" "+\r
14862                                                         classes.sSortJUIAscAllowed +" "+\r
14863                                                         classes.sSortJUIDescAllowed\r
14864                                                 )\r
14865                                                 .addClass( columns[ colIdx ] == 'asc' ?\r
14866                                                         classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?\r
14867                                                                 classes.sSortJUIDesc :\r
14868                                                                 column.sSortingClassJUI\r
14869                                                 );\r
14870                                 } );\r
14871                         }\r
14872                 }\r
14873         } );\r
14874         \r
14875         /*\r
14876          * Public helper functions. These aren't used internally by DataTables, or\r
14877          * called by any of the options passed into DataTables, but they can be used\r
14878          * externally by developers working with DataTables. They are helper functions\r
14879          * to make working with DataTables a little bit easier.\r
14880          */\r
14881         \r
14882         var __htmlEscapeEntities = function ( d ) {\r
14883                 return typeof d === 'string' ?\r
14884                         d.replace(/</g, '&lt;').replace(/>/g, '&gt;').replace(/"/g, '&quot;') :\r
14885                         d;\r
14886         };\r
14887         \r
14888         /**\r
14889          * Helpers for `columns.render`.\r
14890          *\r
14891          * The options defined here can be used with the `columns.render` initialisation\r
14892          * option to provide a display renderer. The following functions are defined:\r
14893          *\r
14894          * * `number` - Will format numeric data (defined by `columns.data`) for\r
14895          *   display, retaining the original unformatted data for sorting and filtering.\r
14896          *   It takes 5 parameters:\r
14897          *   * `string` - Thousands grouping separator\r
14898          *   * `string` - Decimal point indicator\r
14899          *   * `integer` - Number of decimal points to show\r
14900          *   * `string` (optional) - Prefix.\r
14901          *   * `string` (optional) - Postfix (/suffix).\r
14902          * * `text` - Escape HTML to help prevent XSS attacks. It has no optional\r
14903          *   parameters.\r
14904          *\r
14905          * @example\r
14906          *   // Column definition using the number renderer\r
14907          *   {\r
14908          *     data: "salary",\r
14909          *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )\r
14910          *   }\r
14911          *\r
14912          * @namespace\r
14913          */\r
14914         DataTable.render = {\r
14915                 number: function ( thousands, decimal, precision, prefix, postfix ) {\r
14916                         return {\r
14917                                 display: function ( d ) {\r
14918                                         if ( typeof d !== 'number' && typeof d !== 'string' ) {\r
14919                                                 return d;\r
14920                                         }\r
14921         \r
14922                                         var negative = d < 0 ? '-' : '';\r
14923                                         var flo = parseFloat( d );\r
14924         \r
14925                                         // If NaN then there isn't much formatting that we can do - just\r
14926                                         // return immediately, escaping any HTML (this was supposed to\r
14927                                         // be a number after all)\r
14928                                         if ( isNaN( flo ) ) {\r
14929                                                 return __htmlEscapeEntities( d );\r
14930                                         }\r
14931         \r
14932                                         d = Math.abs( flo );\r
14933         \r
14934                                         var intPart = parseInt( d, 10 );\r
14935                                         var floatPart = precision ?\r
14936                                                 decimal+(d - intPart).toFixed( precision ).substring( 2 ):\r
14937                                                 '';\r
14938         \r
14939                                         return negative + (prefix||'') +\r
14940                                                 intPart.toString().replace(\r
14941                                                         /\B(?=(\d{3})+(?!\d))/g, thousands\r
14942                                                 ) +\r
14943                                                 floatPart +\r
14944                                                 (postfix||'');\r
14945                                 }\r
14946                         };\r
14947                 },\r
14948         \r
14949                 text: function () {\r
14950                         return {\r
14951                                 display: __htmlEscapeEntities\r
14952                         };\r
14953                 }\r
14954         };\r
14955         \r
14956         \r
14957         /*\r
14958          * This is really a good bit rubbish this method of exposing the internal methods\r
14959          * publicly... - To be fixed in 2.0 using methods on the prototype\r
14960          */\r
14961         \r
14962         \r
14963         /**\r
14964          * Create a wrapper function for exporting an internal functions to an external API.\r
14965          *  @param {string} fn API function name\r
14966          *  @returns {function} wrapped function\r
14967          *  @memberof DataTable#internal\r
14968          */\r
14969         function _fnExternApiFunc (fn)\r
14970         {\r
14971                 return function() {\r
14972                         var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(\r
14973                                 Array.prototype.slice.call(arguments)\r
14974                         );\r
14975                         return DataTable.ext.internal[fn].apply( this, args );\r
14976                 };\r
14977         }\r
14978         \r
14979         \r
14980         /**\r
14981          * Reference to internal functions for use by plug-in developers. Note that\r
14982          * these methods are references to internal functions and are considered to be\r
14983          * private. If you use these methods, be aware that they are liable to change\r
14984          * between versions.\r
14985          *  @namespace\r
14986          */\r
14987         $.extend( DataTable.ext.internal, {\r
14988                 _fnExternApiFunc: _fnExternApiFunc,\r
14989                 _fnBuildAjax: _fnBuildAjax,\r
14990                 _fnAjaxUpdate: _fnAjaxUpdate,\r
14991                 _fnAjaxParameters: _fnAjaxParameters,\r
14992                 _fnAjaxUpdateDraw: _fnAjaxUpdateDraw,\r
14993                 _fnAjaxDataSrc: _fnAjaxDataSrc,\r
14994                 _fnAddColumn: _fnAddColumn,\r
14995                 _fnColumnOptions: _fnColumnOptions,\r
14996                 _fnAdjustColumnSizing: _fnAdjustColumnSizing,\r
14997                 _fnVisibleToColumnIndex: _fnVisibleToColumnIndex,\r
14998                 _fnColumnIndexToVisible: _fnColumnIndexToVisible,\r
14999                 _fnVisbleColumns: _fnVisbleColumns,\r
15000                 _fnGetColumns: _fnGetColumns,\r
15001                 _fnColumnTypes: _fnColumnTypes,\r
15002                 _fnApplyColumnDefs: _fnApplyColumnDefs,\r
15003                 _fnHungarianMap: _fnHungarianMap,\r
15004                 _fnCamelToHungarian: _fnCamelToHungarian,\r
15005                 _fnLanguageCompat: _fnLanguageCompat,\r
15006                 _fnBrowserDetect: _fnBrowserDetect,\r
15007                 _fnAddData: _fnAddData,\r
15008                 _fnAddTr: _fnAddTr,\r
15009                 _fnNodeToDataIndex: _fnNodeToDataIndex,\r
15010                 _fnNodeToColumnIndex: _fnNodeToColumnIndex,\r
15011                 _fnGetCellData: _fnGetCellData,\r
15012                 _fnSetCellData: _fnSetCellData,\r
15013                 _fnSplitObjNotation: _fnSplitObjNotation,\r
15014                 _fnGetObjectDataFn: _fnGetObjectDataFn,\r
15015                 _fnSetObjectDataFn: _fnSetObjectDataFn,\r
15016                 _fnGetDataMaster: _fnGetDataMaster,\r
15017                 _fnClearTable: _fnClearTable,\r
15018                 _fnDeleteIndex: _fnDeleteIndex,\r
15019                 _fnInvalidate: _fnInvalidate,\r
15020                 _fnGetRowElements: _fnGetRowElements,\r
15021                 _fnCreateTr: _fnCreateTr,\r
15022                 _fnBuildHead: _fnBuildHead,\r
15023                 _fnDrawHead: _fnDrawHead,\r
15024                 _fnDraw: _fnDraw,\r
15025                 _fnReDraw: _fnReDraw,\r
15026                 _fnAddOptionsHtml: _fnAddOptionsHtml,\r
15027                 _fnDetectHeader: _fnDetectHeader,\r
15028                 _fnGetUniqueThs: _fnGetUniqueThs,\r
15029                 _fnFeatureHtmlFilter: _fnFeatureHtmlFilter,\r
15030                 _fnFilterComplete: _fnFilterComplete,\r
15031                 _fnFilterCustom: _fnFilterCustom,\r
15032                 _fnFilterColumn: _fnFilterColumn,\r
15033                 _fnFilter: _fnFilter,\r
15034                 _fnFilterCreateSearch: _fnFilterCreateSearch,\r
15035                 _fnEscapeRegex: _fnEscapeRegex,\r
15036                 _fnFilterData: _fnFilterData,\r
15037                 _fnFeatureHtmlInfo: _fnFeatureHtmlInfo,\r
15038                 _fnUpdateInfo: _fnUpdateInfo,\r
15039                 _fnInfoMacros: _fnInfoMacros,\r
15040                 _fnInitialise: _fnInitialise,\r
15041                 _fnInitComplete: _fnInitComplete,\r
15042                 _fnLengthChange: _fnLengthChange,\r
15043                 _fnFeatureHtmlLength: _fnFeatureHtmlLength,\r
15044                 _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,\r
15045                 _fnPageChange: _fnPageChange,\r
15046                 _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,\r
15047                 _fnProcessingDisplay: _fnProcessingDisplay,\r
15048                 _fnFeatureHtmlTable: _fnFeatureHtmlTable,\r
15049                 _fnScrollDraw: _fnScrollDraw,\r
15050                 _fnApplyToChildren: _fnApplyToChildren,\r
15051                 _fnCalculateColumnWidths: _fnCalculateColumnWidths,\r
15052                 _fnThrottle: _fnThrottle,\r
15053                 _fnConvertToWidth: _fnConvertToWidth,\r
15054                 _fnGetWidestNode: _fnGetWidestNode,\r
15055                 _fnGetMaxLenString: _fnGetMaxLenString,\r
15056                 _fnStringToCss: _fnStringToCss,\r
15057                 _fnSortFlatten: _fnSortFlatten,\r
15058                 _fnSort: _fnSort,\r
15059                 _fnSortAria: _fnSortAria,\r
15060                 _fnSortListener: _fnSortListener,\r
15061                 _fnSortAttachListener: _fnSortAttachListener,\r
15062                 _fnSortingClasses: _fnSortingClasses,\r
15063                 _fnSortData: _fnSortData,\r
15064                 _fnSaveState: _fnSaveState,\r
15065                 _fnLoadState: _fnLoadState,\r
15066                 _fnSettingsFromNode: _fnSettingsFromNode,\r
15067                 _fnLog: _fnLog,\r
15068                 _fnMap: _fnMap,\r
15069                 _fnBindAction: _fnBindAction,\r
15070                 _fnCallbackReg: _fnCallbackReg,\r
15071                 _fnCallbackFire: _fnCallbackFire,\r
15072                 _fnLengthOverflow: _fnLengthOverflow,\r
15073                 _fnRenderer: _fnRenderer,\r
15074                 _fnDataSource: _fnDataSource,\r
15075                 _fnRowAttributes: _fnRowAttributes,\r
15076                 _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant\r
15077                                                 // in 1.10, so this dead-end function is\r
15078                                                 // added to prevent errors\r
15079         } );\r
15080         \r
15081 \r
15082         // jQuery access\r
15083         $.fn.dataTable = DataTable;\r
15084 \r
15085         // Provide access to the host jQuery object (circular reference)\r
15086         DataTable.$ = $;\r
15087 \r
15088         // Legacy aliases\r
15089         $.fn.dataTableSettings = DataTable.settings;\r
15090         $.fn.dataTableExt = DataTable.ext;\r
15091 \r
15092         // With a capital `D` we return a DataTables API instance rather than a\r
15093         // jQuery object\r
15094         $.fn.DataTable = function ( opts ) {\r
15095                 return $(this).dataTable( opts ).api();\r
15096         };\r
15097 \r
15098         // All properties that are available to $.fn.dataTable should also be\r
15099         // available on $.fn.DataTable\r
15100         $.each( DataTable, function ( prop, val ) {\r
15101                 $.fn.DataTable[ prop ] = val;\r
15102         } );\r
15103 \r
15104 \r
15105         // Information about events fired by DataTables - for documentation.\r
15106         /**\r
15107          * Draw event, fired whenever the table is redrawn on the page, at the same\r
15108          * point as fnDrawCallback. This may be useful for binding events or\r
15109          * performing calculations when the table is altered at all.\r
15110          *  @name DataTable#draw.dt\r
15111          *  @event\r
15112          *  @param {event} e jQuery event object\r
15113          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}\r
15114          */\r
15115 \r
15116         /**\r
15117          * Search event, fired when the searching applied to the table (using the\r
15118          * built-in global search, or column filters) is altered.\r
15119          *  @name DataTable#search.dt\r
15120          *  @event\r
15121          *  @param {event} e jQuery event object\r
15122          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}\r
15123          */\r
15124 \r
15125         /**\r
15126          * Page change event, fired when the paging of the table is altered.\r
15127          *  @name DataTable#page.dt\r
15128          *  @event\r
15129          *  @param {event} e jQuery event object\r
15130          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}\r
15131          */\r
15132 \r
15133         /**\r
15134          * Order event, fired when the ordering applied to the table is altered.\r
15135          *  @name DataTable#order.dt\r
15136          *  @event\r
15137          *  @param {event} e jQuery event object\r
15138          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}\r
15139          */\r
15140 \r
15141         /**\r
15142          * DataTables initialisation complete event, fired when the table is fully\r
15143          * drawn, including Ajax data loaded, if Ajax data is required.\r
15144          *  @name DataTable#init.dt\r
15145          *  @event\r
15146          *  @param {event} e jQuery event object\r
15147          *  @param {object} oSettings DataTables settings object\r
15148          *  @param {object} json The JSON object request from the server - only\r
15149          *    present if client-side Ajax sourced data is used</li></ol>\r
15150          */\r
15151 \r
15152         /**\r
15153          * State save event, fired when the table has changed state a new state save\r
15154          * is required. This event allows modification of the state saving object\r
15155          * prior to actually doing the save, including addition or other state\r
15156          * properties (for plug-ins) or modification of a DataTables core property.\r
15157          *  @name DataTable#stateSaveParams.dt\r
15158          *  @event\r
15159          *  @param {event} e jQuery event object\r
15160          *  @param {object} oSettings DataTables settings object\r
15161          *  @param {object} json The state information to be saved\r
15162          */\r
15163 \r
15164         /**\r
15165          * State load event, fired when the table is loading state from the stored\r
15166          * data, but prior to the settings object being modified by the saved state\r
15167          * - allowing modification of the saved state is required or loading of\r
15168          * state for a plug-in.\r
15169          *  @name DataTable#stateLoadParams.dt\r
15170          *  @event\r
15171          *  @param {event} e jQuery event object\r
15172          *  @param {object} oSettings DataTables settings object\r
15173          *  @param {object} json The saved state information\r
15174          */\r
15175 \r
15176         /**\r
15177          * State loaded event, fired when state has been loaded from stored data and\r
15178          * the settings object has been modified by the loaded data.\r
15179          *  @name DataTable#stateLoaded.dt\r
15180          *  @event\r
15181          *  @param {event} e jQuery event object\r
15182          *  @param {object} oSettings DataTables settings object\r
15183          *  @param {object} json The saved state information\r
15184          */\r
15185 \r
15186         /**\r
15187          * Processing event, fired when DataTables is doing some kind of processing\r
15188          * (be it, order, searcg or anything else). It can be used to indicate to\r
15189          * the end user that there is something happening, or that something has\r
15190          * finished.\r
15191          *  @name DataTable#processing.dt\r
15192          *  @event\r
15193          *  @param {event} e jQuery event object\r
15194          *  @param {object} oSettings DataTables settings object\r
15195          *  @param {boolean} bShow Flag for if DataTables is doing processing or not\r
15196          */\r
15197 \r
15198         /**\r
15199          * Ajax (XHR) event, fired whenever an Ajax request is completed from a\r
15200          * request to made to the server for new data. This event is called before\r
15201          * DataTables processed the returned data, so it can also be used to pre-\r
15202          * process the data returned from the server, if needed.\r
15203          *\r
15204          * Note that this trigger is called in `fnServerData`, if you override\r
15205          * `fnServerData` and which to use this event, you need to trigger it in you\r
15206          * success function.\r
15207          *  @name DataTable#xhr.dt\r
15208          *  @event\r
15209          *  @param {event} e jQuery event object\r
15210          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}\r
15211          *  @param {object} json JSON returned from the server\r
15212          *\r
15213          *  @example\r
15214          *     // Use a custom property returned from the server in another DOM element\r
15215          *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {\r
15216          *       $('#status').html( json.status );\r
15217          *     } );\r
15218          *\r
15219          *  @example\r
15220          *     // Pre-process the data returned from the server\r
15221          *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {\r
15222          *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {\r
15223          *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;\r
15224          *       }\r
15225          *       // Note no return - manipulate the data directly in the JSON object.\r
15226          *     } );\r
15227          */\r
15228 \r
15229         /**\r
15230          * Destroy event, fired when the DataTable is destroyed by calling fnDestroy\r
15231          * or passing the bDestroy:true parameter in the initialisation object. This\r
15232          * can be used to remove bound events, added DOM nodes, etc.\r
15233          *  @name DataTable#destroy.dt\r
15234          *  @event\r
15235          *  @param {event} e jQuery event object\r
15236          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}\r
15237          */\r
15238 \r
15239         /**\r
15240          * Page length change event, fired when number of records to show on each\r
15241          * page (the length) is changed.\r
15242          *  @name DataTable#length.dt\r
15243          *  @event\r
15244          *  @param {event} e jQuery event object\r
15245          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}\r
15246          *  @param {integer} len New length\r
15247          */\r
15248 \r
15249         /**\r
15250          * Column sizing has changed.\r
15251          *  @name DataTable#column-sizing.dt\r
15252          *  @event\r
15253          *  @param {event} e jQuery event object\r
15254          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}\r
15255          */\r
15256 \r
15257         /**\r
15258          * Column visibility has changed.\r
15259          *  @name DataTable#column-visibility.dt\r
15260          *  @event\r
15261          *  @param {event} e jQuery event object\r
15262          *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}\r
15263          *  @param {int} column Column index\r
15264          *  @param {bool} vis `false` if column now hidden, or `true` if visible\r
15265          */\r
15266 \r
15267         return $.fn.dataTable;\r
15268 }));\r