Subversion Repositories Integrator Subversion

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
1 espaco 1
/*! DataTables 1.10.2
2
 * ©2008-2014 SpryMedia Ltd - datatables.net/license
3
 */
4
 
5
/**
6
 * @summary     DataTables
7
 * @description Paginate, search and order HTML tables
8
 * @version     1.10.2
9
 * @file        jquery.dataTables.js
10
 * @author      SpryMedia Ltd (www.sprymedia.co.uk)
11
 * @contact     www.sprymedia.co.uk/contact
12
 * @copyright   Copyright 2008-2014 SpryMedia Ltd.
13
 *
14
 * This source file is free software, available under the following license:
15
 *   MIT license - http://datatables.net/license
16
 *
17
 * This source file is distributed in the hope that it will be useful, but
18
 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
19
 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details.
20
 *
21
 * For details please refer to: http://www.datatables.net
22
 */
23
 
24
/*jslint evil: true, undef: true, browser: true */
25
/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidateRow,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnScrollBarWidth,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/
26
 
27
(/** @lends <global> */function( window, document, undefined ) {
28
 
29
(function( factory ) {
30
        "use strict";
31
 
32
        if ( typeof define === 'function' && define.amd ) {
33
                // Define as an AMD module if possible
34
                define( 'datatables', ['jquery'], factory );
35
        }
36
    else if ( typeof exports === 'object' ) {
37
        // Node/CommonJS
38
        factory( require( 'jquery' ) );
39
    }
40
        else if ( jQuery && !jQuery.fn.dataTable ) {
41
                // Define using browser globals otherwise
42
                // Prevent multiple instantiations if the script is loaded twice
43
                factory( jQuery );
44
        }
45
}
46
(/** @lends <global> */function( $ ) {
47
        "use strict";
48
 
49
        /**
50
         * DataTables is a plug-in for the jQuery Javascript library. It is a highly
51
         * flexible tool, based upon the foundations of progressive enhancement,
52
         * which will add advanced interaction controls to any HTML table. For a
53
         * full list of features please refer to
54
         * [DataTables.net](href="http://datatables.net).
55
         *
56
         * Note that the `DataTable` object is not a global variable but is aliased
57
         * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may
58
         * be  accessed.
59
         *
60
         *  @class
61
         *  @param {object} [init={}] Configuration object for DataTables. Options
62
         *    are defined by {@link DataTable.defaults}
63
         *  @requires jQuery 1.7+
64
         *
65
         *  @example
66
         *    // Basic initialisation
67
         *    $(document).ready( function {
68
         *      $('#example').dataTable();
69
         *    } );
70
         *
71
         *  @example
72
         *    // Initialisation with configuration options - in this case, disable
73
         *    // pagination and sorting.
74
         *    $(document).ready( function {
75
         *      $('#example').dataTable( {
76
         *        "paginate": false,
77
         *        "sort": false
78
         *      } );
79
         *    } );
80
         */
81
        var DataTable;
82
 
83
 
84
        /*
85
         * It is useful to have variables which are scoped locally so only the
86
         * DataTables functions can access them and they don't leak into global space.
87
         * At the same time these functions are often useful over multiple files in the
88
         * core and API, so we list, or at least document, all variables which are used
89
         * by DataTables as private variables here. This also ensures that there is no
90
         * clashing of variable names and that they can easily referenced for reuse.
91
         */
92
 
93
 
94
        // Defined else where
95
        //  _selector_run
96
        //  _selector_opts
97
        //  _selector_first
98
        //  _selector_row_indexes
99
 
100
        var _ext; // DataTable.ext
101
        var _Api; // DataTable.Api
102
        var _api_register; // DataTable.Api.register
103
        var _api_registerPlural; // DataTable.Api.registerPlural
104
 
105
        var _re_dic = {};
106
        var _re_new_lines = /[\r\n]/g;
107
        var _re_html = /<.*?>/g;
108
        var _re_date_start = /^[\w\+\-]/;
109
        var _re_date_end = /[\w\+\-]$/;
110
 
111
        // Escape regular expression special characters
112
        var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' );
113
 
114
        // U+2009 is thin space and U+202F is narrow no-break space, both used in many
115
        // standards as thousands separators
116
        var _re_formatted_numeric = /[',$£€¥%\u2009\u202F]/g;
117
 
118
 
119
        var _empty = function ( d ) {
120
                return !d || d === true || d === '-' ? true : false;
121
        };
122
 
123
 
124
        var _intVal = function ( s ) {
125
                var integer = parseInt( s, 10 );
126
                return !isNaN(integer) && isFinite(s) ? integer : null;
127
        };
128
 
129
        // Convert from a formatted number with characters other than `.` as the
130
        // decimal place, to a Javascript number
131
        var _numToDecimal = function ( num, decimalPoint ) {
132
                // Cache created regular expressions for speed as this function is called often
133
                if ( ! _re_dic[ decimalPoint ] ) {
134
                        _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' );
135
                }
136
                return typeof num === 'string' ?
137
                        num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) :
138
                        num;
139
        };
140
 
141
 
142
        var _isNumber = function ( d, decimalPoint, formatted ) {
143
                var strType = typeof d === 'string';
144
 
145
                if ( decimalPoint && strType ) {
146
                        d = _numToDecimal( d, decimalPoint );
147
                }
148
 
149
                if ( formatted && strType ) {
150
                        d = d.replace( _re_formatted_numeric, '' );
151
                }
152
 
153
                return _empty( d ) || (!isNaN( parseFloat(d) ) && isFinite( d ));
154
        };
155
 
156
 
157
        // A string without HTML in it can be considered to be HTML still
158
        var _isHtml = function ( d ) {
159
                return _empty( d ) || typeof d === 'string';
160
        };
161
 
162
 
163
        var _htmlNumeric = function ( d, decimalPoint, formatted ) {
164
                if ( _empty( d ) ) {
165
                        return true;
166
                }
167
 
168
                var html = _isHtml( d );
169
                return ! html ?
170
                        null :
171
                        _isNumber( _stripHtml( d ), decimalPoint, formatted ) ?
172
                                true :
173
                                null;
174
        };
175
 
176
 
177
        var _pluck = function ( a, prop, prop2 ) {
178
                var out = [];
179
                var i=0, ien=a.length;
180
 
181
                // Could have the test in the loop for slightly smaller code, but speed
182
                // is essential here
183
                if ( prop2 !== undefined ) {
184
                        for ( ; i<ien ; i++ ) {
185
                                if ( a[i] && a[i][ prop ] ) {
186
                                        out.push( a[i][ prop ][ prop2 ] );
187
                                }
188
                        }
189
                }
190
                else {
191
                        for ( ; i<ien ; i++ ) {
192
                                if ( a[i] ) {
193
                                        out.push( a[i][ prop ] );
194
                                }
195
                        }
196
                }
197
 
198
                return out;
199
        };
200
 
201
 
202
        // Basically the same as _pluck, but rather than looping over `a` we use `order`
203
        // as the indexes to pick from `a`
204
        var _pluck_order = function ( a, order, prop, prop2 )
205
        {
206
                var out = [];
207
                var i=0, ien=order.length;
208
 
209
                // Could have the test in the loop for slightly smaller code, but speed
210
                // is essential here
211
                if ( prop2 !== undefined ) {
212
                        for ( ; i<ien ; i++ ) {
213
                                out.push( a[ order[i] ][ prop ][ prop2 ] );
214
                        }
215
                }
216
                else {
217
                        for ( ; i<ien ; i++ ) {
218
                                out.push( a[ order[i] ][ prop ] );
219
                        }
220
                }
221
 
222
                return out;
223
        };
224
 
225
 
226
        var _range = function ( len, start )
227
        {
228
                var out = [];
229
                var end;
230
 
231
                if ( start === undefined ) {
232
                        start = 0;
233
                        end = len;
234
                }
235
                else {
236
                        end = start;
237
                        start = len;
238
                }
239
 
240
                for ( var i=start ; i<end ; i++ ) {
241
                        out.push( i );
242
                }
243
 
244
                return out;
245
        };
246
 
247
 
248
        var _stripHtml = function ( d ) {
249
                return d.replace( _re_html, '' );
250
        };
251
 
252
 
253
        /**
254
         * Find the unique elements in a source array.
255
         *
256
         * @param  {array} src Source array
257
         * @return {array} Array of unique items
258
         * @ignore
259
         */
260
        var _unique = function ( src )
261
        {
262
                // A faster unique method is to use object keys to identify used values,
263
                // but this doesn't work with arrays or objects, which we must also
264
                // consider. See jsperf.com/compare-array-unique-versions/4 for more
265
                // information.
266
                var
267
                        out = [],
268
                        val,
269
                        i, ien=src.length,
270
                        j, k=0;
271
 
272
                again: for ( i=0 ; i<ien ; i++ ) {
273
                        val = src[i];
274
 
275
                        for ( j=0 ; j<k ; j++ ) {
276
                                if ( out[j] === val ) {
277
                                        continue again;
278
                                }
279
                        }
280
 
281
                        out.push( val );
282
                        k++;
283
                }
284
 
285
                return out;
286
        };
287
 
288
 
289
 
290
        /**
291
         * Create a mapping object that allows camel case parameters to be looked up
292
         * for their Hungarian counterparts. The mapping is stored in a private
293
         * parameter called `_hungarianMap` which can be accessed on the source object.
294
         *  @param {object} o
295
         *  @memberof DataTable#oApi
296
         */
297
        function _fnHungarianMap ( o )
298
        {
299
                var
300
                        hungarian = 'a aa ai ao as b fn i m o s ',
301
                        match,
302
                        newKey,
303
                        map = {};
304
 
305
                $.each( o, function (key, val) {
306
                        match = key.match(/^([^A-Z]+?)([A-Z])/);
307
 
308
                        if ( match && hungarian.indexOf(match[1]+' ') !== -1 )
309
                        {
310
                                newKey = key.replace( match[0], match[2].toLowerCase() );
311
                                map[ newKey ] = key;
312
 
313
                                //console.log( key, match );
314
                                if ( match[1] === 'o' )
315
                                {
316
                                        _fnHungarianMap( o[key] );
317
                                }
318
                        }
319
                } );
320
 
321
                o._hungarianMap = map;
322
        }
323
 
324
 
325
        /**
326
         * Convert from camel case parameters to Hungarian, based on a Hungarian map
327
         * created by _fnHungarianMap.
328
         *  @param {object} src The model object which holds all parameters that can be
329
         *    mapped.
330
         *  @param {object} user The object to convert from camel case to Hungarian.
331
         *  @param {boolean} force When set to `true`, properties which already have a
332
         *    Hungarian value in the `user` object will be overwritten. Otherwise they
333
         *    won't be.
334
         *  @memberof DataTable#oApi
335
         */
336
        function _fnCamelToHungarian ( src, user, force )
337
        {
338
                if ( ! src._hungarianMap ) {
339
                        _fnHungarianMap( src );
340
                }
341
 
342
                var hungarianKey;
343
 
344
                $.each( user, function (key, val) {
345
                        hungarianKey = src._hungarianMap[ key ];
346
 
347
                        if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) )
348
                        {
349
                                // For objects, we need to buzz down into the object to copy parameters
350
                                if ( hungarianKey.charAt(0) === 'o' )
351
                                {
352
                                        // Copy the camelCase options over to the hungarian
353
                                        if ( ! user[ hungarianKey ] ) {
354
                                                user[ hungarianKey ] = {};
355
                                        }
356
                                        $.extend( true, user[hungarianKey], user[key] );
357
 
358
                                        _fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force );
359
                                }
360
                                else {
361
                                        user[hungarianKey] = user[ key ];
362
                                }
363
                        }
364
                } );
365
        }
366
 
367
 
368
        /**
369
         * Language compatibility - when certain options are given, and others aren't, we
370
         * need to duplicate the values over, in order to provide backwards compatibility
371
         * with older language files.
372
         *  @param {object} oSettings dataTables settings object
373
         *  @memberof DataTable#oApi
374
         */
375
        function _fnLanguageCompat( lang )
376
        {
377
                var defaults = DataTable.defaults.oLanguage;
378
                var zeroRecords = lang.sZeroRecords;
379
 
380
                /* Backwards compatibility - if there is no sEmptyTable given, then use the same as
381
                 * sZeroRecords - assuming that is given.
382
                 */
383
                if ( ! lang.sEmptyTable && zeroRecords &&
384
                        defaults.sEmptyTable === "No data available in table" )
385
                {
386
                        _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' );
387
                }
388
 
389
                /* Likewise with loading records */
390
                if ( ! lang.sLoadingRecords && zeroRecords &&
391
                        defaults.sLoadingRecords === "Loading..." )
392
                {
393
                        _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' );
394
                }
395
 
396
                // Old parameter name of the thousands separator mapped onto the new
397
                if ( lang.sInfoThousands ) {
398
                        lang.sThousands = lang.sInfoThousands;
399
                }
400
 
401
                var decimal = lang.sDecimal;
402
                if ( decimal ) {
403
                        _addNumericSort( decimal );
404
                }
405
        }
406
 
407
 
408
        /**
409
         * Map one parameter onto another
410
         *  @param {object} o Object to map
411
         *  @param {*} knew The new parameter name
412
         *  @param {*} old The old parameter name
413
         */
414
        var _fnCompatMap = function ( o, knew, old ) {
415
                if ( o[ knew ] !== undefined ) {
416
                        o[ old ] = o[ knew ];
417
                }
418
        };
419
 
420
 
421
        /**
422
         * Provide backwards compatibility for the main DT options. Note that the new
423
         * options are mapped onto the old parameters, so this is an external interface
424
         * change only.
425
         *  @param {object} init Object to map
426
         */
427
        function _fnCompatOpts ( init )
428
        {
429
                _fnCompatMap( init, 'ordering',      'bSort' );
430
                _fnCompatMap( init, 'orderMulti',    'bSortMulti' );
431
                _fnCompatMap( init, 'orderClasses',  'bSortClasses' );
432
                _fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' );
433
                _fnCompatMap( init, 'order',         'aaSorting' );
434
                _fnCompatMap( init, 'orderFixed',    'aaSortingFixed' );
435
                _fnCompatMap( init, 'paging',        'bPaginate' );
436
                _fnCompatMap( init, 'pagingType',    'sPaginationType' );
437
                _fnCompatMap( init, 'pageLength',    'iDisplayLength' );
438
                _fnCompatMap( init, 'searching',     'bFilter' );
439
 
440
                // Column search objects are in an array, so it needs to be converted
441
                // element by element
442
                var searchCols = init.aoSearchCols;
443
 
444
                if ( searchCols ) {
445
                        for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) {
446
                                if ( searchCols[i] ) {
447
                                        _fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] );
448
                                }
449
                        }
450
                }
451
        }
452
 
453
 
454
        /**
455
         * Provide backwards compatibility for column options. Note that the new options
456
         * are mapped onto the old parameters, so this is an external interface change
457
         * only.
458
         *  @param {object} init Object to map
459
         */
460
        function _fnCompatCols ( init )
461
        {
462
                _fnCompatMap( init, 'orderable',     'bSortable' );
463
                _fnCompatMap( init, 'orderData',     'aDataSort' );
464
                _fnCompatMap( init, 'orderSequence', 'asSorting' );
465
                _fnCompatMap( init, 'orderDataType', 'sortDataType' );
466
        }
467
 
468
 
469
        /**
470
         * Browser feature detection for capabilities, quirks
471
         *  @param {object} settings dataTables settings object
472
         *  @memberof DataTable#oApi
473
         */
474
        function _fnBrowserDetect( settings )
475
        {
476
                var browser = settings.oBrowser;
477
 
478
                // Scrolling feature / quirks detection
479
                var n = $('<div/>')
480
                        .css( {
481
                                position: 'absolute',
482
                                top: 0,
483
                                left: 0,
484
                                height: 1,
485
                                width: 1,
486
                                overflow: 'hidden'
487
                        } )
488
                        .append(
489
                                $('<div/>')
490
                                        .css( {
491
                                                position: 'absolute',
492
                                                top: 1,
493
                                                left: 1,
494
                                                width: 100,
495
                                                overflow: 'scroll'
496
                                        } )
497
                                        .append(
498
                                                $('<div class="test"/>')
499
                                                        .css( {
500
                                                                width: '100%',
501
                                                                height: 10
502
                                                        } )
503
                                        )
504
                        )
505
                        .appendTo( 'body' );
506
 
507
                var test = n.find('.test');
508
 
509
                // IE6/7 will oversize a width 100% element inside a scrolling element, to
510
                // include the width of the scrollbar, while other browsers ensure the inner
511
                // element is contained without forcing scrolling
512
                browser.bScrollOversize = test[0].offsetWidth === 100;
513
 
514
                // In rtl text layout, some browsers (most, but not all) will place the
515
                // scrollbar on the left, rather than the right.
516
                browser.bScrollbarLeft = test.offset().left !== 1;
517
 
518
                n.remove();
519
        }
520
 
521
 
522
        /**
523
         * Array.prototype reduce[Right] method, used for browsers which don't support
524
         * JS 1.6. Done this way to reduce code size, since we iterate either way
525
         *  @param {object} settings dataTables settings object
526
         *  @memberof DataTable#oApi
527
         */
528
        function _fnReduce ( that, fn, init, start, end, inc )
529
        {
530
                var
531
                        i = start,
532
                        value,
533
                        isSet = false;
534
 
535
                if ( init !== undefined ) {
536
                        value = init;
537
                        isSet = true;
538
                }
539
 
540
                while ( i !== end ) {
541
                        if ( ! that.hasOwnProperty(i) ) {
542
                                continue;
543
                        }
544
 
545
                        value = isSet ?
546
                                fn( value, that[i], i, that ) :
547
                                that[i];
548
 
549
                        isSet = true;
550
                        i += inc;
551
                }
552
 
553
                return value;
554
        }
555
 
556
        /**
557
         * Add a column to the list used for the table with default values
558
         *  @param {object} oSettings dataTables settings object
559
         *  @param {node} nTh The th element for this column
560
         *  @memberof DataTable#oApi
561
         */
562
        function _fnAddColumn( oSettings, nTh )
563
        {
564
                // Add column to aoColumns array
565
                var oDefaults = DataTable.defaults.column;
566
                var iCol = oSettings.aoColumns.length;
567
                var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, {
568
                        "nTh": nTh ? nTh : document.createElement('th'),
569
                        "sTitle":    oDefaults.sTitle    ? oDefaults.sTitle    : nTh ? nTh.innerHTML : '',
570
                        "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol],
571
                        "mData": oDefaults.mData ? oDefaults.mData : iCol,
572
                        idx: iCol
573
                } );
574
                oSettings.aoColumns.push( oCol );
575
 
576
                // Add search object for column specific search. Note that the `searchCols[ iCol ]`
577
                // passed into extend can be undefined. This allows the user to give a default
578
                // with only some of the parameters defined, and also not give a default
579
                var searchCols = oSettings.aoPreSearchCols;
580
                searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] );
581
 
582
                // Use the default column options function to initialise classes etc
583
                _fnColumnOptions( oSettings, iCol, null );
584
        }
585
 
586
 
587
        /**
588
         * Apply options for a column
589
         *  @param {object} oSettings dataTables settings object
590
         *  @param {int} iCol column index to consider
591
         *  @param {object} oOptions object with sType, bVisible and bSearchable etc
592
         *  @memberof DataTable#oApi
593
         */
594
        function _fnColumnOptions( oSettings, iCol, oOptions )
595
        {
596
                var oCol = oSettings.aoColumns[ iCol ];
597
                var oClasses = oSettings.oClasses;
598
                var th = $(oCol.nTh);
599
 
600
                // Try to get width information from the DOM. We can't get it from CSS
601
                // as we'd need to parse the CSS stylesheet. `width` option can override
602
                if ( ! oCol.sWidthOrig ) {
603
                        // Width attribute
604
                        oCol.sWidthOrig = th.attr('width') || null;
605
 
606
                        // Style attribute
607
                        var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/);
608
                        if ( t ) {
609
                                oCol.sWidthOrig = t[1];
610
                        }
611
                }
612
 
613
                /* User specified column options */
614
                if ( oOptions !== undefined && oOptions !== null )
615
                {
616
                        // Backwards compatibility
617
                        _fnCompatCols( oOptions );
618
 
619
                        // Map camel case parameters to their Hungarian counterparts
620
                        _fnCamelToHungarian( DataTable.defaults.column, oOptions );
621
 
622
                        /* Backwards compatibility for mDataProp */
623
                        if ( oOptions.mDataProp !== undefined && !oOptions.mData )
624
                        {
625
                                oOptions.mData = oOptions.mDataProp;
626
                        }
627
 
628
                        if ( oOptions.sType )
629
                        {
630
                                oCol._sManualType = oOptions.sType;
631
                        }
632
 
633
                        // `class` is a reserved word in Javascript, so we need to provide
634
                        // the ability to use a valid name for the camel case input
635
                        if ( oOptions.className && ! oOptions.sClass )
636
                        {
637
                                oOptions.sClass = oOptions.className;
638
                        }
639
 
640
                        $.extend( oCol, oOptions );
641
                        _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" );
642
 
643
                        /* iDataSort to be applied (backwards compatibility), but aDataSort will take
644
                         * priority if defined
645
                         */
646
                        if ( typeof oOptions.iDataSort === 'number' )
647
                        {
648
                                oCol.aDataSort = [ oOptions.iDataSort ];
649
                        }
650
                        _fnMap( oCol, oOptions, "aDataSort" );
651
                }
652
 
653
                /* Cache the data get and set functions for speed */
654
                var mDataSrc = oCol.mData;
655
                var mData = _fnGetObjectDataFn( mDataSrc );
656
                var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null;
657
 
658
                var attrTest = function( src ) {
659
                        return typeof src === 'string' && src.indexOf('@') !== -1;
660
                };
661
                oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && (
662
                        attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter)
663
                );
664
 
665
                oCol.fnGetData = function (rowData, type, meta) {
666
                        var innerData = mData( rowData, type, undefined, meta );
667
 
668
                        return mRender && type ?
669
                                mRender( innerData, type, rowData, meta ) :
670
                                innerData;
671
                };
672
                oCol.fnSetData = function ( rowData, val, meta ) {
673
                        return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta );
674
                };
675
 
676
                /* Feature sorting overrides column specific when off */
677
                if ( !oSettings.oFeatures.bSort )
678
                {
679
                        oCol.bSortable = false;
680
                        th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called
681
                }
682
 
683
                /* Check that the class assignment is correct for sorting */
684
                var bAsc = $.inArray('asc', oCol.asSorting) !== -1;
685
                var bDesc = $.inArray('desc', oCol.asSorting) !== -1;
686
                if ( !oCol.bSortable || (!bAsc && !bDesc) )
687
                {
688
                        oCol.sSortingClass = oClasses.sSortableNone;
689
                        oCol.sSortingClassJUI = "";
690
                }
691
                else if ( bAsc && !bDesc )
692
                {
693
                        oCol.sSortingClass = oClasses.sSortableAsc;
694
                        oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed;
695
                }
696
                else if ( !bAsc && bDesc )
697
                {
698
                        oCol.sSortingClass = oClasses.sSortableDesc;
699
                        oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed;
700
                }
701
                else
702
                {
703
                        oCol.sSortingClass = oClasses.sSortable;
704
                        oCol.sSortingClassJUI = oClasses.sSortJUI;
705
                }
706
        }
707
 
708
 
709
        /**
710
         * Adjust the table column widths for new data. Note: you would probably want to
711
         * do a redraw after calling this function!
712
         *  @param {object} settings dataTables settings object
713
         *  @memberof DataTable#oApi
714
         */
715
        function _fnAdjustColumnSizing ( settings )
716
        {
717
                /* Not interested in doing column width calculation if auto-width is disabled */
718
                if ( settings.oFeatures.bAutoWidth !== false )
719
                {
720
                        var columns = settings.aoColumns;
721
 
722
                        _fnCalculateColumnWidths( settings );
723
                        for ( var i=0 , iLen=columns.length ; i<iLen ; i++ )
724
                        {
725
                                columns[i].nTh.style.width = columns[i].sWidth;
726
                        }
727
                }
728
 
729
                var scroll = settings.oScroll;
730
                if ( scroll.sY !== '' || scroll.sX !== '')
731
                {
732
                        _fnScrollDraw( settings );
733
                }
734
 
735
                _fnCallbackFire( settings, null, 'column-sizing', [settings] );
736
        }
737
 
738
 
739
        /**
740
         * Covert the index of a visible column to the index in the data array (take account
741
         * of hidden columns)
742
         *  @param {object} oSettings dataTables settings object
743
         *  @param {int} iMatch Visible column index to lookup
744
         *  @returns {int} i the data index
745
         *  @memberof DataTable#oApi
746
         */
747
        function _fnVisibleToColumnIndex( oSettings, iMatch )
748
        {
749
                var aiVis = _fnGetColumns( oSettings, 'bVisible' );
750
 
751
                return typeof aiVis[iMatch] === 'number' ?
752
                        aiVis[iMatch] :
753
                        null;
754
        }
755
 
756
 
757
        /**
758
         * Covert the index of an index in the data array and convert it to the visible
759
         *   column index (take account of hidden columns)
760
         *  @param {int} iMatch Column index to lookup
761
         *  @param {object} oSettings dataTables settings object
762
         *  @returns {int} i the data index
763
         *  @memberof DataTable#oApi
764
         */
765
        function _fnColumnIndexToVisible( oSettings, iMatch )
766
        {
767
                var aiVis = _fnGetColumns( oSettings, 'bVisible' );
768
                var iPos = $.inArray( iMatch, aiVis );
769
 
770
                return iPos !== -1 ? iPos : null;
771
        }
772
 
773
 
774
        /**
775
         * Get the number of visible columns
776
         *  @param {object} oSettings dataTables settings object
777
         *  @returns {int} i the number of visible columns
778
         *  @memberof DataTable#oApi
779
         */
780
        function _fnVisbleColumns( oSettings )
781
        {
782
                return _fnGetColumns( oSettings, 'bVisible' ).length;
783
        }
784
 
785
 
786
        /**
787
         * Get an array of column indexes that match a given property
788
         *  @param {object} oSettings dataTables settings object
789
         *  @param {string} sParam Parameter in aoColumns to look for - typically
790
         *    bVisible or bSearchable
791
         *  @returns {array} Array of indexes with matched properties
792
         *  @memberof DataTable#oApi
793
         */
794
        function _fnGetColumns( oSettings, sParam )
795
        {
796
                var a = [];
797
 
798
                $.map( oSettings.aoColumns, function(val, i) {
799
                        if ( val[sParam] ) {
800
                                a.push( i );
801
                        }
802
                } );
803
 
804
                return a;
805
        }
806
 
807
 
808
        /**
809
         * Calculate the 'type' of a column
810
         *  @param {object} settings dataTables settings object
811
         *  @memberof DataTable#oApi
812
         */
813
        function _fnColumnTypes ( settings )
814
        {
815
                var columns = settings.aoColumns;
816
                var data = settings.aoData;
817
                var types = DataTable.ext.type.detect;
818
                var i, ien, j, jen, k, ken;
819
                var col, cell, detectedType, cache;
820
 
821
                // For each column, spin over the 
822
                for ( i=0, ien=columns.length ; i<ien ; i++ ) {
823
                        col = columns[i];
824
                        cache = [];
825
 
826
                        if ( ! col.sType && col._sManualType ) {
827
                                col.sType = col._sManualType;
828
                        }
829
                        else if ( ! col.sType ) {
830
                                for ( j=0, jen=types.length ; j<jen ; j++ ) {
831
                                        for ( k=0, ken=data.length ; k<ken ; k++ ) {
832
                                                // Use a cache array so we only need to get the type data
833
                                                // from the formatter once (when using multiple detectors)
834
                                                if ( cache[k] === undefined ) {
835
                                                        cache[k] = _fnGetCellData( settings, k, i, 'type' );
836
                                                }
837
 
838
                                                detectedType = types[j]( cache[k], settings );
839
 
840
                                                // Doesn't match, so break early, since this type can't
841
                                                // apply to this column. Also, HTML is a special case since
842
                                                // it is so similar to `string`. Just a single match is
843
                                                // needed for a column to be html type
844
                                                if ( ! detectedType || detectedType === 'html' ) {
845
                                                        break;
846
                                                }
847
                                        }
848
 
849
                                        // Type is valid for all data points in the column - use this
850
                                        // type
851
                                        if ( detectedType ) {
852
                                                col.sType = detectedType;
853
                                                break;
854
                                        }
855
                                }
856
 
857
                                // Fall back - if no type was detected, always use string
858
                                if ( ! col.sType ) {
859
                                        col.sType = 'string';
860
                                }
861
                        }
862
                }
863
        }
864
 
865
 
866
        /**
867
         * Take the column definitions and static columns arrays and calculate how
868
         * they relate to column indexes. The callback function will then apply the
869
         * definition found for a column to a suitable configuration object.
870
         *  @param {object} oSettings dataTables settings object
871
         *  @param {array} aoColDefs The aoColumnDefs array that is to be applied
872
         *  @param {array} aoCols The aoColumns array that defines columns individually
873
         *  @param {function} fn Callback function - takes two parameters, the calculated
874
         *    column index and the definition for that column.
875
         *  @memberof DataTable#oApi
876
         */
877
        function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn )
878
        {
879
                var i, iLen, j, jLen, k, kLen, def;
880
                var columns = oSettings.aoColumns;
881
 
882
                // Column definitions with aTargets
883
                if ( aoColDefs )
884
                {
885
                        /* Loop over the definitions array - loop in reverse so first instance has priority */
886
                        for ( i=aoColDefs.length-1 ; i>=0 ; i-- )
887
                        {
888
                                def = aoColDefs[i];
889
 
890
                                /* Each definition can target multiple columns, as it is an array */
891
                                var aTargets = def.targets !== undefined ?
892
                                        def.targets :
893
                                        def.aTargets;
894
 
895
                                if ( ! $.isArray( aTargets ) )
896
                                {
897
                                        aTargets = [ aTargets ];
898
                                }
899
 
900
                                for ( j=0, jLen=aTargets.length ; j<jLen ; j++ )
901
                                {
902
                                        if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 )
903
                                        {
904
                                                /* Add columns that we don't yet know about */
905
                                                while( columns.length <= aTargets[j] )
906
                                                {
907
                                                        _fnAddColumn( oSettings );
908
                                                }
909
 
910
                                                /* Integer, basic index */
911
                                                fn( aTargets[j], def );
912
                                        }
913
                                        else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 )
914
                                        {
915
                                                /* Negative integer, right to left column counting */
916
                                                fn( columns.length+aTargets[j], def );
917
                                        }
918
                                        else if ( typeof aTargets[j] === 'string' )
919
                                        {
920
                                                /* Class name matching on TH element */
921
                                                for ( k=0, kLen=columns.length ; k<kLen ; k++ )
922
                                                {
923
                                                        if ( aTargets[j] == "_all" ||
924
                                                             $(columns[k].nTh).hasClass( aTargets[j] ) )
925
                                                        {
926
                                                                fn( k, def );
927
                                                        }
928
                                                }
929
                                        }
930
                                }
931
                        }
932
                }
933
 
934
                // Statically defined columns array
935
                if ( aoCols )
936
                {
937
                        for ( i=0, iLen=aoCols.length ; i<iLen ; i++ )
938
                        {
939
                                fn( i, aoCols[i] );
940
                        }
941
                }
942
        }
943
 
944
        /**
945
         * Add a data array to the table, creating DOM node etc. This is the parallel to
946
         * _fnGatherData, but for adding rows from a Javascript source, rather than a
947
         * DOM source.
948
         *  @param {object} oSettings dataTables settings object
949
         *  @param {array} aData data array to be added
950
         *  @param {node} [nTr] TR element to add to the table - optional. If not given,
951
         *    DataTables will create a row automatically
952
         *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
953
         *    if nTr is.
954
         *  @returns {int} >=0 if successful (index of new aoData entry), -1 if failed
955
         *  @memberof DataTable#oApi
956
         */
957
        function _fnAddData ( oSettings, aDataIn, nTr, anTds )
958
        {
959
                /* Create the object for storing information about this new row */
960
                var iRow = oSettings.aoData.length;
961
                var oData = $.extend( true, {}, DataTable.models.oRow, {
962
                        src: nTr ? 'dom' : 'data'
963
                } );
964
 
965
                oData._aData = aDataIn;
966
                oSettings.aoData.push( oData );
967
 
968
                /* Create the cells */
969
                var nTd, sThisType;
970
                var columns = oSettings.aoColumns;
971
                for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
972
                {
973
                        // When working with a row, the data source object must be populated. In
974
                        // all other cases, the data source object is already populated, so we
975
                        // don't overwrite it, which might break bindings etc
976
                        if ( nTr ) {
977
                                _fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) );
978
                        }
979
                        columns[i].sType = null;
980
                }
981
 
982
                /* Add to the display array */
983
                oSettings.aiDisplayMaster.push( iRow );
984
 
985
                /* Create the DOM information, or register it if already present */
986
                if ( nTr || ! oSettings.oFeatures.bDeferRender )
987
                {
988
                        _fnCreateTr( oSettings, iRow, nTr, anTds );
989
                }
990
 
991
                return iRow;
992
        }
993
 
994
 
995
        /**
996
         * Add one or more TR elements to the table. Generally we'd expect to
997
         * use this for reading data from a DOM sourced table, but it could be
998
         * used for an TR element. Note that if a TR is given, it is used (i.e.
999
         * it is not cloned).
1000
         *  @param {object} settings dataTables settings object
1001
         *  @param {array|node|jQuery} trs The TR element(s) to add to the table
1002
         *  @returns {array} Array of indexes for the added rows
1003
         *  @memberof DataTable#oApi
1004
         */
1005
        function _fnAddTr( settings, trs )
1006
        {
1007
                var row;
1008
 
1009
                // Allow an individual node to be passed in
1010
                if ( ! (trs instanceof $) ) {
1011
                        trs = $(trs);
1012
                }
1013
 
1014
                return trs.map( function (i, el) {
1015
                        row = _fnGetRowElements( settings, el );
1016
                        return _fnAddData( settings, row.data, el, row.cells );
1017
                } );
1018
        }
1019
 
1020
 
1021
        /**
1022
         * Take a TR element and convert it to an index in aoData
1023
         *  @param {object} oSettings dataTables settings object
1024
         *  @param {node} n the TR element to find
1025
         *  @returns {int} index if the node is found, null if not
1026
         *  @memberof DataTable#oApi
1027
         */
1028
        function _fnNodeToDataIndex( oSettings, n )
1029
        {
1030
                return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null;
1031
        }
1032
 
1033
 
1034
        /**
1035
         * Take a TD element and convert it into a column data index (not the visible index)
1036
         *  @param {object} oSettings dataTables settings object
1037
         *  @param {int} iRow The row number the TD/TH can be found in
1038
         *  @param {node} n The TD/TH element to find
1039
         *  @returns {int} index if the node is found, -1 if not
1040
         *  @memberof DataTable#oApi
1041
         */
1042
        function _fnNodeToColumnIndex( oSettings, iRow, n )
1043
        {
1044
                return $.inArray( n, oSettings.aoData[ iRow ].anCells );
1045
        }
1046
 
1047
 
1048
        /**
1049
         * Get the data for a given cell from the internal cache, taking into account data mapping
1050
         *  @param {object} settings dataTables settings object
1051
         *  @param {int} rowIdx aoData row id
1052
         *  @param {int} colIdx Column index
1053
         *  @param {string} type data get type ('display', 'type' 'filter' 'sort')
1054
         *  @returns {*} Cell data
1055
         *  @memberof DataTable#oApi
1056
         */
1057
        function _fnGetCellData( settings, rowIdx, colIdx, type )
1058
        {
1059
                var draw           = settings.iDraw;
1060
                var col            = settings.aoColumns[colIdx];
1061
                var rowData        = settings.aoData[rowIdx]._aData;
1062
                var defaultContent = col.sDefaultContent;
1063
                var cellData       = col.fnGetData( rowData, type, {
1064
                        settings: settings,
1065
                        row:      rowIdx,
1066
                        col:      colIdx
1067
                } );
1068
 
1069
                if ( cellData === undefined ) {
1070
                        if ( settings.iDrawError != draw && defaultContent === null ) {
1071
                                _fnLog( settings, 0, "Requested unknown parameter "+
1072
                                        (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+
1073
                                        " for row "+rowIdx, 4 );
1074
                                settings.iDrawError = draw;
1075
                        }
1076
                        return defaultContent;
1077
                }
1078
 
1079
                /* When the data source is null, we can use default column data */
1080
                if ( (cellData === rowData || cellData === null) && defaultContent !== null ) {
1081
                        cellData = defaultContent;
1082
                }
1083
                else if ( typeof cellData === 'function' ) {
1084
                        // If the data source is a function, then we run it and use the return,
1085
                        // executing in the scope of the data object (for instances)
1086
                        return cellData.call( rowData );
1087
                }
1088
 
1089
                if ( cellData === null && type == 'display' ) {
1090
                        return '';
1091
                }
1092
                return cellData;
1093
        }
1094
 
1095
 
1096
        /**
1097
         * Set the value for a specific cell, into the internal data cache
1098
         *  @param {object} settings dataTables settings object
1099
         *  @param {int} rowIdx aoData row id
1100
         *  @param {int} colIdx Column index
1101
         *  @param {*} val Value to set
1102
         *  @memberof DataTable#oApi
1103
         */
1104
        function _fnSetCellData( settings, rowIdx, colIdx, val )
1105
        {
1106
                var col     = settings.aoColumns[colIdx];
1107
                var rowData = settings.aoData[rowIdx]._aData;
1108
 
1109
                col.fnSetData( rowData, val, {
1110
                        settings: settings,
1111
                        row:      rowIdx,
1112
                        col:      colIdx
1113
                }  );
1114
        }
1115
 
1116
 
1117
        // Private variable that is used to match action syntax in the data property object
1118
        var __reArray = /\[.*?\]$/;
1119
        var __reFn = /\(\)$/;
1120
 
1121
        /**
1122
         * Split string on periods, taking into account escaped periods
1123
         * @param  {string} str String to split
1124
         * @return {array} Split string
1125
         */
1126
        function _fnSplitObjNotation( str )
1127
        {
1128
                return $.map( str.match(/(\\.|[^\.])+/g), function ( s ) {
1129
                        return s.replace(/\\./g, '.');
1130
                } );
1131
        }
1132
 
1133
 
1134
        /**
1135
         * Return a function that can be used to get data from a source object, taking
1136
         * into account the ability to use nested objects as a source
1137
         *  @param {string|int|function} mSource The data source for the object
1138
         *  @returns {function} Data get function
1139
         *  @memberof DataTable#oApi
1140
         */
1141
        function _fnGetObjectDataFn( mSource )
1142
        {
1143
                if ( $.isPlainObject( mSource ) )
1144
                {
1145
                        /* Build an object of get functions, and wrap them in a single call */
1146
                        var o = {};
1147
                        $.each( mSource, function (key, val) {
1148
                                if ( val ) {
1149
                                        o[key] = _fnGetObjectDataFn( val );
1150
                                }
1151
                        } );
1152
 
1153
                        return function (data, type, row, meta) {
1154
                                var t = o[type] || o._;
1155
                                return t !== undefined ?
1156
                                        t(data, type, row, meta) :
1157
                                        data;
1158
                        };
1159
                }
1160
                else if ( mSource === null )
1161
                {
1162
                        /* Give an empty string for rendering / sorting etc */
1163
                        return function (data) { // type, row and meta also passed, but not used
1164
                                return data;
1165
                        };
1166
                }
1167
                else if ( typeof mSource === 'function' )
1168
                {
1169
                        return function (data, type, row, meta) {
1170
                                return mSource( data, type, row, meta );
1171
                        };
1172
                }
1173
                else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
1174
                              mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
1175
                {
1176
                        /* If there is a . in the source string then the data source is in a
1177
                         * nested object so we loop over the data for each level to get the next
1178
                         * level down. On each loop we test for undefined, and if found immediately
1179
                         * return. This allows entire objects to be missing and sDefaultContent to
1180
                         * be used if defined, rather than throwing an error
1181
                         */
1182
                        var fetchData = function (data, type, src) {
1183
                                var arrayNotation, funcNotation, out, innerSrc;
1184
 
1185
                                if ( src !== "" )
1186
                                {
1187
                                        var a = _fnSplitObjNotation( src );
1188
 
1189
                                        for ( var i=0, iLen=a.length ; i<iLen ; i++ )
1190
                                        {
1191
                                                // Check if we are dealing with special notation
1192
                                                arrayNotation = a[i].match(__reArray);
1193
                                                funcNotation = a[i].match(__reFn);
1194
 
1195
                                                if ( arrayNotation )
1196
                                                {
1197
                                                        // Array notation
1198
                                                        a[i] = a[i].replace(__reArray, '');
1199
 
1200
                                                        // Condition allows simply [] to be passed in
1201
                                                        if ( a[i] !== "" ) {
1202
                                                                data = data[ a[i] ];
1203
                                                        }
1204
                                                        out = [];
1205
 
1206
                                                        // Get the remainder of the nested object to get
1207
                                                        a.splice( 0, i+1 );
1208
                                                        innerSrc = a.join('.');
1209
 
1210
                                                        // Traverse each entry in the array getting the properties requested
1211
                                                        for ( var j=0, jLen=data.length ; j<jLen ; j++ ) {
1212
                                                                out.push( fetchData( data[j], type, innerSrc ) );
1213
                                                        }
1214
 
1215
                                                        // If a string is given in between the array notation indicators, that
1216
                                                        // is used to join the strings together, otherwise an array is returned
1217
                                                        var join = arrayNotation[0].substring(1, arrayNotation[0].length-1);
1218
                                                        data = (join==="") ? out : out.join(join);
1219
 
1220
                                                        // The inner call to fetchData has already traversed through the remainder
1221
                                                        // of the source requested, so we exit from the loop
1222
                                                        break;
1223
                                                }
1224
                                                else if ( funcNotation )
1225
                                                {
1226
                                                        // Function call
1227
                                                        a[i] = a[i].replace(__reFn, '');
1228
                                                        data = data[ a[i] ]();
1229
                                                        continue;
1230
                                                }
1231
 
1232
                                                if ( data === null || data[ a[i] ] === undefined )
1233
                                                {
1234
                                                        return undefined;
1235
                                                }
1236
                                                data = data[ a[i] ];
1237
                                        }
1238
                                }
1239
 
1240
                                return data;
1241
                        };
1242
 
1243
                        return function (data, type) { // row and meta also passed, but not used
1244
                                return fetchData( data, type, mSource );
1245
                        };
1246
                }
1247
                else
1248
                {
1249
                        /* Array or flat object mapping */
1250
                        return function (data, type) { // row and meta also passed, but not used
1251
                                return data[mSource];
1252
                        };
1253
                }
1254
        }
1255
 
1256
 
1257
        /**
1258
         * Return a function that can be used to set data from a source object, taking
1259
         * into account the ability to use nested objects as a source
1260
         *  @param {string|int|function} mSource The data source for the object
1261
         *  @returns {function} Data set function
1262
         *  @memberof DataTable#oApi
1263
         */
1264
        function _fnSetObjectDataFn( mSource )
1265
        {
1266
                if ( $.isPlainObject( mSource ) )
1267
                {
1268
                        /* Unlike get, only the underscore (global) option is used for for
1269
                         * setting data since we don't know the type here. This is why an object
1270
                         * option is not documented for `mData` (which is read/write), but it is
1271
                         * for `mRender` which is read only.
1272
                         */
1273
                        return _fnSetObjectDataFn( mSource._ );
1274
                }
1275
                else if ( mSource === null )
1276
                {
1277
                        /* Nothing to do when the data source is null */
1278
                        return function () {};
1279
                }
1280
                else if ( typeof mSource === 'function' )
1281
                {
1282
                        return function (data, val, meta) {
1283
                                mSource( data, 'set', val, meta );
1284
                        };
1285
                }
1286
                else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 ||
1287
                              mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) )
1288
                {
1289
                        /* Like the get, we need to get data from a nested object */
1290
                        var setData = function (data, val, src) {
1291
                                var a = _fnSplitObjNotation( src ), b;
1292
                                var aLast = a[a.length-1];
1293
                                var arrayNotation, funcNotation, o, innerSrc;
1294
 
1295
                                for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ )
1296
                                {
1297
                                        // Check if we are dealing with an array notation request
1298
                                        arrayNotation = a[i].match(__reArray);
1299
                                        funcNotation = a[i].match(__reFn);
1300
 
1301
                                        if ( arrayNotation )
1302
                                        {
1303
                                                a[i] = a[i].replace(__reArray, '');
1304
                                                data[ a[i] ] = [];
1305
 
1306
                                                // Get the remainder of the nested object to set so we can recurse
1307
                                                b = a.slice();
1308
                                                b.splice( 0, i+1 );
1309
                                                innerSrc = b.join('.');
1310
 
1311
                                                // Traverse each entry in the array setting the properties requested
1312
                                                for ( var j=0, jLen=val.length ; j<jLen ; j++ )
1313
                                                {
1314
                                                        o = {};
1315
                                                        setData( o, val[j], innerSrc );
1316
                                                        data[ a[i] ].push( o );
1317
                                                }
1318
 
1319
                                                // The inner call to setData has already traversed through the remainder
1320
                                                // of the source and has set the data, thus we can exit here
1321
                                                return;
1322
                                        }
1323
                                        else if ( funcNotation )
1324
                                        {
1325
                                                // Function call
1326
                                                a[i] = a[i].replace(__reFn, '');
1327
                                                data = data[ a[i] ]( val );
1328
                                        }
1329
 
1330
                                        // If the nested object doesn't currently exist - since we are
1331
                                        // trying to set the value - create it
1332
                                        if ( data[ a[i] ] === null || data[ a[i] ] === undefined )
1333
                                        {
1334
                                                data[ a[i] ] = {};
1335
                                        }
1336
                                        data = data[ a[i] ];
1337
                                }
1338
 
1339
                                // Last item in the input - i.e, the actual set
1340
                                if ( aLast.match(__reFn ) )
1341
                                {
1342
                                        // Function call
1343
                                        data = data[ aLast.replace(__reFn, '') ]( val );
1344
                                }
1345
                                else
1346
                                {
1347
                                        // If array notation is used, we just want to strip it and use the property name
1348
                                        // and assign the value. If it isn't used, then we get the result we want anyway
1349
                                        data[ aLast.replace(__reArray, '') ] = val;
1350
                                }
1351
                        };
1352
 
1353
                        return function (data, val) { // meta is also passed in, but not used
1354
                                return setData( data, val, mSource );
1355
                        };
1356
                }
1357
                else
1358
                {
1359
                        /* Array or flat object mapping */
1360
                        return function (data, val) { // meta is also passed in, but not used
1361
                                data[mSource] = val;
1362
                        };
1363
                }
1364
        }
1365
 
1366
 
1367
        /**
1368
         * Return an array with the full table data
1369
         *  @param {object} oSettings dataTables settings object
1370
         *  @returns array {array} aData Master data array
1371
         *  @memberof DataTable#oApi
1372
         */
1373
        function _fnGetDataMaster ( settings )
1374
        {
1375
                return _pluck( settings.aoData, '_aData' );
1376
        }
1377
 
1378
 
1379
        /**
1380
         * Nuke the table
1381
         *  @param {object} oSettings dataTables settings object
1382
         *  @memberof DataTable#oApi
1383
         */
1384
        function _fnClearTable( settings )
1385
        {
1386
                settings.aoData.length = 0;
1387
                settings.aiDisplayMaster.length = 0;
1388
                settings.aiDisplay.length = 0;
1389
        }
1390
 
1391
 
1392
         /**
1393
         * Take an array of integers (index array) and remove a target integer (value - not
1394
         * the key!)
1395
         *  @param {array} a Index array to target
1396
         *  @param {int} iTarget value to find
1397
         *  @memberof DataTable#oApi
1398
         */
1399
        function _fnDeleteIndex( a, iTarget, splice )
1400
        {
1401
                var iTargetIndex = -1;
1402
 
1403
                for ( var i=0, iLen=a.length ; i<iLen ; i++ )
1404
                {
1405
                        if ( a[i] == iTarget )
1406
                        {
1407
                                iTargetIndex = i;
1408
                        }
1409
                        else if ( a[i] > iTarget )
1410
                        {
1411
                                a[i]--;
1412
                        }
1413
                }
1414
 
1415
                if ( iTargetIndex != -1 && splice === undefined )
1416
                {
1417
                        a.splice( iTargetIndex, 1 );
1418
                }
1419
        }
1420
 
1421
 
1422
        /**
1423
         * Mark cached data as invalid such that a re-read of the data will occur when
1424
         * the cached data is next requested. Also update from the data source object.
1425
         *
1426
         * @param {object} settings DataTables settings object
1427
         * @param  {int}    rowIdx   Row index to invalidate
1428
         * @memberof DataTable#oApi
1429
         *
1430
         * @todo For the modularisation of v1.11 this will need to become a callback, so
1431
         *   the sort and filter methods can subscribe to it. That will required
1432
         *   initialisation options for sorting, which is why it is not already baked in
1433
         */
1434
        function _fnInvalidateRow( settings, rowIdx, src, column )
1435
        {
1436
                var row = settings.aoData[ rowIdx ];
1437
                var i, ien;
1438
 
1439
                // Are we reading last data from DOM or the data object?
1440
                if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) {
1441
                        // Read the data from the DOM
1442
                        row._aData = _fnGetRowElements( settings, row ).data;
1443
                }
1444
                else {
1445
                        // Reading from data object, update the DOM
1446
                        var cells = row.anCells;
1447
                        var cell;
1448
 
1449
                        if ( cells ) {
1450
                                for ( i=0, ien=cells.length ; i<ien ; i++ ) {
1451
                                        cell = cells[i];
1452
 
1453
                                        // This is very frustrating, but in IE if you just write directly
1454
                                        // to innerHTML, and elements that are overwritten are GC'ed,
1455
                                        // even if there is a reference to them elsewhere
1456
                                        while ( cell.childNodes.length ) {
1457
                                                cell.removeChild( cell.firstChild );
1458
                                        }
1459
 
1460
                                        cells[i].innerHTML = _fnGetCellData( settings, rowIdx, i, 'display' );
1461
                                }
1462
                        }
1463
                }
1464
 
1465
                row._aSortData = null;
1466
                row._aFilterData = null;
1467
 
1468
                // Invalidate the type for a specific column (if given) or all columns since
1469
                // the data might have changed
1470
                var cols = settings.aoColumns;
1471
                if ( column !== undefined ) {
1472
                        cols[ column ].sType = null;
1473
                }
1474
                else {
1475
                        for ( i=0, ien=cols.length ; i<ien ; i++ ) {
1476
                                cols[i].sType = null;
1477
                        }
1478
                }
1479
 
1480
                // Update DataTables special `DT_*` attributes for the row
1481
                _fnRowAttributes( row );
1482
        }
1483
 
1484
 
1485
        /**
1486
         * Build a data source object from an HTML row, reading the contents of the
1487
         * cells that are in the row.
1488
         *
1489
         * @param {object} settings DataTables settings object
1490
         * @param {node|object} TR element from which to read data or existing row
1491
         *   object from which to re-read the data from the cells
1492
         * @returns {object} Object with two parameters: `data` the data read, in
1493
         *   document order, and `cells` and array of nodes (they can be useful to the
1494
         *   caller, so rather than needing a second traversal to get them, just return
1495
         *   them from here).
1496
         * @memberof DataTable#oApi
1497
         */
1498
        function _fnGetRowElements( settings, row )
1499
        {
1500
                var
1501
                        d = [],
1502
                        tds = [],
1503
                        td = row.firstChild,
1504
                        name, col, o, i=0, contents,
1505
                        columns = settings.aoColumns;
1506
 
1507
                var attr = function ( str, data, td  ) {
1508
                        if ( typeof str === 'string' ) {
1509
                                var idx = str.indexOf('@');
1510
 
1511
                                if ( idx !== -1 ) {
1512
                                        var src = str.substring( idx+1 );
1513
                                        o[ '@'+src ] = td.getAttribute( src );
1514
                                }
1515
                        }
1516
                };
1517
 
1518
                var cellProcess = function ( cell ) {
1519
                        col = columns[i];
1520
                        contents = $.trim(cell.innerHTML);
1521
 
1522
                        if ( col && col._bAttrSrc ) {
1523
                                o = {
1524
                                        display: contents
1525
                                };
1526
 
1527
                                attr( col.mData.sort, o, cell );
1528
                                attr( col.mData.type, o, cell );
1529
                                attr( col.mData.filter, o, cell );
1530
 
1531
                                d.push( o );
1532
                        }
1533
                        else {
1534
                                d.push( contents );
1535
                        }
1536
 
1537
                        i++;
1538
                };
1539
 
1540
                if ( td ) {
1541
                        // `tr` element passed in
1542
                        while ( td ) {
1543
                                name = td.nodeName.toUpperCase();
1544
 
1545
                                if ( name == "TD" || name == "TH" ) {
1546
                                        cellProcess( td );
1547
                                        tds.push( td );
1548
                                }
1549
 
1550
                                td = td.nextSibling;
1551
                        }
1552
                }
1553
                else {
1554
                        // Existing row object passed in
1555
                        tds = row.anCells;
1556
 
1557
                        for ( var j=0, jen=tds.length ; j<jen ; j++ ) {
1558
                                cellProcess( tds[j] );
1559
                        }
1560
                }
1561
 
1562
                return {
1563
                        data: d,
1564
                        cells: tds
1565
                };
1566
        }
1567
        /**
1568
         * Create a new TR element (and it's TD children) for a row
1569
         *  @param {object} oSettings dataTables settings object
1570
         *  @param {int} iRow Row to consider
1571
         *  @param {node} [nTrIn] TR element to add to the table - optional. If not given,
1572
         *    DataTables will create a row automatically
1573
         *  @param {array} [anTds] Array of TD|TH elements for the row - must be given
1574
         *    if nTr is.
1575
         *  @memberof DataTable#oApi
1576
         */
1577
        function _fnCreateTr ( oSettings, iRow, nTrIn, anTds )
1578
        {
1579
                var
1580
                        row = oSettings.aoData[iRow],
1581
                        rowData = row._aData,
1582
                        cells = [],
1583
                        nTr, nTd, oCol,
1584
                        i, iLen;
1585
 
1586
                if ( row.nTr === null )
1587
                {
1588
                        nTr = nTrIn || document.createElement('tr');
1589
 
1590
                        row.nTr = nTr;
1591
                        row.anCells = cells;
1592
 
1593
                        /* Use a private property on the node to allow reserve mapping from the node
1594
                         * to the aoData array for fast look up
1595
                         */
1596
                        nTr._DT_RowIndex = iRow;
1597
 
1598
                        /* Special parameters can be given by the data source to be used on the row */
1599
                        _fnRowAttributes( row );
1600
 
1601
                        /* Process each column */
1602
                        for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ )
1603
                        {
1604
                                oCol = oSettings.aoColumns[i];
1605
 
1606
                                nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType );
1607
                                cells.push( nTd );
1608
 
1609
                                // Need to create the HTML if new, or if a rendering function is defined
1610
                                if ( !nTrIn || oCol.mRender || oCol.mData !== i )
1611
                                {
1612
                                        nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' );
1613
                                }
1614
 
1615
                                /* Add user defined class */
1616
                                if ( oCol.sClass )
1617
                                {
1618
                                        nTd.className += ' '+oCol.sClass;
1619
                                }
1620
 
1621
                                // Visibility - add or remove as required
1622
                                if ( oCol.bVisible && ! nTrIn )
1623
                                {
1624
                                        nTr.appendChild( nTd );
1625
                                }
1626
                                else if ( ! oCol.bVisible && nTrIn )
1627
                                {
1628
                                        nTd.parentNode.removeChild( nTd );
1629
                                }
1630
 
1631
                                if ( oCol.fnCreatedCell )
1632
                                {
1633
                                        oCol.fnCreatedCell.call( oSettings.oInstance,
1634
                                                nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i
1635
                                        );
1636
                                }
1637
                        }
1638
 
1639
                        _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] );
1640
                }
1641
 
1642
                // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved
1643
                // and deployed
1644
                row.nTr.setAttribute( 'role', 'row' );
1645
        }
1646
 
1647
 
1648
        /**
1649
         * Add attributes to a row based on the special `DT_*` parameters in a data
1650
         * source object.
1651
         *  @param {object} DataTables row object for the row to be modified
1652
         *  @memberof DataTable#oApi
1653
         */
1654
        function _fnRowAttributes( row )
1655
        {
1656
                var tr = row.nTr;
1657
                var data = row._aData;
1658
 
1659
                if ( tr ) {
1660
                        if ( data.DT_RowId ) {
1661
                                tr.id = data.DT_RowId;
1662
                        }
1663
 
1664
                        if ( data.DT_RowClass ) {
1665
                                // Remove any classes added by DT_RowClass before
1666
                                var a = data.DT_RowClass.split(' ');
1667
                                row.__rowc = row.__rowc ?
1668
                                        _unique( row.__rowc.concat( a ) ) :
1669
                                        a;
1670
 
1671
                                $(tr)
1672
                                        .removeClass( row.__rowc.join(' ') )
1673
                                        .addClass( data.DT_RowClass );
1674
                        }
1675
 
1676
                        if ( data.DT_RowData ) {
1677
                                $(tr).data( data.DT_RowData );
1678
                        }
1679
                }
1680
        }
1681
 
1682
 
1683
        /**
1684
         * Create the HTML header for the table
1685
         *  @param {object} oSettings dataTables settings object
1686
         *  @memberof DataTable#oApi
1687
         */
1688
        function _fnBuildHead( oSettings )
1689
        {
1690
                var i, ien, cell, row, column;
1691
                var thead = oSettings.nTHead;
1692
                var tfoot = oSettings.nTFoot;
1693
                var createHeader = $('th, td', thead).length === 0;
1694
                var classes = oSettings.oClasses;
1695
                var columns = oSettings.aoColumns;
1696
 
1697
                if ( createHeader ) {
1698
                        row = $('<tr/>').appendTo( thead );
1699
                }
1700
 
1701
                for ( i=0, ien=columns.length ; i<ien ; i++ ) {
1702
                        column = columns[i];
1703
                        cell = $( column.nTh ).addClass( column.sClass );
1704
 
1705
                        if ( createHeader ) {
1706
                                cell.appendTo( row );
1707
                        }
1708
 
1709
                        // 1.11 move into sorting
1710
                        if ( oSettings.oFeatures.bSort ) {
1711
                                cell.addClass( column.sSortingClass );
1712
 
1713
                                if ( column.bSortable !== false ) {
1714
                                        cell
1715
                                                .attr( 'tabindex', oSettings.iTabIndex )
1716
                                                .attr( 'aria-controls', oSettings.sTableId );
1717
 
1718
                                        _fnSortAttachListener( oSettings, column.nTh, i );
1719
                                }
1720
                        }
1721
 
1722
                        if ( column.sTitle != cell.html() ) {
1723
                                cell.html( column.sTitle );
1724
                        }
1725
 
1726
                        _fnRenderer( oSettings, 'header' )(
1727
                                oSettings, cell, column, classes
1728
                        );
1729
                }
1730
 
1731
                if ( createHeader ) {
1732
                        _fnDetectHeader( oSettings.aoHeader, thead );
1733
                }
1734
 
1735
                /* ARIA role for the rows */
1736
                $(thead).find('>tr').attr('role', 'row');
1737
 
1738
                /* Deal with the footer - add classes if required */
1739
                $(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH );
1740
                $(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH );
1741
 
1742
                // Cache the footer cells. Note that we only take the cells from the first
1743
                // row in the footer. If there is more than one row the user wants to
1744
                // interact with, they need to use the table().foot() method. Note also this
1745
                // allows cells to be used for multiple columns using colspan
1746
                if ( tfoot !== null ) {
1747
                        var cells = oSettings.aoFooter[0];
1748
 
1749
                        for ( i=0, ien=cells.length ; i<ien ; i++ ) {
1750
                                column = columns[i];
1751
                                column.nTf = cells[i].cell;
1752
 
1753
                                if ( column.sClass ) {
1754
                                        $(column.nTf).addClass( column.sClass );
1755
                                }
1756
                        }
1757
                }
1758
        }
1759
 
1760
 
1761
        /**
1762
         * Draw the header (or footer) element based on the column visibility states. The
1763
         * methodology here is to use the layout array from _fnDetectHeader, modified for
1764
         * the instantaneous column visibility, to construct the new layout. The grid is
1765
         * traversed over cell at a time in a rows x columns grid fashion, although each
1766
         * cell insert can cover multiple elements in the grid - which is tracks using the
1767
         * aApplied array. Cell inserts in the grid will only occur where there isn't
1768
         * already a cell in that position.
1769
         *  @param {object} oSettings dataTables settings object
1770
         *  @param array {objects} aoSource Layout array from _fnDetectHeader
1771
         *  @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc,
1772
         *  @memberof DataTable#oApi
1773
         */
1774
        function _fnDrawHead( oSettings, aoSource, bIncludeHidden )
1775
        {
1776
                var i, iLen, j, jLen, k, kLen, n, nLocalTr;
1777
                var aoLocal = [];
1778
                var aApplied = [];
1779
                var iColumns = oSettings.aoColumns.length;
1780
                var iRowspan, iColspan;
1781
 
1782
                if ( ! aoSource )
1783
                {
1784
                        return;
1785
                }
1786
 
1787
                if (  bIncludeHidden === undefined )
1788
                {
1789
                        bIncludeHidden = false;
1790
                }
1791
 
1792
                /* Make a copy of the master layout array, but without the visible columns in it */
1793
                for ( i=0, iLen=aoSource.length ; i<iLen ; i++ )
1794
                {
1795
                        aoLocal[i] = aoSource[i].slice();
1796
                        aoLocal[i].nTr = aoSource[i].nTr;
1797
 
1798
                        /* Remove any columns which are currently hidden */
1799
                        for ( j=iColumns-1 ; j>=0 ; j-- )
1800
                        {
1801
                                if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden )
1802
                                {
1803
                                        aoLocal[i].splice( j, 1 );
1804
                                }
1805
                        }
1806
 
1807
                        /* Prep the applied array - it needs an element for each row */
1808
                        aApplied.push( [] );
1809
                }
1810
 
1811
                for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ )
1812
                {
1813
                        nLocalTr = aoLocal[i].nTr;
1814
 
1815
                        /* All cells are going to be replaced, so empty out the row */
1816
                        if ( nLocalTr )
1817
                        {
1818
                                while( (n = nLocalTr.firstChild) )
1819
                                {
1820
                                        nLocalTr.removeChild( n );
1821
                                }
1822
                        }
1823
 
1824
                        for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ )
1825
                        {
1826
                                iRowspan = 1;
1827
                                iColspan = 1;
1828
 
1829
                                /* Check to see if there is already a cell (row/colspan) covering our target
1830
                                 * insert point. If there is, then there is nothing to do.
1831
                                 */
1832
                                if ( aApplied[i][j] === undefined )
1833
                                {
1834
                                        nLocalTr.appendChild( aoLocal[i][j].cell );
1835
                                        aApplied[i][j] = 1;
1836
 
1837
                                        /* Expand the cell to cover as many rows as needed */
1838
                                        while ( aoLocal[i+iRowspan] !== undefined &&
1839
                                                aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell )
1840
                                        {
1841
                                                aApplied[i+iRowspan][j] = 1;
1842
                                                iRowspan++;
1843
                                        }
1844
 
1845
                                        /* Expand the cell to cover as many columns as needed */
1846
                                        while ( aoLocal[i][j+iColspan] !== undefined &&
1847
                                                aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell )
1848
                                        {
1849
                                                /* Must update the applied array over the rows for the columns */
1850
                                                for ( k=0 ; k<iRowspan ; k++ )
1851
                                                {
1852
                                                        aApplied[i+k][j+iColspan] = 1;
1853
                                                }
1854
                                                iColspan++;
1855
                                        }
1856
 
1857
                                        /* Do the actual expansion in the DOM */
1858
                                        $(aoLocal[i][j].cell)
1859
                                                .attr('rowspan', iRowspan)
1860
                                                .attr('colspan', iColspan);
1861
                                }
1862
                        }
1863
                }
1864
        }
1865
 
1866
 
1867
        /**
1868
         * Insert the required TR nodes into the table for display
1869
         *  @param {object} oSettings dataTables settings object
1870
         *  @memberof DataTable#oApi
1871
         */
1872
        function _fnDraw( oSettings )
1873
        {
1874
                /* Provide a pre-callback function which can be used to cancel the draw is false is returned */
1875
                var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] );
1876
                if ( $.inArray( false, aPreDraw ) !== -1 )
1877
                {
1878
                        _fnProcessingDisplay( oSettings, false );
1879
                        return;
1880
                }
1881
 
1882
                var i, iLen, n;
1883
                var anRows = [];
1884
                var iRowCount = 0;
1885
                var asStripeClasses = oSettings.asStripeClasses;
1886
                var iStripes = asStripeClasses.length;
1887
                var iOpenRows = oSettings.aoOpenRows.length;
1888
                var oLang = oSettings.oLanguage;
1889
                var iInitDisplayStart = oSettings.iInitDisplayStart;
1890
                var bServerSide = _fnDataSource( oSettings ) == 'ssp';
1891
                var aiDisplay = oSettings.aiDisplay;
1892
 
1893
                oSettings.bDrawing = true;
1894
 
1895
                /* Check and see if we have an initial draw position from state saving */
1896
                if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 )
1897
                {
1898
                        oSettings._iDisplayStart = bServerSide ?
1899
                                iInitDisplayStart :
1900
                                iInitDisplayStart >= oSettings.fnRecordsDisplay() ?
1901
 
1902
                                        iInitDisplayStart;
1903
 
1904
                        oSettings.iInitDisplayStart = -1;
1905
                }
1906
 
1907
                var iDisplayStart = oSettings._iDisplayStart;
1908
                var iDisplayEnd = oSettings.fnDisplayEnd();
1909
 
1910
                /* Server-side processing draw intercept */
1911
                if ( oSettings.bDeferLoading )
1912
                {
1913
                        oSettings.bDeferLoading = false;
1914
                        oSettings.iDraw++;
1915
                        _fnProcessingDisplay( oSettings, false );
1916
                }
1917
                else if ( !bServerSide )
1918
                {
1919
                        oSettings.iDraw++;
1920
                }
1921
                else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) )
1922
                {
1923
                        return;
1924
                }
1925
 
1926
                if ( aiDisplay.length !== 0 )
1927
                {
1928
                        var iStart = bServerSide ? 0 : iDisplayStart;
1929
                        var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd;
1930
 
1931
                        for ( var j=iStart ; j<iEnd ; j++ )
1932
                        {
1933
                                var iDataIndex = aiDisplay[j];
1934
                                var aoData = oSettings.aoData[ iDataIndex ];
1935
                                if ( aoData.nTr === null )
1936
                                {
1937
                                        _fnCreateTr( oSettings, iDataIndex );
1938
                                }
1939
 
1940
                                var nRow = aoData.nTr;
1941
 
1942
                                /* Remove the old striping classes and then add the new one */
1943
                                if ( iStripes !== 0 )
1944
                                {
1945
                                        var sStripe = asStripeClasses[ iRowCount % iStripes ];
1946
                                        if ( aoData._sRowStripe != sStripe )
1947
                                        {
1948
                                                $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe );
1949
                                                aoData._sRowStripe = sStripe;
1950
                                        }
1951
                                }
1952
 
1953
                                /* Row callback functions - might want to manipulate the row */
1954
                                _fnCallbackFire( oSettings, 'aoRowCallback', null,
1955
                                        [nRow, aoData._aData, iRowCount, j] );
1956
 
1957
                                anRows.push( nRow );
1958
                                iRowCount++;
1959
                        }
1960
                }
1961
                else
1962
                {
1963
                        /* Table is empty - create a row with an empty message in it */
1964
                        var sZero = oLang.sZeroRecords;
1965
                        if ( oSettings.iDraw == 1 &&  _fnDataSource( oSettings ) == 'ajax' )
1966
                        {
1967
                                sZero = oLang.sLoadingRecords;
1968
                        }
1969
                        else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 )
1970
                        {
1971
                                sZero = oLang.sEmptyTable;
1972
                        }
1973
 
1974
                        anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } )
1975
                                .append( $('<td />', {
1976
                                        'valign':  'top',
1977
                                        'colSpan': _fnVisbleColumns( oSettings ),
1978
                                        'class':   oSettings.oClasses.sRowEmpty
1979
                                } ).html( sZero ) )[0];
1980
                }
1981
 
1982
                /* Header and footer callbacks */
1983
                _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0],
1984
                        _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
1985
 
1986
                _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0],
1987
                        _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] );
1988
 
1989
                var body = $(oSettings.nTBody);
1990
 
1991
                body.children().detach();
1992
                body.append( $(anRows) );
1993
 
1994
                /* Call all required callback functions for the end of a draw */
1995
                _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] );
1996
 
1997
                /* Draw is complete, sorting and filtering must be as well */
1998
                oSettings.bSorted = false;
1999
                oSettings.bFiltered = false;
2000
                oSettings.bDrawing = false;
2001
        }
2002
 
2003
 
2004
        /**
2005
         * Redraw the table - taking account of the various features which are enabled
2006
         *  @param {object} oSettings dataTables settings object
2007
         *  @param {boolean} [holdPosition] Keep the current paging position. By default
2008
         *    the paging is reset to the first page
2009
         *  @memberof DataTable#oApi
2010
         */
2011
        function _fnReDraw( settings, holdPosition )
2012
        {
2013
                var
2014
                        features = settings.oFeatures,
2015
                        sort     = features.bSort,
2016
                        filter   = features.bFilter;
2017
 
2018
                if ( sort ) {
2019
                        _fnSort( settings );
2020
                }
2021
 
2022
                if ( filter ) {
2023
                        _fnFilterComplete( settings, settings.oPreviousSearch );
2024
                }
2025
                else {
2026
                        // No filtering, so we want to just use the display master
2027
                        settings.aiDisplay = settings.aiDisplayMaster.slice();
2028
                }
2029
 
2030
                if ( holdPosition !== true ) {
2031
                        settings._iDisplayStart = 0;
2032
                }
2033
 
2034
                // Let any modules know about the draw hold position state (used by
2035
                // scrolling internally)
2036
                settings._drawHold = holdPosition;
2037
 
2038
                _fnDraw( settings );
2039
 
2040
                settings._drawHold = false;
2041
        }
2042
 
2043
 
2044
        /**
2045
         * Add the options to the page HTML for the table
2046
         *  @param {object} oSettings dataTables settings object
2047
         *  @memberof DataTable#oApi
2048
         */
2049
        function _fnAddOptionsHtml ( oSettings )
2050
        {
2051
                var classes = oSettings.oClasses;
2052
                var table = $(oSettings.nTable);
2053
                var holding = $('<div/>').insertBefore( table ); // Holding element for speed
2054
                var features = oSettings.oFeatures;
2055
 
2056
                // All DataTables are wrapped in a div
2057
                var insert = $('<div/>', {
2058
                        id:      oSettings.sTableId+'_wrapper',
2059
                        'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter)
2060
                } );
2061
 
2062
                oSettings.nHolding = holding[0];
2063
                oSettings.nTableWrapper = insert[0];
2064
                oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling;
2065
 
2066
                /* Loop over the user set positioning and place the elements as needed */
2067
                var aDom = oSettings.sDom.split('');
2068
                var featureNode, cOption, nNewNode, cNext, sAttr, j;
2069
                for ( var i=0 ; i<aDom.length ; i++ )
2070
                {
2071
                        featureNode = null;
2072
                        cOption = aDom[i];
2073
 
2074
                        if ( cOption == '<' )
2075
                        {
2076
                                /* New container div */
2077
                                nNewNode = $('<div/>')[0];
2078
 
2079
                                /* Check to see if we should append an id and/or a class name to the container */
2080
                                cNext = aDom[i+1];
2081
                                if ( cNext == "'" || cNext == '"' )
2082
                                {
2083
                                        sAttr = "";
2084
                                        j = 2;
2085
                                        while ( aDom[i+j] != cNext )
2086
                                        {
2087
                                                sAttr += aDom[i+j];
2088
                                                j++;
2089
                                        }
2090
 
2091
                                        /* Replace jQuery UI constants @todo depreciated */
2092
                                        if ( sAttr == "H" )
2093
                                        {
2094
                                                sAttr = classes.sJUIHeader;
2095
                                        }
2096
                                        else if ( sAttr == "F" )
2097
                                        {
2098
                                                sAttr = classes.sJUIFooter;
2099
                                        }
2100
 
2101
                                        /* The attribute can be in the format of "#id.class", "#id" or "class" This logic
2102
                                         * breaks the string into parts and applies them as needed
2103
                                         */
2104
                                        if ( sAttr.indexOf('.') != -1 )
2105
                                        {
2106
                                                var aSplit = sAttr.split('.');
2107
                                                nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1);
2108
                                                nNewNode.className = aSplit[1];
2109
                                        }
2110
                                        else if ( sAttr.charAt(0) == "#" )
2111
                                        {
2112
                                                nNewNode.id = sAttr.substr(1, sAttr.length-1);
2113
                                        }
2114
                                        else
2115
                                        {
2116
                                                nNewNode.className = sAttr;
2117
                                        }
2118
 
2119
                                        i += j; /* Move along the position array */
2120
                                }
2121
 
2122
                                insert.append( nNewNode );
2123
                                insert = $(nNewNode);
2124
                        }
2125
                        else if ( cOption == '>' )
2126
                        {
2127
                                /* End container div */
2128
                                insert = insert.parent();
2129
                        }
2130
                        // @todo Move options into their own plugins?
2131
                        else if ( cOption == 'l' && features.bPaginate && features.bLengthChange )
2132
                        {
2133
                                /* Length */
2134
                                featureNode = _fnFeatureHtmlLength( oSettings );
2135
                        }
2136
                        else if ( cOption == 'f' && features.bFilter )
2137
                        {
2138
                                /* Filter */
2139
                                featureNode = _fnFeatureHtmlFilter( oSettings );
2140
                        }
2141
                        else if ( cOption == 'r' && features.bProcessing )
2142
                        {
2143
                                /* pRocessing */
2144
                                featureNode = _fnFeatureHtmlProcessing( oSettings );
2145
                        }
2146
                        else if ( cOption == 't' )
2147
                        {
2148
                                /* Table */
2149
                                featureNode = _fnFeatureHtmlTable( oSettings );
2150
                        }
2151
                        else if ( cOption ==  'i' && features.bInfo )
2152
                        {
2153
                                /* Info */
2154
                                featureNode = _fnFeatureHtmlInfo( oSettings );
2155
                        }
2156
                        else if ( cOption == 'p' && features.bPaginate )
2157
                        {
2158
                                /* Pagination */
2159
                                featureNode = _fnFeatureHtmlPaginate( oSettings );
2160
                        }
2161
                        else if ( DataTable.ext.feature.length !== 0 )
2162
                        {
2163
                                /* Plug-in features */
2164
                                var aoFeatures = DataTable.ext.feature;
2165
                                for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ )
2166
                                {
2167
                                        if ( cOption == aoFeatures[k].cFeature )
2168
                                        {
2169
                                                featureNode = aoFeatures[k].fnInit( oSettings );
2170
                                                break;
2171
                                        }
2172
                                }
2173
                        }
2174
 
2175
                        /* Add to the 2D features array */
2176
                        if ( featureNode )
2177
                        {
2178
                                var aanFeatures = oSettings.aanFeatures;
2179
 
2180
                                if ( ! aanFeatures[cOption] )
2181
                                {
2182
                                        aanFeatures[cOption] = [];
2183
                                }
2184
 
2185
                                aanFeatures[cOption].push( featureNode );
2186
                                insert.append( featureNode );
2187
                        }
2188
                }
2189
 
2190
                /* Built our DOM structure - replace the holding div with what we want */
2191
                holding.replaceWith( insert );
2192
        }
2193
 
2194
 
2195
        /**
2196
         * Use the DOM source to create up an array of header cells. The idea here is to
2197
         * create a layout grid (array) of rows x columns, which contains a reference
2198
         * to the cell that that point in the grid (regardless of col/rowspan), such that
2199
         * any column / row could be removed and the new grid constructed
2200
         *  @param array {object} aLayout Array to store the calculated layout in
2201
         *  @param {node} nThead The header/footer element for the table
2202
         *  @memberof DataTable#oApi
2203
         */
2204
        function _fnDetectHeader ( aLayout, nThead )
2205
        {
2206
                var nTrs = $(nThead).children('tr');
2207
                var nTr, nCell;
2208
                var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan;
2209
                var bUnique;
2210
                var fnShiftCol = function ( a, i, j ) {
2211
                        var k = a[i];
2212
                        while ( k[j] ) {
2213
                                j++;
2214
                        }
2215
                        return j;
2216
                };
2217
 
2218
                aLayout.splice( 0, aLayout.length );
2219
 
2220
                /* We know how many rows there are in the layout - so prep it */
2221
                for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
2222
                {
2223
                        aLayout.push( [] );
2224
                }
2225
 
2226
                /* Calculate a layout array */
2227
                for ( i=0, iLen=nTrs.length ; i<iLen ; i++ )
2228
                {
2229
                        nTr = nTrs[i];
2230
                        iColumn = 0;
2231
 
2232
                        /* For every cell in the row... */
2233
                        nCell = nTr.firstChild;
2234
                        while ( nCell ) {
2235
                                if ( nCell.nodeName.toUpperCase() == "TD" ||
2236
                                     nCell.nodeName.toUpperCase() == "TH" )
2237
                                {
2238
                                        /* Get the col and rowspan attributes from the DOM and sanitise them */
2239
                                        iColspan = nCell.getAttribute('colspan') * 1;
2240
                                        iRowspan = nCell.getAttribute('rowspan') * 1;
2241
                                        iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan;
2242
                                        iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan;
2243
 
2244
                                        /* There might be colspan cells already in this row, so shift our target
2245
                                         * accordingly
2246
                                         */
2247
                                        iColShifted = fnShiftCol( aLayout, i, iColumn );
2248
 
2249
                                        /* Cache calculation for unique columns */
2250
                                        bUnique = iColspan === 1 ? true : false;
2251
 
2252
                                        /* If there is col / rowspan, copy the information into the layout grid */
2253
                                        for ( l=0 ; l<iColspan ; l++ )
2254
                                        {
2255
                                                for ( k=0 ; k<iRowspan ; k++ )
2256
                                                {
2257
                                                        aLayout[i+k][iColShifted+l] = {
2258
                                                                "cell": nCell,
2259
                                                                "unique": bUnique
2260
                                                        };
2261
                                                        aLayout[i+k].nTr = nTr;
2262
                                                }
2263
                                        }
2264
                                }
2265
                                nCell = nCell.nextSibling;
2266
                        }
2267
                }
2268
        }
2269
 
2270
 
2271
        /**
2272
         * Get an array of unique th elements, one for each column
2273
         *  @param {object} oSettings dataTables settings object
2274
         *  @param {node} nHeader automatically detect the layout from this node - optional
2275
         *  @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional
2276
         *  @returns array {node} aReturn list of unique th's
2277
         *  @memberof DataTable#oApi
2278
         */
2279
        function _fnGetUniqueThs ( oSettings, nHeader, aLayout )
2280
        {
2281
                var aReturn = [];
2282
                if ( !aLayout )
2283
                {
2284
                        aLayout = oSettings.aoHeader;
2285
                        if ( nHeader )
2286
                        {
2287
                                aLayout = [];
2288
                                _fnDetectHeader( aLayout, nHeader );
2289
                        }
2290
                }
2291
 
2292
                for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ )
2293
                {
2294
                        for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ )
2295
                        {
2296
                                if ( aLayout[i][j].unique &&
2297
                                         (!aReturn[j] || !oSettings.bSortCellsTop) )
2298
                                {
2299
                                        aReturn[j] = aLayout[i][j].cell;
2300
                                }
2301
                        }
2302
                }
2303
 
2304
                return aReturn;
2305
        }
2306
 
2307
 
2308
 
2309
        /**
2310
         * Create an Ajax call based on the table's settings, taking into account that
2311
         * parameters can have multiple forms, and backwards compatibility.
2312
         *
2313
         * @param {object} oSettings dataTables settings object
2314
         * @param {array} data Data to send to the server, required by
2315
         *     DataTables - may be augmented by developer callbacks
2316
         * @param {function} fn Callback function to run when data is obtained
2317
         */
2318
        function _fnBuildAjax( oSettings, data, fn )
2319
        {
2320
                // Compatibility with 1.9-, allow fnServerData and event to manipulate
2321
                _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] );
2322
 
2323
                // Convert to object based for 1.10+ if using the old array scheme which can
2324
                // come from server-side processing or serverParams
2325
                if ( data && $.isArray(data) ) {
2326
                        var tmp = {};
2327
                        var rbracket = /(.*?)\[\]$/;
2328
 
2329
                        $.each( data, function (key, val) {
2330
                                var match = val.name.match(rbracket);
2331
 
2332
                                if ( match ) {
2333
                                        // Support for arrays
2334
                                        var name = match[0];
2335
 
2336
                                        if ( ! tmp[ name ] ) {
2337
                                                tmp[ name ] = [];
2338
                                        }
2339
                                        tmp[ name ].push( val.value );
2340
                                }
2341
                                else {
2342
                                        tmp[val.name] = val.value;
2343
                                }
2344
                        } );
2345
                        data = tmp;
2346
                }
2347
 
2348
                var ajaxData;
2349
                var ajax = oSettings.ajax;
2350
                var instance = oSettings.oInstance;
2351
 
2352
                if ( $.isPlainObject( ajax ) && ajax.data )
2353
                {
2354
                        ajaxData = ajax.data;
2355
 
2356
                        var newData = $.isFunction( ajaxData ) ?
2357
                                ajaxData( data ) :  // fn can manipulate data or return an object
2358
                                ajaxData;           // object or array to merge
2359
 
2360
                        // If the function returned an object, use that alone
2361
                        data = $.isFunction( ajaxData ) && newData ?
2362
                                newData :
2363
                                $.extend( true, data, newData );
2364
 
2365
                        // Remove the data property as we've resolved it already and don't want
2366
                        // jQuery to do it again (it is restored at the end of the function)
2367
                        delete ajax.data;
2368
                }
2369
 
2370
                var baseAjax = {
2371
                        "data": data,
2372
                        "success": function (json) {
2373
                                var error = json.error || json.sError;
2374
                                if ( error ) {
2375
                                        oSettings.oApi._fnLog( oSettings, 0, error );
2376
                                }
2377
 
2378
                                oSettings.json = json;
2379
                                _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json] );
2380
                                fn( json );
2381
                        },
2382
                        "dataType": "json",
2383
                        "cache": false,
2384
                        "type": oSettings.sServerMethod,
2385
                        "error": function (xhr, error, thrown) {
2386
                                var log = oSettings.oApi._fnLog;
2387
 
2388
                                if ( error == "parsererror" ) {
2389
                                        log( oSettings, 0, 'Invalid JSON response', 1 );
2390
                                }
2391
                                else if ( xhr.readyState === 4 ) {
2392
                                        log( oSettings, 0, 'Ajax error', 7 );
2393
                                }
2394
 
2395
                                _fnProcessingDisplay( oSettings, false );
2396
                        }
2397
                };
2398
 
2399
                // Store the data submitted for the API
2400
                oSettings.oAjaxData = data;
2401
 
2402
                // Allow plug-ins and external processes to modify the data
2403
                _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] );
2404
 
2405
                if ( oSettings.fnServerData )
2406
                {
2407
                        // DataTables 1.9- compatibility
2408
                        oSettings.fnServerData.call( instance,
2409
                                oSettings.sAjaxSource,
2410
                                $.map( data, function (val, key) { // Need to convert back to 1.9 trad format
2411
                                        return { name: key, value: val };
2412
                                } ),
2413
                                fn,
2414
                                oSettings
2415
                        );
2416
                }
2417
                else if ( oSettings.sAjaxSource || typeof ajax === 'string' )
2418
                {
2419
                        // DataTables 1.9- compatibility
2420
                        oSettings.jqXHR = $.ajax( $.extend( baseAjax, {
2421
                                url: ajax || oSettings.sAjaxSource
2422
                        } ) );
2423
                }
2424
                else if ( $.isFunction( ajax ) )
2425
                {
2426
                        // Is a function - let the caller define what needs to be done
2427
                        oSettings.jqXHR = ajax.call( instance, data, fn, oSettings );
2428
                }
2429
                else
2430
                {
2431
                        // Object to extend the base settings
2432
                        oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) );
2433
 
2434
                        // Restore for next time around
2435
                        ajax.data = ajaxData;
2436
                }
2437
        }
2438
 
2439
 
2440
        /**
2441
         * Update the table using an Ajax call
2442
         *  @param {object} settings dataTables settings object
2443
         *  @returns {boolean} Block the table drawing or not
2444
         *  @memberof DataTable#oApi
2445
         */
2446
        function _fnAjaxUpdate( settings )
2447
        {
2448
                if ( settings.bAjaxDataGet ) {
2449
                        settings.iDraw++;
2450
                        _fnProcessingDisplay( settings, true );
2451
 
2452
                        _fnBuildAjax(
2453
                                settings,
2454
                                _fnAjaxParameters( settings ),
2455
                                function(json) {
2456
                                        _fnAjaxUpdateDraw( settings, json );
2457
                                }
2458
                        );
2459
 
2460
                        return false;
2461
                }
2462
                return true;
2463
        }
2464
 
2465
 
2466
        /**
2467
         * Build up the parameters in an object needed for a server-side processing
2468
         * request. Note that this is basically done twice, is different ways - a modern
2469
         * method which is used by default in DataTables 1.10 which uses objects and
2470
         * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if
2471
         * the sAjaxSource option is used in the initialisation, or the legacyAjax
2472
         * option is set.
2473
         *  @param {object} oSettings dataTables settings object
2474
         *  @returns {bool} block the table drawing or not
2475
         *  @memberof DataTable#oApi
2476
         */
2477
        function _fnAjaxParameters( settings )
2478
        {
2479
                var
2480
                        columns = settings.aoColumns,
2481
                        columnCount = columns.length,
2482
                        features = settings.oFeatures,
2483
                        preSearch = settings.oPreviousSearch,
2484
                        preColSearch = settings.aoPreSearchCols,
2485
                        i, data = [], dataProp, column, columnSearch,
2486
                        sort = _fnSortFlatten( settings ),
2487
                        displayStart = settings._iDisplayStart,
2488
                        displayLength = features.bPaginate !== false ?
2489
                                settings._iDisplayLength :
2490
                                -1;
2491
 
2492
                var param = function ( name, value ) {
2493
                        data.push( { 'name': name, 'value': value } );
2494
                };
2495
 
2496
                // DataTables 1.9- compatible method
2497
                param( 'sEcho',          settings.iDraw );
2498
                param( 'iColumns',       columnCount );
2499
                param( 'sColumns',       _pluck( columns, 'sName' ).join(',') );
2500
                param( 'iDisplayStart',  displayStart );
2501
                param( 'iDisplayLength', displayLength );
2502
 
2503
                // DataTables 1.10+ method
2504
                var d = {
2505
                        draw:    settings.iDraw,
2506
                        columns: [],
2507
                        order:   [],
2508
                        start:   displayStart,
2509
                        length:  displayLength,
2510
                        search:  {
2511
                                value: preSearch.sSearch,
2512
                                regex: preSearch.bRegex
2513
                        }
2514
                };
2515
 
2516
                for ( i=0 ; i<columnCount ; i++ ) {
2517
                        column = columns[i];
2518
                        columnSearch = preColSearch[i];
2519
                        dataProp = typeof column.mData=="function" ? 'function' : column.mData ;
2520
 
2521
                        d.columns.push( {
2522
                                data:       dataProp,
2523
                                name:       column.sName,
2524
                                searchable: column.bSearchable,
2525
                                orderable:  column.bSortable,
2526
                                search:     {
2527
                                        value: columnSearch.sSearch,
2528
                                        regex: columnSearch.bRegex
2529
                                }
2530
                        } );
2531
 
2532
                        param( "mDataProp_"+i, dataProp );
2533
 
2534
                        if ( features.bFilter ) {
2535
                                param( 'sSearch_'+i,     columnSearch.sSearch );
2536
                                param( 'bRegex_'+i,      columnSearch.bRegex );
2537
                                param( 'bSearchable_'+i, column.bSearchable );
2538
                        }
2539
 
2540
                        if ( features.bSort ) {
2541
                                param( 'bSortable_'+i, column.bSortable );
2542
                        }
2543
                }
2544
 
2545
                if ( features.bFilter ) {
2546
                        param( 'sSearch', preSearch.sSearch );
2547
                        param( 'bRegex', preSearch.bRegex );
2548
                }
2549
 
2550
                if ( features.bSort ) {
2551
                        $.each( sort, function ( i, val ) {
2552
                                d.order.push( { column: val.col, dir: val.dir } );
2553
 
2554
                                param( 'iSortCol_'+i, val.col );
2555
                                param( 'sSortDir_'+i, val.dir );
2556
                        } );
2557
 
2558
                        param( 'iSortingCols', sort.length );
2559
                }
2560
 
2561
                // If the legacy.ajax parameter is null, then we automatically decide which
2562
                // form to use, based on sAjaxSource
2563
                var legacy = DataTable.ext.legacy.ajax;
2564
                if ( legacy === null ) {
2565
                        return settings.sAjaxSource ? data : d;
2566
                }
2567
 
2568
                // Otherwise, if legacy has been specified then we use that to decide on the
2569
                // form
2570
                return legacy ? data : d;
2571
        }
2572
 
2573
 
2574
        /**
2575
         * Data the data from the server (nuking the old) and redraw the table
2576
         *  @param {object} oSettings dataTables settings object
2577
         *  @param {object} json json data return from the server.
2578
         *  @param {string} json.sEcho Tracking flag for DataTables to match requests
2579
         *  @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering
2580
         *  @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering
2581
         *  @param {array} json.aaData The data to display on this page
2582
         *  @param {string} [json.sColumns] Column ordering (sName, comma separated)
2583
         *  @memberof DataTable#oApi
2584
         */
2585
        function _fnAjaxUpdateDraw ( settings, json )
2586
        {
2587
                // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation.
2588
                // Support both
2589
                var compat = function ( old, modern ) {
2590
                        return json[old] !== undefined ? json[old] : json[modern];
2591
                };
2592
 
2593
                var draw            = compat( 'sEcho',                'draw' );
2594
                var recordsTotal    = compat( 'iTotalRecords',        'recordsTotal' );
2595
                var rocordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' );
2596
 
2597
                if ( draw ) {
2598
                        // Protect against out of sequence returns
2599
                        if ( draw*1 < settings.iDraw ) {
2600
                                return;
2601
                        }
2602
                        settings.iDraw = draw * 1;
2603
                }
2604
 
2605
                _fnClearTable( settings );
2606
                settings._iRecordsTotal   = parseInt(recordsTotal, 10);
2607
                settings._iRecordsDisplay = parseInt(rocordsFiltered, 10);
2608
 
2609
                var data = _fnAjaxDataSrc( settings, json );
2610
                for ( var i=0, ien=data.length ; i<ien ; i++ ) {
2611
                        _fnAddData( settings, data[i] );
2612
                }
2613
                settings.aiDisplay = settings.aiDisplayMaster.slice();
2614
 
2615
                settings.bAjaxDataGet = false;
2616
                _fnDraw( settings );
2617
 
2618
                if ( ! settings._bInitComplete ) {
2619
                        _fnInitComplete( settings, json );
2620
                }
2621
 
2622
                settings.bAjaxDataGet = true;
2623
                _fnProcessingDisplay( settings, false );
2624
        }
2625
 
2626
 
2627
        /**
2628
         * Get the data from the JSON data source to use for drawing a table. Using
2629
         * `_fnGetObjectDataFn` allows the data to be sourced from a property of the
2630
         * source object, or from a processing function.
2631
         *  @param {object} oSettings dataTables settings object
2632
         *  @param  {object} json Data source object / array from the server
2633
         *  @return {array} Array of data to use
2634
         */
2635
        function _fnAjaxDataSrc ( oSettings, json )
2636
        {
2637
                var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ?
2638
                        oSettings.ajax.dataSrc :
2639
                        oSettings.sAjaxDataProp; // Compatibility with 1.9-.
2640
 
2641
                // Compatibility with 1.9-. In order to read from aaData, check if the
2642
                // default has been changed, if not, check for aaData
2643
                if ( dataSrc === 'data' ) {
2644
                        return json.aaData || json[dataSrc];
2645
                }
2646
 
2647
                return dataSrc !== "" ?
2648
                        _fnGetObjectDataFn( dataSrc )( json ) :
2649
                        json;
2650
        }
2651
 
2652
 
2653
        /**
2654
         * Generate the node required for filtering text
2655
         *  @returns {node} Filter control element
2656
         *  @param {object} oSettings dataTables settings object
2657
         *  @memberof DataTable#oApi
2658
         */
2659
        function _fnFeatureHtmlFilter ( settings )
2660
        {
2661
                var classes = settings.oClasses;
2662
                var tableId = settings.sTableId;
2663
                var language = settings.oLanguage;
2664
                var previousSearch = settings.oPreviousSearch;
2665
                var features = settings.aanFeatures;
2666
                var input = '<input type="search" class="'+classes.sFilterInput+'"/>';
2667
 
2668
                var str = language.sSearch;
2669
                str = str.match(/_INPUT_/) ?
2670
                        str.replace('_INPUT_', input) :
2671
                        str+input;
2672
 
2673
                var filter = $('<div/>', {
2674
                                'id': ! features.f ? tableId+'_filter' : null,
2675
                                'class': classes.sFilter
2676
                        } )
2677
                        .append( $('<label/>' ).append( str ) );
2678
 
2679
                var searchFn = function() {
2680
                        /* Update all other filter input elements for the new display */
2681
                        var n = features.f;
2682
                        var val = !this.value ? "" : this.value; // mental IE8 fix :-(
2683
 
2684
                        /* Now do the filter */
2685
                        if ( val != previousSearch.sSearch ) {
2686
                                _fnFilterComplete( settings, {
2687
                                        "sSearch": val,
2688
                                        "bRegex": previousSearch.bRegex,
2689
                                        "bSmart": previousSearch.bSmart ,
2690
                                        "bCaseInsensitive": previousSearch.bCaseInsensitive
2691
                                } );
2692
 
2693
                                // Need to redraw, without resorting
2694
                                settings._iDisplayStart = 0;
2695
                                _fnDraw( settings );
2696
                        }
2697
                };
2698
                var jqFilter = $('input', filter)
2699
                        .val( previousSearch.sSearch )
2700
                        .attr( 'placeholder', language.sSearchPlaceholder )
2701
                        .bind(
2702
                                'keyup.DT search.DT input.DT paste.DT cut.DT',
2703
                                _fnDataSource( settings ) === 'ssp' ?
2704
                                        _fnThrottle( searchFn, 400 ):
2705
                                        searchFn
2706
                        )
2707
                        .bind( 'keypress.DT', function(e) {
2708
                                /* Prevent form submission */
2709
                                if ( e.keyCode == 13 ) {
2710
                                        return false;
2711
                                }
2712
                        } )
2713
                        .attr('aria-controls', tableId);
2714
 
2715
                // Update the input elements whenever the table is filtered
2716
                $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) {
2717
                        if ( settings === s ) {
2718
                                // IE9 throws an 'unknown error' if document.activeElement is used
2719
                                // inside an iframe or frame...
2720
                                try {
2721
                                        if ( jqFilter[0] !== document.activeElement ) {
2722
                                                jqFilter.val( previousSearch.sSearch );
2723
                                        }
2724
                                }
2725
                                catch ( e ) {}
2726
                        }
2727
                } );
2728
 
2729
                return filter[0];
2730
        }
2731
 
2732
 
2733
        /**
2734
         * Filter the table using both the global filter and column based filtering
2735
         *  @param {object} oSettings dataTables settings object
2736
         *  @param {object} oSearch search information
2737
         *  @param {int} [iForce] force a research of the master array (1) or not (undefined or 0)
2738
         *  @memberof DataTable#oApi
2739
         */
2740
        function _fnFilterComplete ( oSettings, oInput, iForce )
2741
        {
2742
                var oPrevSearch = oSettings.oPreviousSearch;
2743
                var aoPrevSearch = oSettings.aoPreSearchCols;
2744
                var fnSaveFilter = function ( oFilter ) {
2745
                        /* Save the filtering values */
2746
                        oPrevSearch.sSearch = oFilter.sSearch;
2747
                        oPrevSearch.bRegex = oFilter.bRegex;
2748
                        oPrevSearch.bSmart = oFilter.bSmart;
2749
                        oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive;
2750
                };
2751
                var fnRegex = function ( o ) {
2752
                        // Backwards compatibility with the bEscapeRegex option
2753
                        return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex;
2754
                };
2755
 
2756
                // Resolve any column types that are unknown due to addition or invalidation
2757
                // @todo As per sort - can this be moved into an event handler?
2758
                _fnColumnTypes( oSettings );
2759
 
2760
                /* In server-side processing all filtering is done by the server, so no point hanging around here */
2761
                if ( _fnDataSource( oSettings ) != 'ssp' )
2762
                {
2763
                        /* Global filter */
2764
                        _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive );
2765
                        fnSaveFilter( oInput );
2766
 
2767
                        /* Now do the individual column filter */
2768
                        for ( var i=0 ; i<aoPrevSearch.length ; i++ )
2769
                        {
2770
                                _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]),
2771
                                        aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive );
2772
                        }
2773
 
2774
                        /* Custom filtering */
2775
                        _fnFilterCustom( oSettings );
2776
                }
2777
                else
2778
                {
2779
                        fnSaveFilter( oInput );
2780
                }
2781
 
2782
                /* Tell the draw function we have been filtering */
2783
                oSettings.bFiltered = true;
2784
                _fnCallbackFire( oSettings, null, 'search', [oSettings] );
2785
        }
2786
 
2787
 
2788
        /**
2789
         * Apply custom filtering functions
2790
         *  @param {object} oSettings dataTables settings object
2791
         *  @memberof DataTable#oApi
2792
         */
2793
        function _fnFilterCustom( settings )
2794
        {
2795
                var filters = DataTable.ext.search;
2796
                var displayRows = settings.aiDisplay;
2797
                var row, rowIdx;
2798
 
2799
                for ( var i=0, ien=filters.length ; i<ien ; i++ ) {
2800
                        var rows = [];
2801
 
2802
                        // Loop over each row and see if it should be included
2803
                        for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) {
2804
                                rowIdx = displayRows[ j ];
2805
                                row = settings.aoData[ rowIdx ];
2806
 
2807
                                if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) {
2808
                                        rows.push( rowIdx );
2809
                                }
2810
                        }
2811
 
2812
                        // So the array reference doesn't break set the results into the
2813
                        // existing array
2814
                        displayRows.length = 0;
2815
                        displayRows.push.apply( displayRows, rows );
2816
                }
2817
        }
2818
 
2819
 
2820
        /**
2821
         * Filter the table on a per-column basis
2822
         *  @param {object} oSettings dataTables settings object
2823
         *  @param {string} sInput string to filter on
2824
         *  @param {int} iColumn column to filter
2825
         *  @param {bool} bRegex treat search string as a regular expression or not
2826
         *  @param {bool} bSmart use smart filtering or not
2827
         *  @param {bool} bCaseInsensitive Do case insenstive matching or not
2828
         *  @memberof DataTable#oApi
2829
         */
2830
        function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive )
2831
        {
2832
                if ( searchStr === '' ) {
2833
                        return;
2834
                }
2835
 
2836
                var data;
2837
                var display = settings.aiDisplay;
2838
                var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive );
2839
 
2840
                for ( var i=display.length-1 ; i>=0 ; i-- ) {
2841
                        data = settings.aoData[ display[i] ]._aFilterData[ colIdx ];
2842
 
2843
                        if ( ! rpSearch.test( data ) ) {
2844
                                display.splice( i, 1 );
2845
                        }
2846
                }
2847
        }
2848
 
2849
 
2850
        /**
2851
         * Filter the data table based on user input and draw the table
2852
         *  @param {object} settings dataTables settings object
2853
         *  @param {string} input string to filter on
2854
         *  @param {int} force optional - force a research of the master array (1) or not (undefined or 0)
2855
         *  @param {bool} regex treat as a regular expression or not
2856
         *  @param {bool} smart perform smart filtering or not
2857
         *  @param {bool} caseInsensitive Do case insenstive matching or not
2858
         *  @memberof DataTable#oApi
2859
         */
2860
        function _fnFilter( settings, input, force, regex, smart, caseInsensitive )
2861
        {
2862
                var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive );
2863
                var prevSearch = settings.oPreviousSearch.sSearch;
2864
                var displayMaster = settings.aiDisplayMaster;
2865
                var display, invalidated, i;
2866
 
2867
                // Need to take account of custom filtering functions - always filter
2868
                if ( DataTable.ext.search.length !== 0 ) {
2869
                        force = true;
2870
                }
2871
 
2872
                // Check if any of the rows were invalidated
2873
                invalidated = _fnFilterData( settings );
2874
 
2875
                // If the input is blank - we just want the full data set
2876
                if ( input.length <= 0 ) {
2877
                        settings.aiDisplay = displayMaster.slice();
2878
                }
2879
                else {
2880
                        // New search - start from the master array
2881
                        if ( invalidated ||
2882
                                 force ||
2883
                                 prevSearch.length > input.length ||
2884
                                 input.indexOf(prevSearch) !== 0 ||
2885
                                 settings.bSorted // On resort, the display master needs to be
2886
                                                  // re-filtered since indexes will have changed
2887
                        ) {
2888
                                settings.aiDisplay = displayMaster.slice();
2889
                        }
2890
 
2891
                        // Search the display array
2892
                        display = settings.aiDisplay;
2893
 
2894
                        for ( i=display.length-1 ; i>=0 ; i-- ) {
2895
                                if ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) {
2896
                                        display.splice( i, 1 );
2897
                                }
2898
                        }
2899
                }
2900
        }
2901
 
2902
 
2903
        /**
2904
         * Build a regular expression object suitable for searching a table
2905
         *  @param {string} sSearch string to search for
2906
         *  @param {bool} bRegex treat as a regular expression or not
2907
         *  @param {bool} bSmart perform smart filtering or not
2908
         *  @param {bool} bCaseInsensitive Do case insensitive matching or not
2909
         *  @returns {RegExp} constructed object
2910
         *  @memberof DataTable#oApi
2911
         */
2912
        function _fnFilterCreateSearch( search, regex, smart, caseInsensitive )
2913
        {
2914
                search = regex ?
2915
                        search :
2916
                        _fnEscapeRegex( search );
2917
 
2918
                if ( smart ) {
2919
                        /* For smart filtering we want to allow the search to work regardless of
2920
                         * word order. We also want double quoted text to be preserved, so word
2921
                         * order is important - a la google. So this is what we want to
2922
                         * generate:
2923
                         *
2924
                         * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$
2925
                         */
2926
                        var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || '', function ( word ) {
2927
                                return word.charAt(0) === '"' ?
2928
                                        word.match( /^"(.*)"$/ )[1] :
2929
                                        word;
2930
                        } );
2931
 
2932
                        search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$';
2933
                }
2934
 
2935
                return new RegExp( search, caseInsensitive ? 'i' : '' );
2936
        }
2937
 
2938
 
2939
        /**
2940
         * scape a string such that it can be used in a regular expression
2941
         *  @param {string} sVal string to escape
2942
         *  @returns {string} escaped string
2943
         *  @memberof DataTable#oApi
2944
         */
2945
        function _fnEscapeRegex ( sVal )
2946
        {
2947
                return sVal.replace( _re_escape_regex, '\\$1' );
2948
        }
2949
 
2950
 
2951
 
2952
        var __filter_div = $('<div>')[0];
2953
        var __filter_div_textContent = __filter_div.textContent !== undefined;
2954
 
2955
        // Update the filtering data for each row if needed (by invalidation or first run)
2956
        function _fnFilterData ( settings )
2957
        {
2958
                var columns = settings.aoColumns;
2959
                var column;
2960
                var i, j, ien, jen, filterData, cellData, row;
2961
                var fomatters = DataTable.ext.type.search;
2962
                var wasInvalidated = false;
2963
 
2964
                for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
2965
                        row = settings.aoData[i];
2966
 
2967
                        if ( ! row._aFilterData ) {
2968
                                filterData = [];
2969
 
2970
                                for ( j=0, jen=columns.length ; j<jen ; j++ ) {
2971
                                        column = columns[j];
2972
 
2973
                                        if ( column.bSearchable ) {
2974
                                                cellData = _fnGetCellData( settings, i, j, 'filter' );
2975
 
2976
                                                if ( fomatters[ column.sType ] ) {
2977
                                                        cellData = fomatters[ column.sType ]( cellData );
2978
                                                }
2979
 
2980
                                                // Search in DataTables 1.10 is string based. In 1.11 this
2981
                                                // should be altered to also allow strict type checking.
2982
                                                if ( cellData === null ) {
2983
                                                        cellData = '';
2984
                                                }
2985
 
2986
                                                if ( typeof cellData !== 'string' && cellData.toString ) {
2987
                                                        cellData = cellData.toString();
2988
                                                }
2989
                                        }
2990
                                        else {
2991
                                                cellData = '';
2992
                                        }
2993
 
2994
                                        // If it looks like there is an HTML entity in the string,
2995
                                        // attempt to decode it so sorting works as expected. Note that
2996
                                        // we could use a single line of jQuery to do this, but the DOM
2997
                                        // method used here is much faster http://jsperf.com/html-decode
2998
                                        if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) {
2999
                                                __filter_div.innerHTML = cellData;
3000
                                                cellData = __filter_div_textContent ?
3001
                                                        __filter_div.textContent :
3002
                                                        __filter_div.innerText;
3003
                                        }
3004
 
3005
                                        if ( cellData.replace ) {
3006
                                                cellData = cellData.replace(/[\r\n]/g, '');
3007
                                        }
3008
 
3009
                                        filterData.push( cellData );
3010
                                }
3011
 
3012
                                row._aFilterData = filterData;
3013
                                row._sFilterRow = filterData.join('  ');
3014
                                wasInvalidated = true;
3015
                        }
3016
                }
3017
 
3018
                return wasInvalidated;
3019
        }
3020
 
3021
 
3022
        /**
3023
         * Convert from the internal Hungarian notation to camelCase for external
3024
         * interaction
3025
         *  @param {object} obj Object to convert
3026
         *  @returns {object} Inverted object
3027
         *  @memberof DataTable#oApi
3028
         */
3029
        function _fnSearchToCamel ( obj )
3030
        {
3031
                return {
3032
                        search:          obj.sSearch,
3033
                        smart:           obj.bSmart,
3034
                        regex:           obj.bRegex,
3035
                        caseInsensitive: obj.bCaseInsensitive
3036
                };
3037
        }
3038
 
3039
 
3040
 
3041
        /**
3042
         * Convert from camelCase notation to the internal Hungarian. We could use the
3043
         * Hungarian convert function here, but this is cleaner
3044
         *  @param {object} obj Object to convert
3045
         *  @returns {object} Inverted object
3046
         *  @memberof DataTable#oApi
3047
         */
3048
        function _fnSearchToHung ( obj )
3049
        {
3050
                return {
3051
                        sSearch:          obj.search,
3052
                        bSmart:           obj.smart,
3053
                        bRegex:           obj.regex,
3054
                        bCaseInsensitive: obj.caseInsensitive
3055
                };
3056
        }
3057
 
3058
        /**
3059
         * Generate the node required for the info display
3060
         *  @param {object} oSettings dataTables settings object
3061
         *  @returns {node} Information element
3062
         *  @memberof DataTable#oApi
3063
         */
3064
        function _fnFeatureHtmlInfo ( settings )
3065
        {
3066
                var
3067
                        tid = settings.sTableId,
3068
                        nodes = settings.aanFeatures.i,
3069
                        n = $('<div/>', {
3070
                                'class': settings.oClasses.sInfo,
3071
                                'id': ! nodes ? tid+'_info' : null
3072
                        } );
3073
 
3074
                if ( ! nodes ) {
3075
                        // Update display on each draw
3076
                        settings.aoDrawCallback.push( {
3077
                                "fn": _fnUpdateInfo,
3078
                                "sName": "information"
3079
                        } );
3080
 
3081
                        n
3082
                                .attr( 'role', 'status' )
3083
                                .attr( 'aria-live', 'polite' );
3084
 
3085
                        // Table is described by our info div
3086
                        $(settings.nTable).attr( 'aria-describedby', tid+'_info' );
3087
                }
3088
 
3089
                return n[0];
3090
        }
3091
 
3092
 
3093
        /**
3094
         * Update the information elements in the display
3095
         *  @param {object} settings dataTables settings object
3096
         *  @memberof DataTable#oApi
3097
         */
3098
        function _fnUpdateInfo ( settings )
3099
        {
3100
                /* Show information about the table */
3101
                var nodes = settings.aanFeatures.i;
3102
                if ( nodes.length === 0 ) {
3103
                        return;
3104
                }
3105
 
3106
                var
3107
                        lang  = settings.oLanguage,
3108
                        start = settings._iDisplayStart+1,
3109
                        end   = settings.fnDisplayEnd(),
3110
                        max   = settings.fnRecordsTotal(),
3111
                        total = settings.fnRecordsDisplay(),
3112
                        out   = total ?
3113
                                lang.sInfo :
3114
                                lang.sInfoEmpty;
3115
 
3116
                if ( total !== max ) {
3117
                        /* Record set after filtering */
3118
                        out += ' ' + lang.sInfoFiltered;
3119
                }
3120
 
3121
                // Convert the macros
3122
                out += lang.sInfoPostFix;
3123
                out = _fnInfoMacros( settings, out );
3124
 
3125
                var callback = lang.fnInfoCallback;
3126
                if ( callback !== null ) {
3127
                        out = callback.call( settings.oInstance,
3128
                                settings, start, end, max, total, out
3129
                        );
3130
                }
3131
 
3132
                $(nodes).html( out );
3133
        }
3134
 
3135
 
3136
        function _fnInfoMacros ( settings, str )
3137
        {
3138
                // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only
3139
                // internally
3140
                var
3141
                        formatter  = settings.fnFormatNumber,
3142
                        start      = settings._iDisplayStart+1,
3143
                        len        = settings._iDisplayLength,
3144
                        vis        = settings.fnRecordsDisplay(),
3145
                        all        = len === -1;
3146
 
3147
                return str.
3148
                        replace(/_START_/g, formatter.call( settings, start ) ).
3149
                        replace(/_END_/g,   formatter.call( settings, settings.fnDisplayEnd() ) ).
3150
                        replace(/_MAX_/g,   formatter.call( settings, settings.fnRecordsTotal() ) ).
3151
                        replace(/_TOTAL_/g, formatter.call( settings, vis ) ).
3152
                        replace(/_PAGE_/g,  formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ).
3153
                        replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) );
3154
        }
3155
 
3156
 
3157
 
3158
        /**
3159
         * Draw the table for the first time, adding all required features
3160
         *  @param {object} settings dataTables settings object
3161
         *  @memberof DataTable#oApi
3162
         */
3163
        function _fnInitialise ( settings )
3164
        {
3165
                var i, iLen, iAjaxStart=settings.iInitDisplayStart;
3166
                var columns = settings.aoColumns, column;
3167
                var features = settings.oFeatures;
3168
 
3169
                /* Ensure that the table data is fully initialised */
3170
                if ( ! settings.bInitialised ) {
3171
                        setTimeout( function(){ _fnInitialise( settings ); }, 200 );
3172
                        return;
3173
                }
3174
 
3175
                /* Show the display HTML options */
3176
                _fnAddOptionsHtml( settings );
3177
 
3178
                /* Build and draw the header / footer for the table */
3179
                _fnBuildHead( settings );
3180
                _fnDrawHead( settings, settings.aoHeader );
3181
                _fnDrawHead( settings, settings.aoFooter );
3182
 
3183
                /* Okay to show that something is going on now */
3184
                _fnProcessingDisplay( settings, true );
3185
 
3186
                /* Calculate sizes for columns */
3187
                if ( features.bAutoWidth ) {
3188
                        _fnCalculateColumnWidths( settings );
3189
                }
3190
 
3191
                for ( i=0, iLen=columns.length ; i<iLen ; i++ ) {
3192
                        column = columns[i];
3193
 
3194
                        if ( column.sWidth ) {
3195
                                column.nTh.style.width = _fnStringToCss( column.sWidth );
3196
                        }
3197
                }
3198
 
3199
                // If there is default sorting required - let's do it. The sort function
3200
                // will do the drawing for us. Otherwise we draw the table regardless of the
3201
                // Ajax source - this allows the table to look initialised for Ajax sourcing
3202
                // data (show 'loading' message possibly)
3203
                _fnReDraw( settings );
3204
 
3205
                // Server-side processing init complete is done by _fnAjaxUpdateDraw
3206
                var dataSrc = _fnDataSource( settings );
3207
                if ( dataSrc != 'ssp' ) {
3208
                        // if there is an ajax source load the data
3209
                        if ( dataSrc == 'ajax' ) {
3210
                                _fnBuildAjax( settings, [], function(json) {
3211
                                        var aData = _fnAjaxDataSrc( settings, json );
3212
 
3213
                                        // Got the data - add it to the table
3214
                                        for ( i=0 ; i<aData.length ; i++ ) {
3215
                                                _fnAddData( settings, aData[i] );
3216
                                        }
3217
 
3218
                                        // Reset the init display for cookie saving. We've already done
3219
                                        // a filter, and therefore cleared it before. So we need to make
3220
                                        // it appear 'fresh'
3221
                                        settings.iInitDisplayStart = iAjaxStart;
3222
 
3223
                                        _fnReDraw( settings );
3224
 
3225
                                        _fnProcessingDisplay( settings, false );
3226
                                        _fnInitComplete( settings, json );
3227
                                }, settings );
3228
                        }
3229
                        else {
3230
                                _fnProcessingDisplay( settings, false );
3231
                                _fnInitComplete( settings );
3232
                        }
3233
                }
3234
        }
3235
 
3236
 
3237
        /**
3238
         * Draw the table for the first time, adding all required features
3239
         *  @param {object} oSettings dataTables settings object
3240
         *  @param {object} [json] JSON from the server that completed the table, if using Ajax source
3241
         *    with client-side processing (optional)
3242
         *  @memberof DataTable#oApi
3243
         */
3244
        function _fnInitComplete ( settings, json )
3245
        {
3246
                settings._bInitComplete = true;
3247
 
3248
                // On an Ajax load we now have data and therefore want to apply the column
3249
                // sizing
3250
                if ( json ) {
3251
                        _fnAdjustColumnSizing( settings );
3252
                }
3253
 
3254
                _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] );
3255
        }
3256
 
3257
 
3258
        function _fnLengthChange ( settings, val )
3259
        {
3260
                var len = parseInt( val, 10 );
3261
                settings._iDisplayLength = len;
3262
 
3263
                _fnLengthOverflow( settings );
3264
 
3265
                // Fire length change event
3266
                _fnCallbackFire( settings, null, 'length', [settings, len] );
3267
        }
3268
 
3269
 
3270
        /**
3271
         * Generate the node required for user display length changing
3272
         *  @param {object} settings dataTables settings object
3273
         *  @returns {node} Display length feature node
3274
         *  @memberof DataTable#oApi
3275
         */
3276
        function _fnFeatureHtmlLength ( settings )
3277
        {
3278
                var
3279
                        classes  = settings.oClasses,
3280
                        tableId  = settings.sTableId,
3281
                        menu     = settings.aLengthMenu,
3282
                        d2       = $.isArray( menu[0] ),
3283
                        lengths  = d2 ? menu[0] : menu,
3284
                        language = d2 ? menu[1] : menu;
3285
 
3286
                var select = $('<select/>', {
3287
                        'name':          tableId+'_length',
3288
                        'aria-controls': tableId,
3289
                        'class':         classes.sLengthSelect
3290
                } );
3291
 
3292
                for ( var i=0, ien=lengths.length ; i<ien ; i++ ) {
3293
                        select[0][ i ] = new Option( language[i], lengths[i] );
3294
                }
3295
 
3296
                var div = $('<div><label/></div>').addClass( classes.sLength );
3297
                if ( ! settings.aanFeatures.l ) {
3298
                        div[0].id = tableId+'_length';
3299
                }
3300
 
3301
                div.children().append(
3302
                        settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML )
3303
                );
3304
 
3305
                // Can't use `select` variable as user might provide their own and the
3306
                // reference is broken by the use of outerHTML
3307
                $('select', div)
3308
                        .val( settings._iDisplayLength )
3309
                        .bind( 'change.DT', function(e) {
3310
                                _fnLengthChange( settings, $(this).val() );
3311
                                _fnDraw( settings );
3312
                        } );
3313
 
3314
                // Update node value whenever anything changes the table's length
3315
                $(settings.nTable).bind( 'length.dt.DT', function (e, s, len) {
3316
                        if ( settings === s ) {
3317
                                $('select', div).val( len );
3318
                        }
3319
                } );
3320
 
3321
                return div[0];
3322
        }
3323
 
3324
 
3325
 
3326
        /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
3327
         * Note that most of the paging logic is done in
3328
         * DataTable.ext.pager
3329
         */
3330
 
3331
        /**
3332
         * Generate the node required for default pagination
3333
         *  @param {object} oSettings dataTables settings object
3334
         *  @returns {node} Pagination feature node
3335
         *  @memberof DataTable#oApi
3336
         */
3337
        function _fnFeatureHtmlPaginate ( settings )
3338
        {
3339
                var
3340
                        type   = settings.sPaginationType,
3341
                        plugin = DataTable.ext.pager[ type ],
3342
                        modern = typeof plugin === 'function',
3343
                        redraw = function( settings ) {
3344
                                _fnDraw( settings );
3345
                        },
3346
                        node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0],
3347
                        features = settings.aanFeatures;
3348
 
3349
                if ( ! modern ) {
3350
                        plugin.fnInit( settings, node, redraw );
3351
                }
3352
 
3353
                /* Add a draw callback for the pagination on first instance, to update the paging display */
3354
                if ( ! features.p )
3355
                {
3356
                        node.id = settings.sTableId+'_paginate';
3357
 
3358
                        settings.aoDrawCallback.push( {
3359
                                "fn": function( settings ) {
3360
                                        if ( modern ) {
3361
                                                var
3362
                                                        start      = settings._iDisplayStart,
3363
                                                        len        = settings._iDisplayLength,
3364
                                                        visRecords = settings.fnRecordsDisplay(),
3365
                                                        all        = len === -1,
3366
                                                        page = all ? 0 : Math.ceil( start / len ),
3367
                                                        pages = all ? 1 : Math.ceil( visRecords / len ),
3368
                                                        buttons = plugin(page, pages),
3369
                                                        i, ien;
3370
 
3371
                                                for ( i=0, ien=features.p.length ; i<ien ; i++ ) {
3372
                                                        _fnRenderer( settings, 'pageButton' )(
3373
                                                                settings, features.p[i], i, buttons, page, pages
3374
                                                        );
3375
                                                }
3376
                                        }
3377
                                        else {
3378
                                                plugin.fnUpdate( settings, redraw );
3379
                                        }
3380
                                },
3381
                                "sName": "pagination"
3382
                        } );
3383
                }
3384
 
3385
                return node;
3386
        }
3387
 
3388
 
3389
        /**
3390
         * Alter the display settings to change the page
3391
         *  @param {object} settings DataTables settings object
3392
         *  @param {string|int} action Paging action to take: "first", "previous",
3393
         *    "next" or "last" or page number to jump to (integer)
3394
         *  @param [bool] redraw Automatically draw the update or not
3395
         *  @returns {bool} true page has changed, false - no change
3396
         *  @memberof DataTable#oApi
3397
         */
3398
        function _fnPageChange ( settings, action, redraw )
3399
        {
3400
                var
3401
                        start     = settings._iDisplayStart,
3402
                        len       = settings._iDisplayLength,
3403
                        records   = settings.fnRecordsDisplay();
3404
 
3405
                if ( records === 0 || len === -1 )
3406
                {
3407
                        start = 0;
3408
                }
3409
                else if ( typeof action === "number" )
3410
                {
3411
                        start = action * len;
3412
 
3413
                        if ( start > records )
3414
                        {
3415
                                start = 0;
3416
                        }
3417
                }
3418
                else if ( action == "first" )
3419
                {
3420
                        start = 0;
3421
                }
3422
                else if ( action == "previous" )
3423
                {
3424
                        start = len >= 0 ?
3425
                                start - len :
3426
                                0;
3427
 
3428
                        if ( start < 0 )
3429
                        {
3430
                          start = 0;
3431
                        }
3432
                }
3433
                else if ( action == "next" )
3434
                {
3435
                        if ( start + len < records )
3436
                        {
3437
                                start += len;
3438
                        }
3439
                }
3440
                else if ( action == "last" )
3441
                {
3442
                        start = Math.floor( (records-1) / len) * len;
3443
                }
3444
                else
3445
                {
3446
                        _fnLog( settings, 0, "Unknown paging action: "+action, 5 );
3447
                }
3448
 
3449
                var changed = settings._iDisplayStart !== start;
3450
                settings._iDisplayStart = start;
3451
 
3452
                if ( changed ) {
3453
                        _fnCallbackFire( settings, null, 'page', [settings] );
3454
 
3455
                        if ( redraw ) {
3456
                                _fnDraw( settings );
3457
                        }
3458
                }
3459
 
3460
                return changed;
3461
        }
3462
 
3463
 
3464
 
3465
        /**
3466
         * Generate the node required for the processing node
3467
         *  @param {object} settings dataTables settings object
3468
         *  @returns {node} Processing element
3469
         *  @memberof DataTable#oApi
3470
         */
3471
        function _fnFeatureHtmlProcessing ( settings )
3472
        {
3473
                return $('<div/>', {
3474
                                'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null,
3475
                                'class': settings.oClasses.sProcessing
3476
                        } )
3477
                        .html( settings.oLanguage.sProcessing )
3478
                        .insertBefore( settings.nTable )[0];
3479
        }
3480
 
3481
 
3482
        /**
3483
         * Display or hide the processing indicator
3484
         *  @param {object} settings dataTables settings object
3485
         *  @param {bool} show Show the processing indicator (true) or not (false)
3486
         *  @memberof DataTable#oApi
3487
         */
3488
        function _fnProcessingDisplay ( settings, show )
3489
        {
3490
                if ( settings.oFeatures.bProcessing ) {
3491
                        $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' );
3492
                }
3493
 
3494
                _fnCallbackFire( settings, null, 'processing', [settings, show] );
3495
        }
3496
 
3497
        /**
3498
         * Add any control elements for the table - specifically scrolling
3499
         *  @param {object} settings dataTables settings object
3500
         *  @returns {node} Node to add to the DOM
3501
         *  @memberof DataTable#oApi
3502
         */
3503
        function _fnFeatureHtmlTable ( settings )
3504
        {
3505
                var table = $(settings.nTable);
3506
 
3507
                // Add the ARIA grid role to the table
3508
                table.attr( 'role', 'grid' );
3509
 
3510
                // Scrolling from here on in
3511
                var scroll = settings.oScroll;
3512
 
3513
                if ( scroll.sX === '' && scroll.sY === '' ) {
3514
                        return settings.nTable;
3515
                }
3516
 
3517
                var scrollX = scroll.sX;
3518
                var scrollY = scroll.sY;
3519
                var classes = settings.oClasses;
3520
                var caption = table.children('caption');
3521
                var captionSide = caption.length ? caption[0]._captionSide : null;
3522
                var headerClone = $( table[0].cloneNode(false) );
3523
                var footerClone = $( table[0].cloneNode(false) );
3524
                var footer = table.children('tfoot');
3525
                var _div = '<div/>';
3526
                var size = function ( s ) {
3527
                        return !s ? null : _fnStringToCss( s );
3528
                };
3529
 
3530
                // This is fairly messy, but with x scrolling enabled, if the table has a
3531
                // width attribute, regardless of any width applied using the column width
3532
                // options, the browser will shrink or grow the table as needed to fit into
3533
                // that 100%. That would make the width options useless. So we remove it.
3534
                // This is okay, under the assumption that width:100% is applied to the
3535
                // table in CSS (it is in the default stylesheet) which will set the table
3536
                // width as appropriate (the attribute and css behave differently...)
3537
                if ( scroll.sX && table.attr('width') === '100%' ) {
3538
                        table.removeAttr('width');
3539
                }
3540
 
3541
                if ( ! footer.length ) {
3542
                        footer = null;
3543
                }
3544
 
3545
                /*
3546
                 * The HTML structure that we want to generate in this function is:
3547
                 *  div - scroller
3548
                 *    div - scroll head
3549
                 *      div - scroll head inner
3550
                 *        table - scroll head table
3551
                 *          thead - thead
3552
                 *    div - scroll body
3553
                 *      table - table (master table)
3554
                 *        thead - thead clone for sizing
3555
                 *        tbody - tbody
3556
                 *    div - scroll foot
3557
                 *      div - scroll foot inner
3558
                 *        table - scroll foot table
3559
                 *          tfoot - tfoot
3560
                 */
3561
                var scroller = $( _div, { 'class': classes.sScrollWrapper } )
3562
                        .append(
3563
                                $(_div, { 'class': classes.sScrollHead } )
3564
                                        .css( {
3565
                                                overflow: 'hidden',
3566
                                                position: 'relative',
3567
                                                border: 0,
3568
                                                width: scrollX ? size(scrollX) : '100%'
3569
                                        } )
3570
                                        .append(
3571
                                                $(_div, { 'class': classes.sScrollHeadInner } )
3572
                                                        .css( {
3573
                                                                'box-sizing': 'content-box',
3574
                                                                width: scroll.sXInner || '100%'
3575
                                                        } )
3576
                                                        .append(
3577
                                                                headerClone
3578
                                                                        .removeAttr('id')
3579
                                                                        .css( 'margin-left', 0 )
3580
                                                                        .append(
3581
                                                                                table.children('thead')
3582
                                                                        )
3583
                                                        )
3584
                                        )
3585
                                        .append( captionSide === 'top' ? caption : null )
3586
                        )
3587
                        .append(
3588
                                $(_div, { 'class': classes.sScrollBody } )
3589
                                        .css( {
3590
                                                overflow: 'auto',
3591
                                                height: size( scrollY ),
3592
                                                width: size( scrollX )
3593
                                        } )
3594
                                        .append( table )
3595
                        );
3596
 
3597
                if ( footer ) {
3598
                        scroller.append(
3599
                                $(_div, { 'class': classes.sScrollFoot } )
3600
                                        .css( {
3601
                                                overflow: 'hidden',
3602
                                                border: 0,
3603
                                                width: scrollX ? size(scrollX) : '100%'
3604
                                        } )
3605
                                        .append(
3606
                                                $(_div, { 'class': classes.sScrollFootInner } )
3607
                                                        .append(
3608
                                                                footerClone
3609
                                                                        .removeAttr('id')
3610
                                                                        .css( 'margin-left', 0 )
3611
                                                                        .append(
3612
                                                                                table.children('tfoot')
3613
                                                                        )
3614
                                                        )
3615
                                        )
3616
                                        .append( captionSide === 'bottom' ? caption : null )
3617
                        );
3618
                }
3619
 
3620
                var children = scroller.children();
3621
                var scrollHead = children[0];
3622
                var scrollBody = children[1];
3623
                var scrollFoot = footer ? children[2] : null;
3624
 
3625
                // When the body is scrolled, then we also want to scroll the headers
3626
                if ( scrollX ) {
3627
                        $(scrollBody).scroll( function (e) {
3628
                                var scrollLeft = this.scrollLeft;
3629
 
3630
                                scrollHead.scrollLeft = scrollLeft;
3631
 
3632
                                if ( footer ) {
3633
                                        scrollFoot.scrollLeft = scrollLeft;
3634
                                }
3635
                        } );
3636
                }
3637
 
3638
                settings.nScrollHead = scrollHead;
3639
                settings.nScrollBody = scrollBody;
3640
                settings.nScrollFoot = scrollFoot;
3641
 
3642
                // On redraw - align columns
3643
                settings.aoDrawCallback.push( {
3644
                        "fn": _fnScrollDraw,
3645
                        "sName": "scrolling"
3646
                } );
3647
 
3648
                return scroller[0];
3649
        }
3650
 
3651
 
3652
 
3653
        /**
3654
         * Update the header, footer and body tables for resizing - i.e. column
3655
         * alignment.
3656
         *
3657
         * Welcome to the most horrible function DataTables. The process that this
3658
         * function follows is basically:
3659
         *   1. Re-create the table inside the scrolling div
3660
         *   2. Take live measurements from the DOM
3661
         *   3. Apply the measurements to align the columns
3662
         *   4. Clean up
3663
         *
3664
         *  @param {object} settings dataTables settings object
3665
         *  @memberof DataTable#oApi
3666
         */
3667
        function _fnScrollDraw ( settings )
3668
        {
3669
                // Given that this is such a monster function, a lot of variables are use
3670
                // to try and keep the minimised size as small as possible
3671
                var
3672
                        scroll         = settings.oScroll,
3673
                        scrollX        = scroll.sX,
3674
                        scrollXInner   = scroll.sXInner,
3675
                        scrollY        = scroll.sY,
3676
                        barWidth       = scroll.iBarWidth,
3677
                        divHeader      = $(settings.nScrollHead),
3678
                        divHeaderStyle = divHeader[0].style,
3679
                        divHeaderInner = divHeader.children('div'),
3680
                        divHeaderInnerStyle = divHeaderInner[0].style,
3681
                        divHeaderTable = divHeaderInner.children('table'),
3682
                        divBodyEl      = settings.nScrollBody,
3683
                        divBody        = $(divBodyEl),
3684
                        divBodyStyle   = divBodyEl.style,
3685
                        divFooter      = $(settings.nScrollFoot),
3686
                        divFooterInner = divFooter.children('div'),
3687
                        divFooterTable = divFooterInner.children('table'),
3688
                        header         = $(settings.nTHead),
3689
                        table          = $(settings.nTable),
3690
                        tableEl        = table[0],
3691
                        tableStyle     = tableEl.style,
3692
                        footer         = settings.nTFoot ? $(settings.nTFoot) : null,
3693
                        browser        = settings.oBrowser,
3694
                        ie67           = browser.bScrollOversize,
3695
                        headerTrgEls, footerTrgEls,
3696
                        headerSrcEls, footerSrcEls,
3697
                        headerCopy, footerCopy,
3698
                        headerWidths=[], footerWidths=[],
3699
                        headerContent=[],
3700
                        idx, correction, sanityWidth,
3701
                        zeroOut = function(nSizer) {
3702
                                var style = nSizer.style;
3703
                                style.paddingTop = "0";
3704
                                style.paddingBottom = "0";
3705
                                style.borderTopWidth = "0";
3706
                                style.borderBottomWidth = "0";
3707
                                style.height = 0;
3708
                        };
3709
 
3710
                /*
3711
                 * 1. Re-create the table inside the scrolling div
3712
                 */
3713
 
3714
                // Remove the old minimised thead and tfoot elements in the inner table
3715
                table.children('thead, tfoot').remove();
3716
 
3717
                // Clone the current header and footer elements and then place it into the inner table
3718
                headerCopy = header.clone().prependTo( table );
3719
                headerTrgEls = header.find('tr'); // original header is in its own table
3720
                headerSrcEls = headerCopy.find('tr');
3721
                headerCopy.find('th, td').removeAttr('tabindex');
3722
 
3723
                if ( footer ) {
3724
                        footerCopy = footer.clone().prependTo( table );
3725
                        footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized
3726
                        footerSrcEls = footerCopy.find('tr');
3727
                }
3728
 
3729
 
3730
                /*
3731
                 * 2. Take live measurements from the DOM - do not alter the DOM itself!
3732
                 */
3733
 
3734
                // Remove old sizing and apply the calculated column widths
3735
                // Get the unique column headers in the newly created (cloned) header. We want to apply the
3736
                // calculated sizes to this header
3737
                if ( ! scrollX )
3738
                {
3739
                        divBodyStyle.width = '100%';
3740
                        divHeader[0].style.width = '100%';
3741
                }
3742
 
3743
                $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) {
3744
                        idx = _fnVisibleToColumnIndex( settings, i );
3745
                        el.style.width = settings.aoColumns[idx].sWidth;
3746
                } );
3747
 
3748
                if ( footer ) {
3749
                        _fnApplyToChildren( function(n) {
3750
                                n.style.width = "";
3751
                        }, footerSrcEls );
3752
                }
3753
 
3754
                // If scroll collapse is enabled, when we put the headers back into the body for sizing, we
3755
                // will end up forcing the scrollbar to appear, making our measurements wrong for when we
3756
                // then hide it (end of this function), so add the header height to the body scroller.
3757
                if ( scroll.bCollapse && scrollY !== "" ) {
3758
                        divBodyStyle.height = (divBody[0].offsetHeight + header[0].offsetHeight)+"px";
3759
                }
3760
 
3761
                // Size the table as a whole
3762
                sanityWidth = table.outerWidth();
3763
                if ( scrollX === "" ) {
3764
                        // No x scrolling
3765
                        tableStyle.width = "100%";
3766
 
3767
                        // IE7 will make the width of the table when 100% include the scrollbar
3768
                        // - which is shouldn't. When there is a scrollbar we need to take this
3769
                        // into account.
3770
                        if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight ||
3771
                                divBody.css('overflow-y') == "scroll")
3772
                        ) {
3773
                                tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth);
3774
                        }
3775
                }
3776
                else
3777
                {
3778
                        // x scrolling
3779
                        if ( scrollXInner !== "" ) {
3780
                                // x scroll inner has been given - use it
3781
                                tableStyle.width = _fnStringToCss(scrollXInner);
3782
                        }
3783
                        else if ( sanityWidth == divBody.width() && divBody.height() < table.height() ) {
3784
                                // There is y-scrolling - try to take account of the y scroll bar
3785
                                tableStyle.width = _fnStringToCss( sanityWidth-barWidth );
3786
                                if ( table.outerWidth() > sanityWidth-barWidth ) {
3787
                                        // Not possible to take account of it
3788
                                        tableStyle.width = _fnStringToCss( sanityWidth );
3789
                                }
3790
                        }
3791
                        else {
3792
                                // When all else fails
3793
                                tableStyle.width = _fnStringToCss( sanityWidth );
3794
                        }
3795
                }
3796
 
3797
                // Recalculate the sanity width - now that we've applied the required width,
3798
                // before it was a temporary variable. This is required because the column
3799
                // width calculation is done before this table DOM is created.
3800
                sanityWidth = table.outerWidth();
3801
 
3802
                // Hidden header should have zero height, so remove padding and borders. Then
3803
                // set the width based on the real headers
3804
 
3805
                // Apply all styles in one pass
3806
                _fnApplyToChildren( zeroOut, headerSrcEls );
3807
 
3808
                // Read all widths in next pass
3809
                _fnApplyToChildren( function(nSizer) {
3810
                        headerContent.push( nSizer.innerHTML );
3811
                        headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
3812
                }, headerSrcEls );
3813
 
3814
                // Apply all widths in final pass
3815
                _fnApplyToChildren( function(nToSize, i) {
3816
                        nToSize.style.width = headerWidths[i];
3817
                }, headerTrgEls );
3818
 
3819
                $(headerSrcEls).height(0);
3820
 
3821
                /* Same again with the footer if we have one */
3822
                if ( footer )
3823
                {
3824
                        _fnApplyToChildren( zeroOut, footerSrcEls );
3825
 
3826
                        _fnApplyToChildren( function(nSizer) {
3827
                                footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) );
3828
                        }, footerSrcEls );
3829
 
3830
                        _fnApplyToChildren( function(nToSize, i) {
3831
                                nToSize.style.width = footerWidths[i];
3832
                        }, footerTrgEls );
3833
 
3834
                        $(footerSrcEls).height(0);
3835
                }
3836
 
3837
 
3838
                /*
3839
                 * 3. Apply the measurements
3840
                 */
3841
 
3842
                // "Hide" the header and footer that we used for the sizing. We need to keep
3843
                // the content of the cell so that the width applied to the header and body
3844
                // both match, but we want to hide it completely. We want to also fix their
3845
                // width to what they currently are
3846
                _fnApplyToChildren( function(nSizer, i) {
3847
                        nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>';
3848
                        nSizer.style.width = headerWidths[i];
3849
                }, headerSrcEls );
3850
 
3851
                if ( footer )
3852
                {
3853
                        _fnApplyToChildren( function(nSizer, i) {
3854
                                nSizer.innerHTML = "";
3855
                                nSizer.style.width = footerWidths[i];
3856
                        }, footerSrcEls );
3857
                }
3858
 
3859
                // Sanity check that the table is of a sensible width. If not then we are going to get
3860
                // misalignment - try to prevent this by not allowing the table to shrink below its min width
3861
                if ( table.outerWidth() < sanityWidth )
3862
                {
3863
                        // The min width depends upon if we have a vertical scrollbar visible or not */
3864
                        correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight ||
3865
                                divBody.css('overflow-y') == "scroll")) ?
3866
                                        sanityWidth+barWidth :
3867
                                        sanityWidth;
3868
 
3869
                        // IE6/7 are a law unto themselves...
3870
                        if ( ie67 && (divBodyEl.scrollHeight >
3871
                                divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll")
3872
                        ) {
3873
                                tableStyle.width = _fnStringToCss( correction-barWidth );
3874
                        }
3875
 
3876
                        // And give the user a warning that we've stopped the table getting too small
3877
                        if ( scrollX === "" || scrollXInner !== "" ) {
3878
                                _fnLog( settings, 1, 'Possible column misalignment', 6 );
3879
                        }
3880
                }
3881
                else
3882
                {
3883
                        correction = '100%';
3884
                }
3885
 
3886
                // Apply to the container elements
3887
                divBodyStyle.width = _fnStringToCss( correction );
3888
                divHeaderStyle.width = _fnStringToCss( correction );
3889
 
3890
                if ( footer ) {
3891
                        settings.nScrollFoot.style.width = _fnStringToCss( correction );
3892
                }
3893
 
3894
 
3895
                /*
3896
                 * 4. Clean up
3897
                 */
3898
                if ( ! scrollY ) {
3899
                        /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting
3900
                         * the scrollbar height from the visible display, rather than adding it on. We need to
3901
                         * set the height in order to sort this. Don't want to do it in any other browsers.
3902
                         */
3903
                        if ( ie67 ) {
3904
                                divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth );
3905
                        }
3906
                }
3907
 
3908
                if ( scrollY && scroll.bCollapse ) {
3909
                        divBodyStyle.height = _fnStringToCss( scrollY );
3910
 
3911
                        var iExtra = (scrollX && tableEl.offsetWidth > divBodyEl.offsetWidth) ?
3912
                                barWidth :
3913
                                0;
3914
 
3915
                        if ( tableEl.offsetHeight < divBodyEl.offsetHeight ) {
3916
                                divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+iExtra );
3917
                        }
3918
                }
3919
 
3920
                /* Finally set the width's of the header and footer tables */
3921
                var iOuterWidth = table.outerWidth();
3922
                divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth );
3923
                divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth );
3924
 
3925
                // Figure out if there are scrollbar present - if so then we need a the header and footer to
3926
                // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar)
3927
                var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll";
3928
                var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' );
3929
                divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px";
3930
 
3931
                if ( footer ) {
3932
                        divFooterTable[0].style.width = _fnStringToCss( iOuterWidth );
3933
                        divFooterInner[0].style.width = _fnStringToCss( iOuterWidth );
3934
                        divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px";
3935
                }
3936
 
3937
                /* Adjust the position of the header in case we loose the y-scrollbar */
3938
                divBody.scroll();
3939
 
3940
                // If sorting or filtering has occurred, jump the scrolling back to the top
3941
                // only if we aren't holding the position
3942
                if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) {
3943
                        divBodyEl.scrollTop = 0;
3944
                }
3945
        }
3946
 
3947
 
3948
 
3949
        /**
3950
         * Apply a given function to the display child nodes of an element array (typically
3951
         * TD children of TR rows
3952
         *  @param {function} fn Method to apply to the objects
3953
         *  @param array {nodes} an1 List of elements to look through for display children
3954
         *  @param array {nodes} an2 Another list (identical structure to the first) - optional
3955
         *  @memberof DataTable#oApi
3956
         */
3957
        function _fnApplyToChildren( fn, an1, an2 )
3958
        {
3959
                var index=0, i=0, iLen=an1.length;
3960
                var nNode1, nNode2;
3961
 
3962
                while ( i < iLen ) {
3963
                        nNode1 = an1[i].firstChild;
3964
                        nNode2 = an2 ? an2[i].firstChild : null;
3965
 
3966
                        while ( nNode1 ) {
3967
                                if ( nNode1.nodeType === 1 ) {
3968
                                        if ( an2 ) {
3969
                                                fn( nNode1, nNode2, index );
3970
                                        }
3971
                                        else {
3972
                                                fn( nNode1, index );
3973
                                        }
3974
 
3975
                                        index++;
3976
                                }
3977
 
3978
                                nNode1 = nNode1.nextSibling;
3979
                                nNode2 = an2 ? nNode2.nextSibling : null;
3980
                        }
3981
 
3982
                        i++;
3983
                }
3984
        }
3985
 
3986
 
3987
 
3988
        var __re_html_remove = /<.*?>/g;
3989
 
3990
 
3991
        /**
3992
         * Calculate the width of columns for the table
3993
         *  @param {object} oSettings dataTables settings object
3994
         *  @memberof DataTable#oApi
3995
         */
3996
        function _fnCalculateColumnWidths ( oSettings )
3997
        {
3998
                var
3999
                        table = oSettings.nTable,
4000
                        columns = oSettings.aoColumns,
4001
                        scroll = oSettings.oScroll,
4002
                        scrollY = scroll.sY,
4003
                        scrollX = scroll.sX,
4004
                        scrollXInner = scroll.sXInner,
4005
                        columnCount = columns.length,
4006
                        visibleColumns = _fnGetColumns( oSettings, 'bVisible' ),
4007
                        headerCells = $('th', oSettings.nTHead),
4008
                        tableWidthAttr = table.getAttribute('width'),
4009
                        tableContainer = table.parentNode,
4010
                        userInputs = false,
4011
                        i, column, columnIdx, width, outerWidth;
4012
 
4013
                /* Convert any user input sizes into pixel sizes */
4014
                for ( i=0 ; i<visibleColumns.length ; i++ ) {
4015
                        column = columns[ visibleColumns[i] ];
4016
 
4017
                        if ( column.sWidth !== null ) {
4018
                                column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer );
4019
 
4020
                                userInputs = true;
4021
                        }
4022
                }
4023
 
4024
                /* If the number of columns in the DOM equals the number that we have to
4025
                 * process in DataTables, then we can use the offsets that are created by
4026
                 * the web- browser. No custom sizes can be set in order for this to happen,
4027
                 * nor scrolling used
4028
                 */
4029
                if ( ! userInputs && ! scrollX && ! scrollY &&
4030
                    columnCount == _fnVisbleColumns( oSettings ) &&
4031
                        columnCount == headerCells.length
4032
                ) {
4033
                        for ( i=0 ; i<columnCount ; i++ ) {
4034
                                columns[i].sWidth = _fnStringToCss( headerCells.eq(i).width() );
4035
                        }
4036
                }
4037
                else
4038
                {
4039
                        // Otherwise construct a single row table with the widest node in the
4040
                        // data, assign any user defined widths, then insert it into the DOM and
4041
                        // allow the browser to do all the hard work of calculating table widths
4042
                        var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table
4043
                                .empty()
4044
                                .css( 'visibility', 'hidden' )
4045
                                .removeAttr( 'id' )
4046
                                .append( $(oSettings.nTHead).clone( false ) )
4047
                                .append( $(oSettings.nTFoot).clone( false ) )
4048
                                .append( $('<tbody><tr/></tbody>') );
4049
 
4050
                        // Remove any assigned widths from the footer (from scrolling)
4051
                        tmpTable.find('tfoot th, tfoot td').css('width', '');
4052
 
4053
                        var tr = tmpTable.find( 'tbody tr' );
4054
 
4055
                        // Apply custom sizing to the cloned header
4056
                        headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] );
4057
 
4058
                        for ( i=0 ; i<visibleColumns.length ; i++ ) {
4059
                                column = columns[ visibleColumns[i] ];
4060
 
4061
                                headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ?
4062
                                        _fnStringToCss( column.sWidthOrig ) :
4063
                                        '';
4064
                        }
4065
 
4066
                        // Find the widest cell for each column and put it into the table
4067
                        if ( oSettings.aoData.length ) {
4068
                                for ( i=0 ; i<visibleColumns.length ; i++ ) {
4069
                                        columnIdx = visibleColumns[i];
4070
                                        column = columns[ columnIdx ];
4071
 
4072
                                        $( _fnGetWidestNode( oSettings, columnIdx ) )
4073
                                                .clone( false )
4074
                                                .append( column.sContentPadding )
4075
                                                .appendTo( tr );
4076
                                }
4077
                        }
4078
 
4079
                        // Table has been built, attach to the document so we can work with it
4080
                        tmpTable.appendTo( tableContainer );
4081
 
4082
                        // When scrolling (X or Y) we want to set the width of the table as 
4083
                        // appropriate. However, when not scrolling leave the table width as it
4084
                        // is. This results in slightly different, but I think correct behaviour
4085
                        if ( scrollX && scrollXInner ) {
4086
                                tmpTable.width( scrollXInner );
4087
                        }
4088
                        else if ( scrollX ) {
4089
                                tmpTable.css( 'width', 'auto' );
4090
 
4091
                                if ( tmpTable.width() < tableContainer.offsetWidth ) {
4092
                                        tmpTable.width( tableContainer.offsetWidth );
4093
                                }
4094
                        }
4095
                        else if ( scrollY ) {
4096
                                tmpTable.width( tableContainer.offsetWidth );
4097
                        }
4098
                        else if ( tableWidthAttr ) {
4099
                                tmpTable.width( tableWidthAttr );
4100
                        }
4101
 
4102
                        // Take into account the y scrollbar
4103
                        _fnScrollingWidthAdjust( oSettings, tmpTable[0] );
4104
 
4105
                        // Browsers need a bit of a hand when a width is assigned to any columns
4106
                        // when x-scrolling as they tend to collapse the table to the min-width,
4107
                        // even if we sent the column widths. So we need to keep track of what
4108
                        // the table width should be by summing the user given values, and the
4109
                        // automatic values
4110
                        if ( scrollX )
4111
                        {
4112
                                var total = 0;
4113
 
4114
                                for ( i=0 ; i<visibleColumns.length ; i++ ) {
4115
                                        column = columns[ visibleColumns[i] ];
4116
                                        outerWidth = $(headerCells[i]).outerWidth();
4117
 
4118
                                        total += column.sWidthOrig === null ?
4119
                                                outerWidth :
4120
                                                parseInt( column.sWidth, 10 ) + outerWidth - $(headerCells[i]).width();
4121
                                }
4122
 
4123
                                tmpTable.width( _fnStringToCss( total ) );
4124
                                table.style.width = _fnStringToCss( total );
4125
                        }
4126
 
4127
                        // Get the width of each column in the constructed table
4128
                        for ( i=0 ; i<visibleColumns.length ; i++ ) {
4129
                                column = columns[ visibleColumns[i] ];
4130
                                width = $(headerCells[i]).width();
4131
 
4132
                                if ( width ) {
4133
                                        column.sWidth = _fnStringToCss( width );
4134
                                }
4135
                        }
4136
 
4137
                        table.style.width = _fnStringToCss( tmpTable.css('width') );
4138
 
4139
                        // Finished with the table - ditch it
4140
                        tmpTable.remove();
4141
                }
4142
 
4143
                // If there is a width attr, we want to attach an event listener which
4144
                // allows the table sizing to automatically adjust when the window is
4145
                // resized. Use the width attr rather than CSS, since we can't know if the
4146
                // CSS is a relative value or absolute - DOM read is always px.
4147
                if ( tableWidthAttr ) {
4148
                        table.style.width = _fnStringToCss( tableWidthAttr );
4149
                }
4150
 
4151
                if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) {
4152
                        $(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () {
4153
                                _fnAdjustColumnSizing( oSettings );
4154
                        } ) );
4155
 
4156
                        oSettings._reszEvt = true;
4157
                }
4158
        }
4159
 
4160
 
4161
        /**
4162
         * Throttle the calls to a function. Arguments and context are maintained for
4163
         * the throttled function
4164
         *  @param {function} fn Function to be called
4165
         *  @param {int} [freq=200] call frequency in mS
4166
         *  @returns {function} wrapped function
4167
         *  @memberof DataTable#oApi
4168
         */
4169
        function _fnThrottle( fn, freq ) {
4170
                var
4171
                        frequency = freq || 200,
4172
                        last,
4173
                        timer;
4174
 
4175
                return function () {
4176
                        var
4177
                                that = this,
4178
                                now  = +new Date(),
4179
                                args = arguments;
4180
 
4181
                        if ( last && now < last + frequency ) {
4182
                                clearTimeout( timer );
4183
 
4184
                                timer = setTimeout( function () {
4185
                                        last = undefined;
4186
                                        fn.apply( that, args );
4187
                                }, frequency );
4188
                        }
4189
                        else if ( last ) {
4190
                                last = now;
4191
                                fn.apply( that, args );
4192
                        }
4193
                        else {
4194
                                last = now;
4195
                        }
4196
                };
4197
        }
4198
 
4199
 
4200
        /**
4201
         * Convert a CSS unit width to pixels (e.g. 2em)
4202
         *  @param {string} width width to be converted
4203
         *  @param {node} parent parent to get the with for (required for relative widths) - optional
4204
         *  @returns {int} width in pixels
4205
         *  @memberof DataTable#oApi
4206
         */
4207
        function _fnConvertToWidth ( width, parent )
4208
        {
4209
                if ( ! width ) {
4210
                        return 0;
4211
                }
4212
 
4213
                var n = $('<div/>')
4214
                        .css( 'width', _fnStringToCss( width ) )
4215
                        .appendTo( parent || document.body );
4216
 
4217
                var val = n[0].offsetWidth;
4218
                n.remove();
4219
 
4220
                return val;
4221
        }
4222
 
4223
 
4224
        /**
4225
         * Adjust a table's width to take account of vertical scroll bar
4226
         *  @param {object} oSettings dataTables settings object
4227
         *  @param {node} n table node
4228
         *  @memberof DataTable#oApi
4229
         */
4230
 
4231
        function _fnScrollingWidthAdjust ( settings, n )
4232
        {
4233
                var scroll = settings.oScroll;
4234
 
4235
                if ( scroll.sX || scroll.sY ) {
4236
                        // When y-scrolling only, we want to remove the width of the scroll bar
4237
                        // so the table + scroll bar will fit into the area available, otherwise
4238
                        // we fix the table at its current size with no adjustment
4239
                        var correction = ! scroll.sX ? scroll.iBarWidth : 0;
4240
                        n.style.width = _fnStringToCss( $(n).outerWidth() - correction );
4241
                }
4242
        }
4243
 
4244
 
4245
        /**
4246
         * Get the widest node
4247
         *  @param {object} settings dataTables settings object
4248
         *  @param {int} colIdx column of interest
4249
         *  @returns {node} widest table node
4250
         *  @memberof DataTable#oApi
4251
         */
4252
        function _fnGetWidestNode( settings, colIdx )
4253
        {
4254
                var idx = _fnGetMaxLenString( settings, colIdx );
4255
                if ( idx < 0 ) {
4256
                        return null;
4257
                }
4258
 
4259
                var data = settings.aoData[ idx ];
4260
                return ! data.nTr ? // Might not have been created when deferred rendering
4261
                        $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] :
4262
                        data.anCells[ colIdx ];
4263
        }
4264
 
4265
 
4266
        /**
4267
         * Get the maximum strlen for each data column
4268
         *  @param {object} settings dataTables settings object
4269
         *  @param {int} colIdx column of interest
4270
         *  @returns {string} max string length for each column
4271
         *  @memberof DataTable#oApi
4272
         */
4273
        function _fnGetMaxLenString( settings, colIdx )
4274
        {
4275
                var s, max=-1, maxIdx = -1;
4276
 
4277
                for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4278
                        s = _fnGetCellData( settings, i, colIdx, 'display' )+'';
4279
                        s = s.replace( __re_html_remove, '' );
4280
 
4281
                        if ( s.length > max ) {
4282
                                max = s.length;
4283
                                maxIdx = i;
4284
                        }
4285
                }
4286
 
4287
                return maxIdx;
4288
        }
4289
 
4290
 
4291
        /**
4292
         * Append a CSS unit (only if required) to a string
4293
         *  @param {string} value to css-ify
4294
         *  @returns {string} value with css unit
4295
         *  @memberof DataTable#oApi
4296
         */
4297
        function _fnStringToCss( s )
4298
        {
4299
                if ( s === null ) {
4300
                        return '0px';
4301
                }
4302
 
4303
                if ( typeof s == 'number' ) {
4304
                        return s < 0 ?
4305
                                '0px' :
4306
                                s+'px';
4307
                }
4308
 
4309
                // Check it has a unit character already
4310
                return s.match(/\d$/) ?
4311
                        s+'px' :
4312
                        s;
4313
        }
4314
 
4315
 
4316
        /**
4317
         * Get the width of a scroll bar in this browser being used
4318
         *  @returns {int} width in pixels
4319
         *  @memberof DataTable#oApi
4320
         */
4321
        function _fnScrollBarWidth ()
4322
        {
4323
                // On first run a static variable is set, since this is only needed once.
4324
                // Subsequent runs will just use the previously calculated value
4325
                if ( ! DataTable.__scrollbarWidth ) {
4326
                        var inner = $('<p/>').css( {
4327
                                width: '100%',
4328
                                height: 200,
4329
                                padding: 0
4330
                        } )[0];
4331
 
4332
                        var outer = $('<div/>')
4333
                                .css( {
4334
                                        position: 'absolute',
4335
                                        top: 0,
4336
                                        left: 0,
4337
                                        width: 200,
4338
                                        height: 150,
4339
                                        padding: 0,
4340
                                        overflow: 'hidden',
4341
                                        visibility: 'hidden'
4342
                                } )
4343
                                .append( inner )
4344
                                .appendTo( 'body' );
4345
 
4346
                        var w1 = inner.offsetWidth;
4347
                        outer.css( 'overflow', 'scroll' );
4348
                        var w2 = inner.offsetWidth;
4349
 
4350
                        if ( w1 === w2 ) {
4351
                                w2 = outer[0].clientWidth;
4352
                        }
4353
 
4354
                        outer.remove();
4355
 
4356
                        DataTable.__scrollbarWidth = w1 - w2;
4357
                }
4358
 
4359
                return DataTable.__scrollbarWidth;
4360
        }
4361
 
4362
 
4363
 
4364
        function _fnSortFlatten ( settings )
4365
        {
4366
                var
4367
                        i, iLen, k, kLen,
4368
                        aSort = [],
4369
                        aiOrig = [],
4370
                        aoColumns = settings.aoColumns,
4371
                        aDataSort, iCol, sType, srcCol,
4372
                        fixed = settings.aaSortingFixed,
4373
                        fixedObj = $.isPlainObject( fixed ),
4374
                        nestedSort = [],
4375
                        add = function ( a ) {
4376
                                if ( a.length && ! $.isArray( a[0] ) ) {
4377
                                        // 1D array
4378
                                        nestedSort.push( a );
4379
                                }
4380
                                else {
4381
                                        // 2D array
4382
                                        nestedSort.push.apply( nestedSort, a );
4383
                                }
4384
                        };
4385
 
4386
                // Build the sort array, with pre-fix and post-fix options if they have been
4387
                // specified
4388
                if ( $.isArray( fixed ) ) {
4389
                        add( fixed );
4390
                }
4391
 
4392
                if ( fixedObj && fixed.pre ) {
4393
                        add( fixed.pre );
4394
                }
4395
 
4396
                add( settings.aaSorting );
4397
 
4398
                if (fixedObj && fixed.post ) {
4399
                        add( fixed.post );
4400
                }
4401
 
4402
                for ( i=0 ; i<nestedSort.length ; i++ )
4403
                {
4404
                        srcCol = nestedSort[i][0];
4405
                        aDataSort = aoColumns[ srcCol ].aDataSort;
4406
 
4407
                        for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ )
4408
                        {
4409
                                iCol = aDataSort[k];
4410
                                sType = aoColumns[ iCol ].sType || 'string';
4411
 
4412
                                aSort.push( {
4413
                                        src:       srcCol,
4414
                                        col:       iCol,
4415
                                        dir:       nestedSort[i][1],
4416
                                        index:     nestedSort[i][2],
4417
                                        type:      sType,
4418
                                        formatter: DataTable.ext.type.order[ sType+"-pre" ]
4419
                                } );
4420
                        }
4421
                }
4422
 
4423
                return aSort;
4424
        }
4425
 
4426
        /**
4427
         * Change the order of the table
4428
         *  @param {object} oSettings dataTables settings object
4429
         *  @memberof DataTable#oApi
4430
         *  @todo This really needs split up!
4431
         */
4432
        function _fnSort ( oSettings )
4433
        {
4434
                var
4435
                        i, ien, iLen, j, jLen, k, kLen,
4436
                        sDataType, nTh,
4437
                        aiOrig = [],
4438
                        oExtSort = DataTable.ext.type.order,
4439
                        aoData = oSettings.aoData,
4440
                        aoColumns = oSettings.aoColumns,
4441
                        aDataSort, data, iCol, sType, oSort,
4442
                        formatters = 0,
4443
                        sortCol,
4444
                        displayMaster = oSettings.aiDisplayMaster,
4445
                        aSort;
4446
 
4447
                // Resolve any column types that are unknown due to addition or invalidation
4448
                // @todo Can this be moved into a 'data-ready' handler which is called when
4449
                //   data is going to be used in the table?
4450
                _fnColumnTypes( oSettings );
4451
 
4452
                aSort = _fnSortFlatten( oSettings );
4453
 
4454
                for ( i=0, ien=aSort.length ; i<ien ; i++ ) {
4455
                        sortCol = aSort[i];
4456
 
4457
                        // Track if we can use the fast sort algorithm
4458
                        if ( sortCol.formatter ) {
4459
                                formatters++;
4460
                        }
4461
 
4462
                        // Load the data needed for the sort, for each cell
4463
                        _fnSortData( oSettings, sortCol.col );
4464
                }
4465
 
4466
                /* No sorting required if server-side or no sorting array */
4467
                if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 )
4468
                {
4469
                        // Create a value - key array of the current row positions such that we can use their
4470
                        // current position during the sort, if values match, in order to perform stable sorting
4471
                        for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) {
4472
                                aiOrig[ displayMaster[i] ] = i;
4473
                        }
4474
 
4475
                        /* Do the sort - here we want multi-column sorting based on a given data source (column)
4476
                         * and sorting function (from oSort) in a certain direction. It's reasonably complex to
4477
                         * follow on it's own, but this is what we want (example two column sorting):
4478
                         *  fnLocalSorting = function(a,b){
4479
                         *    var iTest;
4480
                         *    iTest = oSort['string-asc']('data11', 'data12');
4481
                         *      if (iTest !== 0)
4482
                         *        return iTest;
4483
                         *    iTest = oSort['numeric-desc']('data21', 'data22');
4484
                         *    if (iTest !== 0)
4485
                         *      return iTest;
4486
                         *    return oSort['numeric-asc']( aiOrig[a], aiOrig[b] );
4487
                         *  }
4488
                         * Basically we have a test for each sorting column, if the data in that column is equal,
4489
                         * test the next column. If all columns match, then we use a numeric sort on the row
4490
                         * positions in the original data array to provide a stable sort.
4491
                         *
4492
                         * Note - I know it seems excessive to have two sorting methods, but the first is around
4493
                         * 15% faster, so the second is only maintained for backwards compatibility with sorting
4494
                         * methods which do not have a pre-sort formatting function.
4495
                         */
4496
                        if ( formatters === aSort.length ) {
4497
                                // All sort types have formatting functions
4498
                                displayMaster.sort( function ( a, b ) {
4499
                                        var
4500
                                                x, y, k, test, sort,
4501
                                                len=aSort.length,
4502
                                                dataA = aoData[a]._aSortData,
4503
                                                dataB = aoData[b]._aSortData;
4504
 
4505
                                        for ( k=0 ; k<len ; k++ ) {
4506
                                                sort = aSort[k];
4507
 
4508
                                                x = dataA[ sort.col ];
4509
                                                y = dataB[ sort.col ];
4510
 
4511
                                                test = x<y ? -1 : x>y ? 1 : 0;
4512
                                                if ( test !== 0 ) {
4513
                                                        return sort.dir === 'asc' ? test : -test;
4514
                                                }
4515
                                        }
4516
 
4517
                                        x = aiOrig[a];
4518
                                        y = aiOrig[b];
4519
                                        return x<y ? -1 : x>y ? 1 : 0;
4520
                                } );
4521
                        }
4522
                        else {
4523
                                // Depreciated - remove in 1.11 (providing a plug-in option)
4524
                                // Not all sort types have formatting methods, so we have to call their sorting
4525
                                // methods.
4526
                                displayMaster.sort( function ( a, b ) {
4527
                                        var
4528
                                                x, y, k, l, test, sort, fn,
4529
                                                len=aSort.length,
4530
                                                dataA = aoData[a]._aSortData,
4531
                                                dataB = aoData[b]._aSortData;
4532
 
4533
                                        for ( k=0 ; k<len ; k++ ) {
4534
                                                sort = aSort[k];
4535
 
4536
                                                x = dataA[ sort.col ];
4537
                                                y = dataB[ sort.col ];
4538
 
4539
                                                fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ];
4540
                                                test = fn( x, y );
4541
                                                if ( test !== 0 ) {
4542
                                                        return test;
4543
                                                }
4544
                                        }
4545
 
4546
                                        x = aiOrig[a];
4547
                                        y = aiOrig[b];
4548
                                        return x<y ? -1 : x>y ? 1 : 0;
4549
                                } );
4550
                        }
4551
                }
4552
 
4553
                /* Tell the draw function that we have sorted the data */
4554
                oSettings.bSorted = true;
4555
        }
4556
 
4557
 
4558
        function _fnSortAria ( settings )
4559
        {
4560
                var label;
4561
                var nextSort;
4562
                var columns = settings.aoColumns;
4563
                var aSort = _fnSortFlatten( settings );
4564
                var oAria = settings.oLanguage.oAria;
4565
 
4566
                // ARIA attributes - need to loop all columns, to update all (removing old
4567
                // attributes as needed)
4568
                for ( var i=0, iLen=columns.length ; i<iLen ; i++ )
4569
                {
4570
                        var col = columns[i];
4571
                        var asSorting = col.asSorting;
4572
                        var sTitle = col.sTitle.replace( /<.*?>/g, "" );
4573
                        var th = col.nTh;
4574
 
4575
                        // IE7 is throwing an error when setting these properties with jQuery's
4576
                        // attr() and removeAttr() methods...
4577
                        th.removeAttribute('aria-sort');
4578
 
4579
                        /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */
4580
                        if ( col.bSortable ) {
4581
                                if ( aSort.length > 0 && aSort[0].col == i ) {
4582
                                        th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" );
4583
                                        nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0];
4584
                                }
4585
                                else {
4586
                                        nextSort = asSorting[0];
4587
                                }
4588
 
4589
                                label = sTitle + ( nextSort === "asc" ?
4590
                                        oAria.sSortAscending :
4591
                                        oAria.sSortDescending
4592
                                );
4593
                        }
4594
                        else {
4595
                                label = sTitle;
4596
                        }
4597
 
4598
                        th.setAttribute('aria-label', label);
4599
                }
4600
        }
4601
 
4602
 
4603
        /**
4604
         * Function to run on user sort request
4605
         *  @param {object} settings dataTables settings object
4606
         *  @param {node} attachTo node to attach the handler to
4607
         *  @param {int} colIdx column sorting index
4608
         *  @param {boolean} [append=false] Append the requested sort to the existing
4609
         *    sort if true (i.e. multi-column sort)
4610
         *  @param {function} [callback] callback function
4611
         *  @memberof DataTable#oApi
4612
         */
4613
        function _fnSortListener ( settings, colIdx, append, callback )
4614
        {
4615
                var col = settings.aoColumns[ colIdx ];
4616
                var sorting = settings.aaSorting;
4617
                var asSorting = col.asSorting;
4618
                var nextSortIdx;
4619
                var next = function ( a ) {
4620
                        var idx = a._idx;
4621
                        if ( idx === undefined ) {
4622
                                idx = $.inArray( a[1], asSorting );
4623
                        }
4624
 
4625
                        return idx+1 >= asSorting.length ? 0 : idx+1;
4626
                };
4627
 
4628
                // Convert to 2D array if needed
4629
                if ( typeof sorting[0] === 'number' ) {
4630
                        sorting = settings.aaSorting = [ sorting ];
4631
                }
4632
 
4633
                // If appending the sort then we are multi-column sorting
4634
                if ( append && settings.oFeatures.bSortMulti ) {
4635
                        // Are we already doing some kind of sort on this column?
4636
                        var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') );
4637
 
4638
                        if ( sortIdx !== -1 ) {
4639
                                // Yes, modify the sort
4640
                                nextSortIdx = next( sorting[sortIdx] );
4641
 
4642
                                sorting[sortIdx][1] = asSorting[ nextSortIdx ];
4643
                                sorting[sortIdx]._idx = nextSortIdx;
4644
                        }
4645
                        else {
4646
                                // No sort on this column yet
4647
                                sorting.push( [ colIdx, asSorting[0], 0 ] );
4648
                                sorting[sorting.length-1]._idx = 0;
4649
                        }
4650
                }
4651
                else if ( sorting.length && sorting[0][0] == colIdx ) {
4652
                        // Single column - already sorting on this column, modify the sort
4653
                        nextSortIdx = next( sorting[0] );
4654
 
4655
                        sorting.length = 1;
4656
                        sorting[0][1] = asSorting[ nextSortIdx ];
4657
                        sorting[0]._idx = nextSortIdx;
4658
                }
4659
                else {
4660
                        // Single column - sort only on this column
4661
                        sorting.length = 0;
4662
                        sorting.push( [ colIdx, asSorting[0] ] );
4663
                        sorting[0]._idx = 0;
4664
                }
4665
 
4666
                // Run the sort by calling a full redraw
4667
                _fnReDraw( settings );
4668
 
4669
                // callback used for async user interaction
4670
                if ( typeof callback == 'function' ) {
4671
                        callback( settings );
4672
                }
4673
        }
4674
 
4675
 
4676
        /**
4677
         * Attach a sort handler (click) to a node
4678
         *  @param {object} settings dataTables settings object
4679
         *  @param {node} attachTo node to attach the handler to
4680
         *  @param {int} colIdx column sorting index
4681
         *  @param {function} [callback] callback function
4682
         *  @memberof DataTable#oApi
4683
         */
4684
        function _fnSortAttachListener ( settings, attachTo, colIdx, callback )
4685
        {
4686
                var col = settings.aoColumns[ colIdx ];
4687
 
4688
                _fnBindAction( attachTo, {}, function (e) {
4689
                        /* If the column is not sortable - don't to anything */
4690
                        if ( col.bSortable === false ) {
4691
                                return;
4692
                        }
4693
 
4694
                        // If processing is enabled use a timeout to allow the processing
4695
                        // display to be shown - otherwise to it synchronously
4696
                        if ( settings.oFeatures.bProcessing ) {
4697
                                _fnProcessingDisplay( settings, true );
4698
 
4699
                                setTimeout( function() {
4700
                                        _fnSortListener( settings, colIdx, e.shiftKey, callback );
4701
 
4702
                                        // In server-side processing, the draw callback will remove the
4703
                                        // processing display
4704
                                        if ( _fnDataSource( settings ) !== 'ssp' ) {
4705
                                                _fnProcessingDisplay( settings, false );
4706
                                        }
4707
                                }, 0 );
4708
                        }
4709
                        else {
4710
                                _fnSortListener( settings, colIdx, e.shiftKey, callback );
4711
                        }
4712
                } );
4713
        }
4714
 
4715
 
4716
        /**
4717
         * Set the sorting classes on table's body, Note: it is safe to call this function
4718
         * when bSort and bSortClasses are false
4719
         *  @param {object} oSettings dataTables settings object
4720
         *  @memberof DataTable#oApi
4721
         */
4722
        function _fnSortingClasses( settings )
4723
        {
4724
                var oldSort = settings.aLastSort;
4725
                var sortClass = settings.oClasses.sSortColumn;
4726
                var sort = _fnSortFlatten( settings );
4727
                var features = settings.oFeatures;
4728
                var i, ien, colIdx;
4729
 
4730
                if ( features.bSort && features.bSortClasses ) {
4731
                        // Remove old sorting classes
4732
                        for ( i=0, ien=oldSort.length ; i<ien ; i++ ) {
4733
                                colIdx = oldSort[i].src;
4734
 
4735
                                // Remove column sorting
4736
                                $( _pluck( settings.aoData, 'anCells', colIdx ) )
4737
                                        .removeClass( sortClass + (i<2 ? i+1 : 3) );
4738
                        }
4739
 
4740
                        // Add new column sorting
4741
                        for ( i=0, ien=sort.length ; i<ien ; i++ ) {
4742
                                colIdx = sort[i].src;
4743
 
4744
                                $( _pluck( settings.aoData, 'anCells', colIdx ) )
4745
                                        .addClass( sortClass + (i<2 ? i+1 : 3) );
4746
                        }
4747
                }
4748
 
4749
                settings.aLastSort = sort;
4750
        }
4751
 
4752
 
4753
        // Get the data to sort a column, be it from cache, fresh (populating the
4754
        // cache), or from a sort formatter
4755
        function _fnSortData( settings, idx )
4756
        {
4757
                // Custom sorting function - provided by the sort data type
4758
                var column = settings.aoColumns[ idx ];
4759
                var customSort = DataTable.ext.order[ column.sSortDataType ];
4760
                var customData;
4761
 
4762
                if ( customSort ) {
4763
                        customData = customSort.call( settings.oInstance, settings, idx,
4764
                                _fnColumnIndexToVisible( settings, idx )
4765
                        );
4766
                }
4767
 
4768
                // Use / populate cache
4769
                var row, cellData;
4770
                var formatter = DataTable.ext.type.order[ column.sType+"-pre" ];
4771
 
4772
                for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
4773
                        row = settings.aoData[i];
4774
 
4775
                        if ( ! row._aSortData ) {
4776
                                row._aSortData = [];
4777
                        }
4778
 
4779
                        if ( ! row._aSortData[idx] || customSort ) {
4780
                                cellData = customSort ?
4781
                                        customData[i] : // If there was a custom sort function, use data from there
4782
                                        _fnGetCellData( settings, i, idx, 'sort' );
4783
 
4784
                                row._aSortData[ idx ] = formatter ?
4785
                                        formatter( cellData ) :
4786
                                        cellData;
4787
                        }
4788
                }
4789
        }
4790
 
4791
 
4792
 
4793
        /**
4794
         * Save the state of a table
4795
         *  @param {object} oSettings dataTables settings object
4796
         *  @memberof DataTable#oApi
4797
         */
4798
        function _fnSaveState ( settings )
4799
        {
4800
                if ( !settings.oFeatures.bStateSave || settings.bDestroying )
4801
                {
4802
                        return;
4803
                }
4804
 
4805
                /* Store the interesting variables */
4806
                var state = {
4807
                        time:    +new Date(),
4808
                        start:   settings._iDisplayStart,
4809
                        length:  settings._iDisplayLength,
4810
                        order:   $.extend( true, [], settings.aaSorting ),
4811
                        search:  _fnSearchToCamel( settings.oPreviousSearch ),
4812
                        columns: $.map( settings.aoColumns, function ( col, i ) {
4813
                                return {
4814
                                        visible: col.bVisible,
4815
                                        search: _fnSearchToCamel( settings.aoPreSearchCols[i] )
4816
                                };
4817
                        } )
4818
                };
4819
 
4820
                _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] );
4821
 
4822
                settings.oSavedState = state;
4823
                settings.fnStateSaveCallback.call( settings.oInstance, settings, state );
4824
        }
4825
 
4826
 
4827
        /**
4828
         * Attempt to load a saved table state
4829
         *  @param {object} oSettings dataTables settings object
4830
         *  @param {object} oInit DataTables init object so we can override settings
4831
         *  @memberof DataTable#oApi
4832
         */
4833
        function _fnLoadState ( settings, oInit )
4834
        {
4835
                var i, ien;
4836
                var columns = settings.aoColumns;
4837
 
4838
                if ( ! settings.oFeatures.bStateSave ) {
4839
                        return;
4840
                }
4841
 
4842
                var state = settings.fnStateLoadCallback.call( settings.oInstance, settings );
4843
                if ( ! state || ! state.time ) {
4844
                        return;
4845
                }
4846
 
4847
                /* Allow custom and plug-in manipulation functions to alter the saved data set and
4848
                 * cancelling of loading by returning false
4849
                 */
4850
                var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, state] );
4851
                if ( $.inArray( false, abStateLoad ) !== -1 ) {
4852
                        return;
4853
                }
4854
 
4855
                /* Reject old data */
4856
                var duration = settings.iStateDuration;
4857
                if ( duration > 0 && state.time < +new Date() - (duration*1000) ) {
4858
                        return;
4859
                }
4860
 
4861
                // Number of columns have changed - all bets are off, no restore of settings
4862
                if ( columns.length !== state.columns.length ) {
4863
                        return;
4864
                }
4865
 
4866
                // Store the saved state so it might be accessed at any time
4867
                settings.oLoadedState = $.extend( true, {}, state );
4868
 
4869
                // Restore key features - todo - for 1.11 this needs to be done by
4870
                // subscribed events
4871
                settings._iDisplayStart    = state.start;
4872
                settings.iInitDisplayStart = state.start;
4873
                settings._iDisplayLength   = state.length;
4874
                settings.aaSorting = [];
4875
 
4876
                // Order
4877
                $.each( state.order, function ( i, col ) {
4878
                        settings.aaSorting.push( col[0] >= columns.length ?
4879
                                [ 0, col[1] ] :
4880
                                col
4881
                        );
4882
                } );
4883
 
4884
                // Search
4885
                $.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) );
4886
 
4887
                // Columns
4888
                for ( i=0, ien=state.columns.length ; i<ien ; i++ ) {
4889
                        var col = state.columns[i];
4890
 
4891
                        // Visibility
4892
                        columns[i].bVisible = col.visible;
4893
 
4894
                        // Search
4895
                        $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) );
4896
                }
4897
 
4898
                _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] );
4899
        }
4900
 
4901
 
4902
        /**
4903
         * Return the settings object for a particular table
4904
         *  @param {node} table table we are using as a dataTable
4905
         *  @returns {object} Settings object - or null if not found
4906
         *  @memberof DataTable#oApi
4907
         */
4908
        function _fnSettingsFromNode ( table )
4909
        {
4910
                var settings = DataTable.settings;
4911
                var idx = $.inArray( table, _pluck( settings, 'nTable' ) );
4912
 
4913
                return idx !== -1 ?
4914
                        settings[ idx ] :
4915
                        null;
4916
        }
4917
 
4918
 
4919
        /**
4920
         * Log an error message
4921
         *  @param {object} settings dataTables settings object
4922
         *  @param {int} level log error messages, or display them to the user
4923
         *  @param {string} msg error message
4924
         *  @param {int} tn Technical note id to get more information about the error.
4925
         *  @memberof DataTable#oApi
4926
         */
4927
        function _fnLog( settings, level, msg, tn )
4928
        {
4929
                msg = 'DataTables warning: '+
4930
                        (settings!==null ? 'table id='+settings.sTableId+' - ' : '')+msg;
4931
 
4932
                if ( tn ) {
4933
                        msg += '. For more information about this error, please see '+
4934
                        'http://datatables.net/tn/'+tn;
4935
                }
4936
 
4937
                if ( ! level  ) {
4938
                        // Backwards compatibility pre 1.10
4939
                        var ext = DataTable.ext;
4940
                        var type = ext.sErrMode || ext.errMode;
4941
 
4942
                        if ( type == 'alert' ) {
4943
                                alert( msg );
4944
                        }
4945
                        else {
4946
                                throw new Error(msg);
4947
                        }
4948
                }
4949
                else if ( window.console && console.log ) {
4950
                        console.log( msg );
4951
                }
4952
        }
4953
 
4954
 
4955
        /**
4956
         * See if a property is defined on one object, if so assign it to the other object
4957
         *  @param {object} ret target object
4958
         *  @param {object} src source object
4959
         *  @param {string} name property
4960
         *  @param {string} [mappedName] name to map too - optional, name used if not given
4961
         *  @memberof DataTable#oApi
4962
         */
4963
        function _fnMap( ret, src, name, mappedName )
4964
        {
4965
                if ( $.isArray( name ) ) {
4966
                        $.each( name, function (i, val) {
4967
                                if ( $.isArray( val ) ) {
4968
                                        _fnMap( ret, src, val[0], val[1] );
4969
                                }
4970
                                else {
4971
                                        _fnMap( ret, src, val );
4972
                                }
4973
                        } );
4974
 
4975
                        return;
4976
                }
4977
 
4978
                if ( mappedName === undefined ) {
4979
                        mappedName = name;
4980
                }
4981
 
4982
                if ( src[name] !== undefined ) {
4983
                        ret[mappedName] = src[name];
4984
                }
4985
        }
4986
 
4987
 
4988
        /**
4989
         * Extend objects - very similar to jQuery.extend, but deep copy objects, and
4990
         * shallow copy arrays. The reason we need to do this, is that we don't want to
4991
         * deep copy array init values (such as aaSorting) since the dev wouldn't be
4992
         * able to override them, but we do want to deep copy arrays.
4993
         *  @param {object} out Object to extend
4994
         *  @param {object} extender Object from which the properties will be applied to
4995
         *      out
4996
         *  @param {boolean} breakRefs If true, then arrays will be sliced to take an
4997
         *      independent copy with the exception of the `data` or `aaData` parameters
4998
         *      if they are present. This is so you can pass in a collection to
4999
         *      DataTables and have that used as your data source without breaking the
5000
         *      references
5001
         *  @returns {object} out Reference, just for convenience - out === the return.
5002
         *  @memberof DataTable#oApi
5003
         *  @todo This doesn't take account of arrays inside the deep copied objects.
5004
         */
5005
        function _fnExtend( out, extender, breakRefs )
5006
        {
5007
                var val;
5008
 
5009
                for ( var prop in extender ) {
5010
                        if ( extender.hasOwnProperty(prop) ) {
5011
                                val = extender[prop];
5012
 
5013
                                if ( $.isPlainObject( val ) ) {
5014
                                        if ( ! $.isPlainObject( out[prop] ) ) {
5015
                                                out[prop] = {};
5016
                                        }
5017
                                        $.extend( true, out[prop], val );
5018
                                }
5019
                                else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) {
5020
                                        out[prop] = val.slice();
5021
                                }
5022
                                else {
5023
                                        out[prop] = val;
5024
                                }
5025
                        }
5026
                }
5027
 
5028
                return out;
5029
        }
5030
 
5031
 
5032
        /**
5033
         * Bind an event handers to allow a click or return key to activate the callback.
5034
         * This is good for accessibility since a return on the keyboard will have the
5035
         * same effect as a click, if the element has focus.
5036
         *  @param {element} n Element to bind the action to
5037
         *  @param {object} oData Data object to pass to the triggered function
5038
         *  @param {function} fn Callback function for when the event is triggered
5039
         *  @memberof DataTable#oApi
5040
         */
5041
        function _fnBindAction( n, oData, fn )
5042
        {
5043
                $(n)
5044
                        .bind( 'click.DT', oData, function (e) {
5045
                                        n.blur(); // Remove focus outline for mouse users
5046
                                        fn(e);
5047
                                } )
5048
                        .bind( 'keypress.DT', oData, function (e){
5049
                                        if ( e.which === 13 ) {
5050
                                                e.preventDefault();
5051
                                                fn(e);
5052
                                        }
5053
                                } )
5054
                        .bind( 'selectstart.DT', function () {
5055
                                        /* Take the brutal approach to cancelling text selection */
5056
                                        return false;
5057
                                } );
5058
        }
5059
 
5060
 
5061
        /**
5062
         * Register a callback function. Easily allows a callback function to be added to
5063
         * an array store of callback functions that can then all be called together.
5064
         *  @param {object} oSettings dataTables settings object
5065
         *  @param {string} sStore Name of the array storage for the callbacks in oSettings
5066
         *  @param {function} fn Function to be called back
5067
         *  @param {string} sName Identifying name for the callback (i.e. a label)
5068
         *  @memberof DataTable#oApi
5069
         */
5070
        function _fnCallbackReg( oSettings, sStore, fn, sName )
5071
        {
5072
                if ( fn )
5073
                {
5074
                        oSettings[sStore].push( {
5075
                                "fn": fn,
5076
                                "sName": sName
5077
                        } );
5078
                }
5079
        }
5080
 
5081
 
5082
        /**
5083
         * Fire callback functions and trigger events. Note that the loop over the
5084
         * callback array store is done backwards! Further note that you do not want to
5085
         * fire off triggers in time sensitive applications (for example cell creation)
5086
         * as its slow.
5087
         *  @param {object} settings dataTables settings object
5088
         *  @param {string} callbackArr Name of the array storage for the callbacks in
5089
         *      oSettings
5090
         *  @param {string} event Name of the jQuery custom event to trigger. If null no
5091
         *      trigger is fired
5092
         *  @param {array} args Array of arguments to pass to the callback function /
5093
         *      trigger
5094
         *  @memberof DataTable#oApi
5095
         */
5096
        function _fnCallbackFire( settings, callbackArr, e, args )
5097
        {
5098
                var ret = [];
5099
 
5100
                if ( callbackArr ) {
5101
                        ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) {
5102
                                return val.fn.apply( settings.oInstance, args );
5103
                        } );
5104
                }
5105
 
5106
                if ( e !== null ) {
5107
                        $(settings.nTable).trigger( e+'.dt', args );
5108
                }
5109
 
5110
                return ret;
5111
        }
5112
 
5113
 
5114
        function _fnLengthOverflow ( settings )
5115
        {
5116
                var
5117
                        start = settings._iDisplayStart,
5118
                        end = settings.fnDisplayEnd(),
5119
                        len = settings._iDisplayLength;
5120
 
5121
                /* If we have space to show extra rows (backing up from the end point - then do so */
5122
                if ( end === settings.fnRecordsDisplay() )
5123
                {
5124
                        start = end - len;
5125
                }
5126
 
5127
                if ( len === -1 || start < 0 )
5128
                {
5129
                        start = 0;
5130
                }
5131
 
5132
                settings._iDisplayStart = start;
5133
        }
5134
 
5135
 
5136
        function _fnRenderer( settings, type )
5137
        {
5138
                var renderer = settings.renderer;
5139
                var host = DataTable.ext.renderer[type];
5140
 
5141
                if ( $.isPlainObject( renderer ) && renderer[type] ) {
5142
                        // Specific renderer for this type. If available use it, otherwise use
5143
                        // the default.
5144
                        return host[renderer[type]] || host._;
5145
                }
5146
                else if ( typeof renderer === 'string' ) {
5147
                        // Common renderer - if there is one available for this type use it,
5148
                        // otherwise use the default
5149
                        return host[renderer] || host._;
5150
                }
5151
 
5152
                // Use the default
5153
                return host._;
5154
        }
5155
 
5156
 
5157
        /**
5158
         * Detect the data source being used for the table. Used to simplify the code
5159
         * a little (ajax) and to make it compress a little smaller.
5160
         *
5161
         *  @param {object} settings dataTables settings object
5162
         *  @returns {string} Data source
5163
         *  @memberof DataTable#oApi
5164
         */
5165
        function _fnDataSource ( settings )
5166
        {
5167
                if ( settings.oFeatures.bServerSide ) {
5168
                        return 'ssp';
5169
                }
5170
                else if ( settings.ajax || settings.sAjaxSource ) {
5171
                        return 'ajax';
5172
                }
5173
                return 'dom';
5174
        }
5175
 
5176
 
5177
        DataTable = function( options )
5178
        {
5179
                /**
5180
                 * Perform a jQuery selector action on the table's TR elements (from the tbody) and
5181
                 * return the resulting jQuery object.
5182
                 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
5183
                 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
5184
                 *  @param {string} [oOpts.filter=none] Select TR elements that meet the current filter
5185
                 *    criterion ("applied") or all TR elements (i.e. no filter).
5186
                 *  @param {string} [oOpts.order=current] Order of the TR elements in the processed array.
5187
                 *    Can be either 'current', whereby the current sorting of the table is used, or
5188
                 *    'original' whereby the original order the data was read into the table is used.
5189
                 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
5190
                 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
5191
                 *    'current' and filter is 'applied', regardless of what they might be given as.
5192
                 *  @returns {object} jQuery object, filtered by the given selector.
5193
                 *  @dtopt API
5194
                 *  @deprecated Since v1.10
5195
                 *
5196
                 *  @example
5197
                 *    $(document).ready(function() {
5198
                 *      var oTable = $('#example').dataTable();
5199
                 *
5200
                 *      // Highlight every second row
5201
                 *      oTable.$('tr:odd').css('backgroundColor', 'blue');
5202
                 *    } );
5203
                 *
5204
                 *  @example
5205
                 *    $(document).ready(function() {
5206
                 *      var oTable = $('#example').dataTable();
5207
                 *
5208
                 *      // Filter to rows with 'Webkit' in them, add a background colour and then
5209
                 *      // remove the filter, thus highlighting the 'Webkit' rows only.
5210
                 *      oTable.fnFilter('Webkit');
5211
                 *      oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue');
5212
                 *      oTable.fnFilter('');
5213
                 *    } );
5214
                 */
5215
                this.$ = function ( sSelector, oOpts )
5216
                {
5217
                        return this.api(true).$( sSelector, oOpts );
5218
                };
5219
 
5220
 
5221
                /**
5222
                 * Almost identical to $ in operation, but in this case returns the data for the matched
5223
                 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes
5224
                 * rather than any descendants, so the data can be obtained for the row/cell. If matching
5225
                 * rows are found, the data returned is the original data array/object that was used to
5226
                 * create the row (or a generated array if from a DOM source).
5227
                 *
5228
                 * This method is often useful in-combination with $ where both functions are given the
5229
                 * same parameters and the array indexes will match identically.
5230
                 *  @param {string|node|jQuery} sSelector jQuery selector or node collection to act on
5231
                 *  @param {object} [oOpts] Optional parameters for modifying the rows to be included
5232
                 *  @param {string} [oOpts.filter=none] Select elements that meet the current filter
5233
                 *    criterion ("applied") or all elements (i.e. no filter).
5234
                 *  @param {string} [oOpts.order=current] Order of the data in the processed array.
5235
                 *    Can be either 'current', whereby the current sorting of the table is used, or
5236
                 *    'original' whereby the original order the data was read into the table is used.
5237
                 *  @param {string} [oOpts.page=all] Limit the selection to the currently displayed page
5238
                 *    ("current") or not ("all"). If 'current' is given, then order is assumed to be
5239
                 *    'current' and filter is 'applied', regardless of what they might be given as.
5240
                 *  @returns {array} Data for the matched elements. If any elements, as a result of the
5241
                 *    selector, were not TR, TD or TH elements in the DataTable, they will have a null
5242
                 *    entry in the array.
5243
                 *  @dtopt API
5244
                 *  @deprecated Since v1.10
5245
                 *
5246
                 *  @example
5247
                 *    $(document).ready(function() {
5248
                 *      var oTable = $('#example').dataTable();
5249
                 *
5250
                 *      // Get the data from the first row in the table
5251
                 *      var data = oTable._('tr:first');
5252
                 *
5253
                 *      // Do something useful with the data
5254
                 *      alert( "First cell is: "+data[0] );
5255
                 *    } );
5256
                 *
5257
                 *  @example
5258
                 *    $(document).ready(function() {
5259
                 *      var oTable = $('#example').dataTable();
5260
                 *
5261
                 *      // Filter to 'Webkit' and get all data for
5262
                 *      oTable.fnFilter('Webkit');
5263
                 *      var data = oTable._('tr', {"search": "applied"});
5264
                 *
5265
                 *      // Do something with the data
5266
                 *      alert( data.length+" rows matched the search" );
5267
                 *    } );
5268
                 */
5269
                this._ = function ( sSelector, oOpts )
5270
                {
5271
                        return this.api(true).rows( sSelector, oOpts ).data();
5272
                };
5273
 
5274
 
5275
                /**
5276
                 * Create a DataTables Api instance, with the currently selected tables for
5277
                 * the Api's context.
5278
                 * @param {boolean} [traditional=false] Set the API instance's context to be
5279
                 *   only the table referred to by the `DataTable.ext.iApiIndex` option, as was
5280
                 *   used in the API presented by DataTables 1.9- (i.e. the traditional mode),
5281
                 *   or if all tables captured in the jQuery object should be used.
5282
                 * @return {DataTables.Api}
5283
                 */
5284
                this.api = function ( traditional )
5285
                {
5286
                        return traditional ?
5287
                                new _Api(
5288
                                        _fnSettingsFromNode( this[ _ext.iApiIndex ] )
5289
                                ) :
5290
                                new _Api( this );
5291
                };
5292
 
5293
 
5294
                /**
5295
                 * Add a single new row or multiple rows of data to the table. Please note
5296
                 * that this is suitable for client-side processing only - if you are using
5297
                 * server-side processing (i.e. "bServerSide": true), then to add data, you
5298
                 * must add it to the data source, i.e. the server-side, through an Ajax call.
5299
                 *  @param {array|object} data The data to be added to the table. This can be:
5300
                 *    <ul>
5301
                 *      <li>1D array of data - add a single row with the data provided</li>
5302
                 *      <li>2D array of arrays - add multiple rows in a single call</li>
5303
                 *      <li>object - data object when using <i>mData</i></li>
5304
                 *      <li>array of objects - multiple data objects when using <i>mData</i></li>
5305
                 *    </ul>
5306
                 *  @param {bool} [redraw=true] redraw the table or not
5307
                 *  @returns {array} An array of integers, representing the list of indexes in
5308
                 *    <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to
5309
                 *    the table.
5310
                 *  @dtopt API
5311
                 *  @deprecated Since v1.10
5312
                 *
5313
                 *  @example
5314
                 *    // Global var for counter
5315
                 *    var giCount = 2;
5316
                 *
5317
                 *    $(document).ready(function() {
5318
                 *      $('#example').dataTable();
5319
                 *    } );
5320
                 *
5321
                 *    function fnClickAddRow() {
5322
                 *      $('#example').dataTable().fnAddData( [
5323
                 *        giCount+".1",
5324
                 *        giCount+".2",
5325
                 *        giCount+".3",
5326
                 *        giCount+".4" ]
5327
                 *      );
5328
                 *
5329
                 *      giCount++;
5330
                 *    }
5331
                 */
5332
                this.fnAddData = function( data, redraw )
5333
                {
5334
                        var api = this.api( true );
5335
 
5336
                        /* Check if we want to add multiple rows or not */
5337
                        var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ?
5338
                                api.rows.add( data ) :
5339
                                api.row.add( data );
5340
 
5341
                        if ( redraw === undefined || redraw ) {
5342
                                api.draw();
5343
                        }
5344
 
5345
                        return rows.flatten().toArray();
5346
                };
5347
 
5348
 
5349
                /**
5350
                 * This function will make DataTables recalculate the column sizes, based on the data
5351
                 * contained in the table and the sizes applied to the columns (in the DOM, CSS or
5352
                 * through the sWidth parameter). This can be useful when the width of the table's
5353
                 * parent element changes (for example a window resize).
5354
                 *  @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to
5355
                 *  @dtopt API
5356
                 *  @deprecated Since v1.10
5357
                 *
5358
                 *  @example
5359
                 *    $(document).ready(function() {
5360
                 *      var oTable = $('#example').dataTable( {
5361
                 *        "sScrollY": "200px",
5362
                 *        "bPaginate": false
5363
                 *      } );
5364
                 *
5365
                 *      $(window).bind('resize', function () {
5366
                 *        oTable.fnAdjustColumnSizing();
5367
                 *      } );
5368
                 *    } );
5369
                 */
5370
                this.fnAdjustColumnSizing = function ( bRedraw )
5371
                {
5372
                        var api = this.api( true ).columns.adjust();
5373
                        var settings = api.settings()[0];
5374
                        var scroll = settings.oScroll;
5375
 
5376
                        if ( bRedraw === undefined || bRedraw ) {
5377
                                api.draw( false );
5378
                        }
5379
                        else if ( scroll.sX !== "" || scroll.sY !== "" ) {
5380
                                /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */
5381
                                _fnScrollDraw( settings );
5382
                        }
5383
                };
5384
 
5385
 
5386
                /**
5387
                 * Quickly and simply clear a table
5388
                 *  @param {bool} [bRedraw=true] redraw the table or not
5389
                 *  @dtopt API
5390
                 *  @deprecated Since v1.10
5391
                 *
5392
                 *  @example
5393
                 *    $(document).ready(function() {
5394
                 *      var oTable = $('#example').dataTable();
5395
                 *
5396
                 *      // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...)
5397
                 *      oTable.fnClearTable();
5398
                 *    } );
5399
                 */
5400
                this.fnClearTable = function( bRedraw )
5401
                {
5402
                        var api = this.api( true ).clear();
5403
 
5404
                        if ( bRedraw === undefined || bRedraw ) {
5405
                                api.draw();
5406
                        }
5407
                };
5408
 
5409
 
5410
                /**
5411
                 * The exact opposite of 'opening' a row, this function will close any rows which
5412
                 * are currently 'open'.
5413
                 *  @param {node} nTr the table row to 'close'
5414
                 *  @returns {int} 0 on success, or 1 if failed (can't find the row)
5415
                 *  @dtopt API
5416
                 *  @deprecated Since v1.10
5417
                 *
5418
                 *  @example
5419
                 *    $(document).ready(function() {
5420
                 *      var oTable;
5421
                 *
5422
                 *      // 'open' an information row when a row is clicked on
5423
                 *      $('#example tbody tr').click( function () {
5424
                 *        if ( oTable.fnIsOpen(this) ) {
5425
                 *          oTable.fnClose( this );
5426
                 *        } else {
5427
                 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5428
                 *        }
5429
                 *      } );
5430
                 *
5431
                 *      oTable = $('#example').dataTable();
5432
                 *    } );
5433
                 */
5434
                this.fnClose = function( nTr )
5435
                {
5436
                        this.api( true ).row( nTr ).child.hide();
5437
                };
5438
 
5439
 
5440
                /**
5441
                 * Remove a row for the table
5442
                 *  @param {mixed} target The index of the row from aoData to be deleted, or
5443
                 *    the TR element you want to delete
5444
                 *  @param {function|null} [callBack] Callback function
5445
                 *  @param {bool} [redraw=true] Redraw the table or not
5446
                 *  @returns {array} The row that was deleted
5447
                 *  @dtopt API
5448
                 *  @deprecated Since v1.10
5449
                 *
5450
                 *  @example
5451
                 *    $(document).ready(function() {
5452
                 *      var oTable = $('#example').dataTable();
5453
                 *
5454
                 *      // Immediately remove the first row
5455
                 *      oTable.fnDeleteRow( 0 );
5456
                 *    } );
5457
                 */
5458
                this.fnDeleteRow = function( target, callback, redraw )
5459
                {
5460
                        var api = this.api( true );
5461
                        var rows = api.rows( target );
5462
                        var settings = rows.settings()[0];
5463
                        var data = settings.aoData[ rows[0][0] ];
5464
 
5465
                        rows.remove();
5466
 
5467
                        if ( callback ) {
5468
                                callback.call( this, settings, data );
5469
                        }
5470
 
5471
                        if ( redraw === undefined || redraw ) {
5472
                                api.draw();
5473
                        }
5474
 
5475
                        return data;
5476
                };
5477
 
5478
 
5479
                /**
5480
                 * Restore the table to it's original state in the DOM by removing all of DataTables
5481
                 * enhancements, alterations to the DOM structure of the table and event listeners.
5482
                 *  @param {boolean} [remove=false] Completely remove the table from the DOM
5483
                 *  @dtopt API
5484
                 *  @deprecated Since v1.10
5485
                 *
5486
                 *  @example
5487
                 *    $(document).ready(function() {
5488
                 *      // This example is fairly pointless in reality, but shows how fnDestroy can be used
5489
                 *      var oTable = $('#example').dataTable();
5490
                 *      oTable.fnDestroy();
5491
                 *    } );
5492
                 */
5493
                this.fnDestroy = function ( remove )
5494
                {
5495
                        this.api( true ).destroy( remove );
5496
                };
5497
 
5498
 
5499
                /**
5500
                 * Redraw the table
5501
                 *  @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw.
5502
                 *  @dtopt API
5503
                 *  @deprecated Since v1.10
5504
                 *
5505
                 *  @example
5506
                 *    $(document).ready(function() {
5507
                 *      var oTable = $('#example').dataTable();
5508
                 *
5509
                 *      // Re-draw the table - you wouldn't want to do it here, but it's an example :-)
5510
                 *      oTable.fnDraw();
5511
                 *    } );
5512
                 */
5513
                this.fnDraw = function( complete )
5514
                {
5515
                        // Note that this isn't an exact match to the old call to _fnDraw - it takes
5516
                        // into account the new data, but can old position.
5517
                        this.api( true ).draw( ! complete );
5518
                };
5519
 
5520
 
5521
                /**
5522
                 * Filter the input based on data
5523
                 *  @param {string} sInput String to filter the table on
5524
                 *  @param {int|null} [iColumn] Column to limit filtering to
5525
                 *  @param {bool} [bRegex=false] Treat as regular expression or not
5526
                 *  @param {bool} [bSmart=true] Perform smart filtering or not
5527
                 *  @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es)
5528
                 *  @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false)
5529
                 *  @dtopt API
5530
                 *  @deprecated Since v1.10
5531
                 *
5532
                 *  @example
5533
                 *    $(document).ready(function() {
5534
                 *      var oTable = $('#example').dataTable();
5535
                 *
5536
                 *      // Sometime later - filter...
5537
                 *      oTable.fnFilter( 'test string' );
5538
                 *    } );
5539
                 */
5540
                this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive )
5541
                {
5542
                        var api = this.api( true );
5543
 
5544
                        if ( iColumn === null || iColumn === undefined ) {
5545
                                api.search( sInput, bRegex, bSmart, bCaseInsensitive );
5546
                        }
5547
                        else {
5548
                                api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive );
5549
                        }
5550
 
5551
                        api.draw();
5552
                };
5553
 
5554
 
5555
                /**
5556
                 * Get the data for the whole table, an individual row or an individual cell based on the
5557
                 * provided parameters.
5558
                 *  @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as
5559
                 *    a TR node then the data source for the whole row will be returned. If given as a
5560
                 *    TD/TH cell node then iCol will be automatically calculated and the data for the
5561
                 *    cell returned. If given as an integer, then this is treated as the aoData internal
5562
                 *    data index for the row (see fnGetPosition) and the data for that row used.
5563
                 *  @param {int} [col] Optional column index that you want the data of.
5564
                 *  @returns {array|object|string} If mRow is undefined, then the data for all rows is
5565
                 *    returned. If mRow is defined, just data for that row, and is iCol is
5566
                 *    defined, only data for the designated cell is returned.
5567
                 *  @dtopt API
5568
                 *  @deprecated Since v1.10
5569
                 *
5570
                 *  @example
5571
                 *    // Row data
5572
                 *    $(document).ready(function() {
5573
                 *      oTable = $('#example').dataTable();
5574
                 *
5575
                 *      oTable.$('tr').click( function () {
5576
                 *        var data = oTable.fnGetData( this );
5577
                 *        // ... do something with the array / object of data for the row
5578
                 *      } );
5579
                 *    } );
5580
                 *
5581
                 *  @example
5582
                 *    // Individual cell data
5583
                 *    $(document).ready(function() {
5584
                 *      oTable = $('#example').dataTable();
5585
                 *
5586
                 *      oTable.$('td').click( function () {
5587
                 *        var sData = oTable.fnGetData( this );
5588
                 *        alert( 'The cell clicked on had the value of '+sData );
5589
                 *      } );
5590
                 *    } );
5591
                 */
5592
                this.fnGetData = function( src, col )
5593
                {
5594
                        var api = this.api( true );
5595
 
5596
                        if ( src !== undefined ) {
5597
                                var type = src.nodeName ? src.nodeName.toLowerCase() : '';
5598
 
5599
                                return col !== undefined || type == 'td' || type == 'th' ?
5600
                                        api.cell( src, col ).data() :
5601
                                        api.row( src ).data() || null;
5602
                        }
5603
 
5604
                        return api.data().toArray();
5605
                };
5606
 
5607
 
5608
                /**
5609
                 * Get an array of the TR nodes that are used in the table's body. Note that you will
5610
                 * typically want to use the '$' API method in preference to this as it is more
5611
                 * flexible.
5612
                 *  @param {int} [iRow] Optional row index for the TR element you want
5613
                 *  @returns {array|node} If iRow is undefined, returns an array of all TR elements
5614
                 *    in the table's body, or iRow is defined, just the TR element requested.
5615
                 *  @dtopt API
5616
                 *  @deprecated Since v1.10
5617
                 *
5618
                 *  @example
5619
                 *    $(document).ready(function() {
5620
                 *      var oTable = $('#example').dataTable();
5621
                 *
5622
                 *      // Get the nodes from the table
5623
                 *      var nNodes = oTable.fnGetNodes( );
5624
                 *    } );
5625
                 */
5626
                this.fnGetNodes = function( iRow )
5627
                {
5628
                        var api = this.api( true );
5629
 
5630
                        return iRow !== undefined ?
5631
                                api.row( iRow ).node() :
5632
                                api.rows().nodes().flatten().toArray();
5633
                };
5634
 
5635
 
5636
                /**
5637
                 * Get the array indexes of a particular cell from it's DOM element
5638
                 * and column index including hidden columns
5639
                 *  @param {node} node this can either be a TR, TD or TH in the table's body
5640
                 *  @returns {int} If nNode is given as a TR, then a single index is returned, or
5641
                 *    if given as a cell, an array of [row index, column index (visible),
5642
                 *    column index (all)] is given.
5643
                 *  @dtopt API
5644
                 *  @deprecated Since v1.10
5645
                 *
5646
                 *  @example
5647
                 *    $(document).ready(function() {
5648
                 *      $('#example tbody td').click( function () {
5649
                 *        // Get the position of the current data from the node
5650
                 *        var aPos = oTable.fnGetPosition( this );
5651
                 *
5652
                 *        // Get the data array for this row
5653
                 *        var aData = oTable.fnGetData( aPos[0] );
5654
                 *
5655
                 *        // Update the data array and return the value
5656
                 *        aData[ aPos[1] ] = 'clicked';
5657
                 *        this.innerHTML = 'clicked';
5658
                 *      } );
5659
                 *
5660
                 *      // Init DataTables
5661
                 *      oTable = $('#example').dataTable();
5662
                 *    } );
5663
                 */
5664
                this.fnGetPosition = function( node )
5665
                {
5666
                        var api = this.api( true );
5667
                        var nodeName = node.nodeName.toUpperCase();
5668
 
5669
                        if ( nodeName == 'TR' ) {
5670
                                return api.row( node ).index();
5671
                        }
5672
                        else if ( nodeName == 'TD' || nodeName == 'TH' ) {
5673
                                var cell = api.cell( node ).index();
5674
 
5675
                                return [
5676
                                        cell.row,
5677
                                        cell.columnVisible,
5678
                                        cell.column
5679
                                ];
5680
                        }
5681
                        return null;
5682
                };
5683
 
5684
 
5685
                /**
5686
                 * Check to see if a row is 'open' or not.
5687
                 *  @param {node} nTr the table row to check
5688
                 *  @returns {boolean} true if the row is currently open, false otherwise
5689
                 *  @dtopt API
5690
                 *  @deprecated Since v1.10
5691
                 *
5692
                 *  @example
5693
                 *    $(document).ready(function() {
5694
                 *      var oTable;
5695
                 *
5696
                 *      // 'open' an information row when a row is clicked on
5697
                 *      $('#example tbody tr').click( function () {
5698
                 *        if ( oTable.fnIsOpen(this) ) {
5699
                 *          oTable.fnClose( this );
5700
                 *        } else {
5701
                 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5702
                 *        }
5703
                 *      } );
5704
                 *
5705
                 *      oTable = $('#example').dataTable();
5706
                 *    } );
5707
                 */
5708
                this.fnIsOpen = function( nTr )
5709
                {
5710
                        return this.api( true ).row( nTr ).child.isShown();
5711
                };
5712
 
5713
 
5714
                /**
5715
                 * This function will place a new row directly after a row which is currently
5716
                 * on display on the page, with the HTML contents that is passed into the
5717
                 * function. This can be used, for example, to ask for confirmation that a
5718
                 * particular record should be deleted.
5719
                 *  @param {node} nTr The table row to 'open'
5720
                 *  @param {string|node|jQuery} mHtml The HTML to put into the row
5721
                 *  @param {string} sClass Class to give the new TD cell
5722
                 *  @returns {node} The row opened. Note that if the table row passed in as the
5723
                 *    first parameter, is not found in the table, this method will silently
5724
                 *    return.
5725
                 *  @dtopt API
5726
                 *  @deprecated Since v1.10
5727
                 *
5728
                 *  @example
5729
                 *    $(document).ready(function() {
5730
                 *      var oTable;
5731
                 *
5732
                 *      // 'open' an information row when a row is clicked on
5733
                 *      $('#example tbody tr').click( function () {
5734
                 *        if ( oTable.fnIsOpen(this) ) {
5735
                 *          oTable.fnClose( this );
5736
                 *        } else {
5737
                 *          oTable.fnOpen( this, "Temporary row opened", "info_row" );
5738
                 *        }
5739
                 *      } );
5740
                 *
5741
                 *      oTable = $('#example').dataTable();
5742
                 *    } );
5743
                 */
5744
                this.fnOpen = function( nTr, mHtml, sClass )
5745
                {
5746
                        return this.api( true )
5747
                                .row( nTr )
5748
                                .child( mHtml, sClass )
5749
                                .show()
5750
                                .child()[0];
5751
                };
5752
 
5753
 
5754
                /**
5755
                 * Change the pagination - provides the internal logic for pagination in a simple API
5756
                 * function. With this function you can have a DataTables table go to the next,
5757
                 * previous, first or last pages.
5758
                 *  @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last"
5759
                 *    or page number to jump to (integer), note that page 0 is the first page.
5760
                 *  @param {bool} [bRedraw=true] Redraw the table or not
5761
                 *  @dtopt API
5762
                 *  @deprecated Since v1.10
5763
                 *
5764
                 *  @example
5765
                 *    $(document).ready(function() {
5766
                 *      var oTable = $('#example').dataTable();
5767
                 *      oTable.fnPageChange( 'next' );
5768
                 *    } );
5769
                 */
5770
                this.fnPageChange = function ( mAction, bRedraw )
5771
                {
5772
                        var api = this.api( true ).page( mAction );
5773
 
5774
                        if ( bRedraw === undefined || bRedraw ) {
5775
                                api.draw(false);
5776
                        }
5777
                };
5778
 
5779
 
5780
                /**
5781
                 * Show a particular column
5782
                 *  @param {int} iCol The column whose display should be changed
5783
                 *  @param {bool} bShow Show (true) or hide (false) the column
5784
                 *  @param {bool} [bRedraw=true] Redraw the table or not
5785
                 *  @dtopt API
5786
                 *  @deprecated Since v1.10
5787
                 *
5788
                 *  @example
5789
                 *    $(document).ready(function() {
5790
                 *      var oTable = $('#example').dataTable();
5791
                 *
5792
                 *      // Hide the second column after initialisation
5793
                 *      oTable.fnSetColumnVis( 1, false );
5794
                 *    } );
5795
                 */
5796
                this.fnSetColumnVis = function ( iCol, bShow, bRedraw )
5797
                {
5798
                        var api = this.api( true ).column( iCol ).visible( bShow );
5799
 
5800
                        if ( bRedraw === undefined || bRedraw ) {
5801
                                api.columns.adjust().draw();
5802
                        }
5803
                };
5804
 
5805
 
5806
                /**
5807
                 * Get the settings for a particular table for external manipulation
5808
                 *  @returns {object} DataTables settings object. See
5809
                 *    {@link DataTable.models.oSettings}
5810
                 *  @dtopt API
5811
                 *  @deprecated Since v1.10
5812
                 *
5813
                 *  @example
5814
                 *    $(document).ready(function() {
5815
                 *      var oTable = $('#example').dataTable();
5816
                 *      var oSettings = oTable.fnSettings();
5817
                 *
5818
                 *      // Show an example parameter from the settings
5819
                 *      alert( oSettings._iDisplayStart );
5820
                 *    } );
5821
                 */
5822
                this.fnSettings = function()
5823
                {
5824
                        return _fnSettingsFromNode( this[_ext.iApiIndex] );
5825
                };
5826
 
5827
 
5828
                /**
5829
                 * Sort the table by a particular column
5830
                 *  @param {int} iCol the data index to sort on. Note that this will not match the
5831
                 *    'display index' if you have hidden data entries
5832
                 *  @dtopt API
5833
                 *  @deprecated Since v1.10
5834
                 *
5835
                 *  @example
5836
                 *    $(document).ready(function() {
5837
                 *      var oTable = $('#example').dataTable();
5838
                 *
5839
                 *      // Sort immediately with columns 0 and 1
5840
                 *      oTable.fnSort( [ [0,'asc'], [1,'asc'] ] );
5841
                 *    } );
5842
                 */
5843
                this.fnSort = function( aaSort )
5844
                {
5845
                        this.api( true ).order( aaSort ).draw();
5846
                };
5847
 
5848
 
5849
                /**
5850
                 * Attach a sort listener to an element for a given column
5851
                 *  @param {node} nNode the element to attach the sort listener to
5852
                 *  @param {int} iColumn the column that a click on this node will sort on
5853
                 *  @param {function} [fnCallback] callback function when sort is run
5854
                 *  @dtopt API
5855
                 *  @deprecated Since v1.10
5856
                 *
5857
                 *  @example
5858
                 *    $(document).ready(function() {
5859
                 *      var oTable = $('#example').dataTable();
5860
                 *
5861
                 *      // Sort on column 1, when 'sorter' is clicked on
5862
                 *      oTable.fnSortListener( document.getElementById('sorter'), 1 );
5863
                 *    } );
5864
                 */
5865
                this.fnSortListener = function( nNode, iColumn, fnCallback )
5866
                {
5867
                        this.api( true ).order.listener( nNode, iColumn, fnCallback );
5868
                };
5869
 
5870
 
5871
                /**
5872
                 * Update a table cell or row - this method will accept either a single value to
5873
                 * update the cell with, an array of values with one element for each column or
5874
                 * an object in the same format as the original data source. The function is
5875
                 * self-referencing in order to make the multi column updates easier.
5876
                 *  @param {object|array|string} mData Data to update the cell/row with
5877
                 *  @param {node|int} mRow TR element you want to update or the aoData index
5878
                 *  @param {int} [iColumn] The column to update, give as null or undefined to
5879
                 *    update a whole row.
5880
                 *  @param {bool} [bRedraw=true] Redraw the table or not
5881
                 *  @param {bool} [bAction=true] Perform pre-draw actions or not
5882
                 *  @returns {int} 0 on success, 1 on error
5883
                 *  @dtopt API
5884
                 *  @deprecated Since v1.10
5885
                 *
5886
                 *  @example
5887
                 *    $(document).ready(function() {
5888
                 *      var oTable = $('#example').dataTable();
5889
                 *      oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell
5890
                 *      oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row
5891
                 *    } );
5892
                 */
5893
                this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction )
5894
                {
5895
                        var api = this.api( true );
5896
 
5897
                        if ( iColumn === undefined || iColumn === null ) {
5898
                                api.row( mRow ).data( mData );
5899
                        }
5900
                        else {
5901
                                api.cell( mRow, iColumn ).data( mData );
5902
                        }
5903
 
5904
                        if ( bAction === undefined || bAction ) {
5905
                                api.columns.adjust();
5906
                        }
5907
 
5908
                        if ( bRedraw === undefined || bRedraw ) {
5909
                                api.draw();
5910
                        }
5911
                        return 0;
5912
                };
5913
 
5914
 
5915
                /**
5916
                 * Provide a common method for plug-ins to check the version of DataTables being used, in order
5917
                 * to ensure compatibility.
5918
                 *  @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the
5919
                 *    formats "X" and "X.Y" are also acceptable.
5920
                 *  @returns {boolean} true if this version of DataTables is greater or equal to the required
5921
                 *    version, or false if this version of DataTales is not suitable
5922
                 *  @method
5923
                 *  @dtopt API
5924
                 *  @deprecated Since v1.10
5925
                 *
5926
                 *  @example
5927
                 *    $(document).ready(function() {
5928
                 *      var oTable = $('#example').dataTable();
5929
                 *      alert( oTable.fnVersionCheck( '1.9.0' ) );
5930
                 *    } );
5931
                 */
5932
                this.fnVersionCheck = _ext.fnVersionCheck;
5933
 
5934
 
5935
                var _that = this;
5936
                var emptyInit = options === undefined;
5937
                var len = this.length;
5938
 
5939
                if ( emptyInit ) {
5940
                        options = {};
5941
                }
5942
 
5943
                this.oApi = this.internal = _ext.internal;
5944
 
5945
                // Extend with old style plug-in API methods
5946
                for ( var fn in DataTable.ext.internal ) {
5947
                        if ( fn ) {
5948
                                this[fn] = _fnExternApiFunc(fn);
5949
                        }
5950
                }
5951
 
5952
                this.each(function() {
5953
                        // For each initialisation we want to give it a clean initialisation
5954
                        // object that can be bashed around
5955
                        var o = {};
5956
                        var oInit = len > 1 ? // optimisation for single table case
5957
                                _fnExtend( o, options, true ) :
5958
                                options;
5959
 
5960
                        /*global oInit,_that,emptyInit*/
5961
                        var i=0, iLen, j, jLen, k, kLen;
5962
                        var sId = this.getAttribute( 'id' );
5963
                        var bInitHandedOff = false;
5964
                        var defaults = DataTable.defaults;
5965
 
5966
 
5967
                        /* Sanity check */
5968
                        if ( this.nodeName.toLowerCase() != 'table' )
5969
                        {
5970
                                _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 );
5971
                                return;
5972
                        }
5973
 
5974
                        /* Backwards compatibility for the defaults */
5975
                        _fnCompatOpts( defaults );
5976
                        _fnCompatCols( defaults.column );
5977
 
5978
                        /* Convert the camel-case defaults to Hungarian */
5979
                        _fnCamelToHungarian( defaults, defaults, true );
5980
                        _fnCamelToHungarian( defaults.column, defaults.column, true );
5981
 
5982
                        /* Setting up the initialisation object */
5983
                        _fnCamelToHungarian( defaults, oInit );
5984
 
5985
                        /* Check to see if we are re-initialising a table */
5986
                        var allSettings = DataTable.settings;
5987
                        for ( i=0, iLen=allSettings.length ; i<iLen ; i++ )
5988
                        {
5989
                                /* Base check on table node */
5990
                                if ( allSettings[i].nTable == this )
5991
                                {
5992
                                        var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve;
5993
                                        var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy;
5994
 
5995
                                        if ( emptyInit || bRetrieve )
5996
                                        {
5997
                                                return allSettings[i].oInstance;
5998
                                        }
5999
                                        else if ( bDestroy )
6000
                                        {
6001
                                                allSettings[i].oInstance.fnDestroy();
6002
                                                break;
6003
                                        }
6004
                                        else
6005
                                        {
6006
                                                _fnLog( allSettings[i], 0, 'Cannot reinitialise DataTable', 3 );
6007
                                                return;
6008
                                        }
6009
                                }
6010
 
6011
                                /* If the element we are initialising has the same ID as a table which was previously
6012
                                 * initialised, but the table nodes don't match (from before) then we destroy the old
6013
                                 * instance by simply deleting it. This is under the assumption that the table has been
6014
                                 * destroyed by other methods. Anyone using non-id selectors will need to do this manually
6015
                                 */
6016
                                if ( allSettings[i].sTableId == this.id )
6017
                                {
6018
                                        allSettings.splice( i, 1 );
6019
                                        break;
6020
                                }
6021
                        }
6022
 
6023
                        /* Ensure the table has an ID - required for accessibility */
6024
                        if ( sId === null || sId === "" )
6025
                        {
6026
                                sId = "DataTables_Table_"+(DataTable.ext._unique++);
6027
                                this.id = sId;
6028
                        }
6029
 
6030
                        /* Create the settings object for this table and set some of the default parameters */
6031
                        var oSettings = $.extend( true, {}, DataTable.models.oSettings, {
6032
                                "nTable":        this,
6033
                                "oApi":          _that.internal,
6034
                                "oInit":         oInit,
6035
                                "sDestroyWidth": $(this)[0].style.width,
6036
                                "sInstance":     sId,
6037
                                "sTableId":      sId
6038
                        } );
6039
                        allSettings.push( oSettings );
6040
 
6041
                        // Need to add the instance after the instance after the settings object has been added
6042
                        // to the settings array, so we can self reference the table instance if more than one
6043
                        oSettings.oInstance = (_that.length===1) ? _that : $(this).dataTable();
6044
 
6045
                        // Backwards compatibility, before we apply all the defaults
6046
                        _fnCompatOpts( oInit );
6047
 
6048
                        if ( oInit.oLanguage )
6049
                        {
6050
                                _fnLanguageCompat( oInit.oLanguage );
6051
                        }
6052
 
6053
                        // If the length menu is given, but the init display length is not, use the length menu
6054
                        if ( oInit.aLengthMenu && ! oInit.iDisplayLength )
6055
                        {
6056
                                oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ?
6057
                                        oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0];
6058
                        }
6059
 
6060
                        // Apply the defaults and init options to make a single init object will all
6061
                        // options defined from defaults and instance options.
6062
                        oInit = _fnExtend( $.extend( true, {}, defaults ), oInit );
6063
 
6064
 
6065
                        // Map the initialisation options onto the settings object
6066
                        _fnMap( oSettings.oFeatures, oInit, [
6067
                                "bPaginate",
6068
                                "bLengthChange",
6069
                                "bFilter",
6070
                                "bSort",
6071
                                "bSortMulti",
6072
                                "bInfo",
6073
                                "bProcessing",
6074
                                "bAutoWidth",
6075
                                "bSortClasses",
6076
                                "bServerSide",
6077
                                "bDeferRender"
6078
                        ] );
6079
                        _fnMap( oSettings, oInit, [
6080
                                "asStripeClasses",
6081
                                "ajax",
6082
                                "fnServerData",
6083
                                "fnFormatNumber",
6084
                                "sServerMethod",
6085
                                "aaSorting",
6086
                                "aaSortingFixed",
6087
                                "aLengthMenu",
6088
                                "sPaginationType",
6089
                                "sAjaxSource",
6090
                                "sAjaxDataProp",
6091
                                "iStateDuration",
6092
                                "sDom",
6093
                                "bSortCellsTop",
6094
                                "iTabIndex",
6095
                                "fnStateLoadCallback",
6096
                                "fnStateSaveCallback",
6097
                                "renderer",
6098
                                [ "iCookieDuration", "iStateDuration" ], // backwards compat
6099
                                [ "oSearch", "oPreviousSearch" ],
6100
                                [ "aoSearchCols", "aoPreSearchCols" ],
6101
                                [ "iDisplayLength", "_iDisplayLength" ],
6102
                                [ "bJQueryUI", "bJUI" ]
6103
                        ] );
6104
                        _fnMap( oSettings.oScroll, oInit, [
6105
                                [ "sScrollX", "sX" ],
6106
                                [ "sScrollXInner", "sXInner" ],
6107
                                [ "sScrollY", "sY" ],
6108
                                [ "bScrollCollapse", "bCollapse" ]
6109
                        ] );
6110
                        _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" );
6111
 
6112
                        /* Callback functions which are array driven */
6113
                        _fnCallbackReg( oSettings, 'aoDrawCallback',       oInit.fnDrawCallback,      'user' );
6114
                        _fnCallbackReg( oSettings, 'aoServerParams',       oInit.fnServerParams,      'user' );
6115
                        _fnCallbackReg( oSettings, 'aoStateSaveParams',    oInit.fnStateSaveParams,   'user' );
6116
                        _fnCallbackReg( oSettings, 'aoStateLoadParams',    oInit.fnStateLoadParams,   'user' );
6117
                        _fnCallbackReg( oSettings, 'aoStateLoaded',        oInit.fnStateLoaded,       'user' );
6118
                        _fnCallbackReg( oSettings, 'aoRowCallback',        oInit.fnRowCallback,       'user' );
6119
                        _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow,        'user' );
6120
                        _fnCallbackReg( oSettings, 'aoHeaderCallback',     oInit.fnHeaderCallback,    'user' );
6121
                        _fnCallbackReg( oSettings, 'aoFooterCallback',     oInit.fnFooterCallback,    'user' );
6122
                        _fnCallbackReg( oSettings, 'aoInitComplete',       oInit.fnInitComplete,      'user' );
6123
                        _fnCallbackReg( oSettings, 'aoPreDrawCallback',    oInit.fnPreDrawCallback,   'user' );
6124
 
6125
                        var oClasses = oSettings.oClasses;
6126
 
6127
                        // @todo Remove in 1.11
6128
                        if ( oInit.bJQueryUI )
6129
                        {
6130
                                /* Use the JUI classes object for display. You could clone the oStdClasses object if
6131
                                 * you want to have multiple tables with multiple independent classes
6132
                                 */
6133
                                $.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses );
6134
 
6135
                                if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" )
6136
                                {
6137
                                        /* Set the DOM to use a layout suitable for jQuery UI's theming */
6138
                                        oSettings.sDom = '<"H"lfr>t<"F"ip>';
6139
                                }
6140
 
6141
                                if ( ! oSettings.renderer ) {
6142
                                        oSettings.renderer = 'jqueryui';
6143
                                }
6144
                                else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) {
6145
                                        oSettings.renderer.header = 'jqueryui';
6146
                                }
6147
                        }
6148
                        else
6149
                        {
6150
                                $.extend( oClasses, DataTable.ext.classes, oInit.oClasses );
6151
                        }
6152
                        $(this).addClass( oClasses.sTable );
6153
 
6154
                        /* Calculate the scroll bar width and cache it for use later on */
6155
                        if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" )
6156
                        {
6157
                                oSettings.oScroll.iBarWidth = _fnScrollBarWidth();
6158
                        }
6159
                        if ( oSettings.oScroll.sX === true ) { // Easy initialisation of x-scrolling
6160
                                oSettings.oScroll.sX = '100%';
6161
                        }
6162
 
6163
                        if ( oSettings.iInitDisplayStart === undefined )
6164
                        {
6165
                                /* Display start point, taking into account the save saving */
6166
                                oSettings.iInitDisplayStart = oInit.iDisplayStart;
6167
                                oSettings._iDisplayStart = oInit.iDisplayStart;
6168
                        }
6169
 
6170
                        if ( oInit.iDeferLoading !== null )
6171
                        {
6172
                                oSettings.bDeferLoading = true;
6173
                                var tmp = $.isArray( oInit.iDeferLoading );
6174
                                oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading;
6175
                                oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading;
6176
                        }
6177
 
6178
                        /* Language definitions */
6179
                        if ( oInit.oLanguage.sUrl !== "" )
6180
                        {
6181
                                /* Get the language definitions from a file - because this Ajax call makes the language
6182
                                 * get async to the remainder of this function we use bInitHandedOff to indicate that
6183
                                 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor
6184
                                 */
6185
                                oSettings.oLanguage.sUrl = oInit.oLanguage.sUrl;
6186
                                $.getJSON( oSettings.oLanguage.sUrl, null, function( json ) {
6187
                                        _fnLanguageCompat( json );
6188
                                        _fnCamelToHungarian( defaults.oLanguage, json );
6189
                                        $.extend( true, oSettings.oLanguage, oInit.oLanguage, json );
6190
                                        _fnInitialise( oSettings );
6191
                                } );
6192
                                bInitHandedOff = true;
6193
                        }
6194
                        else
6195
                        {
6196
                                $.extend( true, oSettings.oLanguage, oInit.oLanguage );
6197
                        }
6198
 
6199
 
6200
                        /*
6201
                         * Stripes
6202
                         */
6203
                        if ( oInit.asStripeClasses === null )
6204
                        {
6205
                                oSettings.asStripeClasses =[
6206
                                        oClasses.sStripeOdd,
6207
                                        oClasses.sStripeEven
6208
                                ];
6209
                        }
6210
 
6211
                        /* Remove row stripe classes if they are already on the table row */
6212
                        var stripeClasses = oSettings.asStripeClasses;
6213
                        var rowOne = $('tbody tr:eq(0)', this);
6214
                        if ( $.inArray( true, $.map( stripeClasses, function(el, i) {
6215
                                return rowOne.hasClass(el);
6216
                        } ) ) !== -1 ) {
6217
                                $('tbody tr', this).removeClass( stripeClasses.join(' ') );
6218
                                oSettings.asDestroyStripes = stripeClasses.slice();
6219
                        }
6220
 
6221
                        /*
6222
                         * Columns
6223
                         * See if we should load columns automatically or use defined ones
6224
                         */
6225
                        var anThs = [];
6226
                        var aoColumnsInit;
6227
                        var nThead = this.getElementsByTagName('thead');
6228
                        if ( nThead.length !== 0 )
6229
                        {
6230
                                _fnDetectHeader( oSettings.aoHeader, nThead[0] );
6231
                                anThs = _fnGetUniqueThs( oSettings );
6232
                        }
6233
 
6234
                        /* If not given a column array, generate one with nulls */
6235
                        if ( oInit.aoColumns === null )
6236
                        {
6237
                                aoColumnsInit = [];
6238
                                for ( i=0, iLen=anThs.length ; i<iLen ; i++ )
6239
                                {
6240
                                        aoColumnsInit.push( null );
6241
                                }
6242
                        }
6243
                        else
6244
                        {
6245
                                aoColumnsInit = oInit.aoColumns;
6246
                        }
6247
 
6248
                        /* Add the columns */
6249
                        for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ )
6250
                        {
6251
                                _fnAddColumn( oSettings, anThs ? anThs[i] : null );
6252
                        }
6253
 
6254
                        /* Apply the column definitions */
6255
                        _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) {
6256
                                _fnColumnOptions( oSettings, iCol, oDef );
6257
                        } );
6258
 
6259
                        /* HTML5 attribute detection - build an mData object automatically if the
6260
                         * attributes are found
6261
                         */
6262
                        if ( rowOne.length ) {
6263
                                var a = function ( cell, name ) {
6264
                                        return cell.getAttribute( 'data-'+name ) ? name : null;
6265
                                };
6266
 
6267
                                $.each( _fnGetRowElements( oSettings, rowOne[0] ).cells, function (i, cell) {
6268
                                        var col = oSettings.aoColumns[i];
6269
 
6270
                                        if ( col.mData === i ) {
6271
                                                var sort = a( cell, 'sort' ) || a( cell, 'order' );
6272
                                                var filter = a( cell, 'filter' ) || a( cell, 'search' );
6273
 
6274
                                                if ( sort !== null || filter !== null ) {
6275
                                                        col.mData = {
6276
                                                                _:      i+'.display',
6277
                                                                sort:   sort !== null   ? i+'.@data-'+sort   : undefined,
6278
                                                                type:   sort !== null   ? i+'.@data-'+sort   : undefined,
6279
                                                                filter: filter !== null ? i+'.@data-'+filter : undefined
6280
                                                        };
6281
 
6282
                                                        _fnColumnOptions( oSettings, i );
6283
                                                }
6284
                                        }
6285
                                } );
6286
                        }
6287
 
6288
                        var features = oSettings.oFeatures;
6289
 
6290
                        /* Must be done after everything which can be overridden by the state saving! */
6291
                        if ( oInit.bStateSave )
6292
                        {
6293
                                features.bStateSave = true;
6294
                                _fnLoadState( oSettings, oInit );
6295
                                _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' );
6296
                        }
6297
 
6298
 
6299
                        /*
6300
                         * Sorting
6301
                         * @todo For modularisation (1.11) this needs to do into a sort start up handler
6302
                         */
6303
 
6304
                        // If aaSorting is not defined, then we use the first indicator in asSorting
6305
                        // in case that has been altered, so the default sort reflects that option
6306
                        if ( oInit.aaSorting === undefined )
6307
                        {
6308
                                var sorting = oSettings.aaSorting;
6309
                                for ( i=0, iLen=sorting.length ; i<iLen ; i++ )
6310
                                {
6311
                                        sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0];
6312
                                }
6313
                        }
6314
 
6315
                        /* Do a first pass on the sorting classes (allows any size changes to be taken into
6316
                         * account, and also will apply sorting disabled classes if disabled
6317
                         */
6318
                        _fnSortingClasses( oSettings );
6319
 
6320
                        if ( features.bSort )
6321
                        {
6322
                                _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
6323
                                        if ( oSettings.bSorted ) {
6324
                                                var aSort = _fnSortFlatten( oSettings );
6325
                                                var sortedColumns = {};
6326
 
6327
                                                $.each( aSort, function (i, val) {
6328
                                                        sortedColumns[ val.src ] = val.dir;
6329
                                                } );
6330
 
6331
                                                _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] );
6332
                                                _fnSortAria( oSettings );
6333
                                        }
6334
                                } );
6335
                        }
6336
 
6337
                        _fnCallbackReg( oSettings, 'aoDrawCallback', function () {
6338
                                if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) {
6339
                                        _fnSortingClasses( oSettings );
6340
                                }
6341
                        }, 'sc' );
6342
 
6343
 
6344
                        /*
6345
                         * Final init
6346
                         * Cache the header, body and footer as required, creating them if needed
6347
                         */
6348
 
6349
                        /* Browser support detection */
6350
                        _fnBrowserDetect( oSettings );
6351
 
6352
                        // Work around for Webkit bug 83867 - store the caption-side before removing from doc
6353
                        var captions = $(this).children('caption').each( function () {
6354
                                this._captionSide = $(this).css('caption-side');
6355
                        } );
6356
 
6357
                        var thead = $(this).children('thead');
6358
                        if ( thead.length === 0 )
6359
                        {
6360
                                thead = $('<thead/>').appendTo(this);
6361
                        }
6362
                        oSettings.nTHead = thead[0];
6363
 
6364
                        var tbody = $(this).children('tbody');
6365
                        if ( tbody.length === 0 )
6366
                        {
6367
                                tbody = $('<tbody/>').appendTo(this);
6368
                        }
6369
                        oSettings.nTBody = tbody[0];
6370
 
6371
                        var tfoot = $(this).children('tfoot');
6372
                        if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") )
6373
                        {
6374
                                // If we are a scrolling table, and no footer has been given, then we need to create
6375
                                // a tfoot element for the caption element to be appended to
6376
                                tfoot = $('<tfoot/>').appendTo(this);
6377
                        }
6378
 
6379
                        if ( tfoot.length === 0 || tfoot.children().length === 0 ) {
6380
                                $(this).addClass( oClasses.sNoFooter );
6381
                        }
6382
                        else if ( tfoot.length > 0 ) {
6383
                                oSettings.nTFoot = tfoot[0];
6384
                                _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot );
6385
                        }
6386
 
6387
                        /* Check if there is data passing into the constructor */
6388
                        if ( oInit.aaData )
6389
                        {
6390
                                for ( i=0 ; i<oInit.aaData.length ; i++ )
6391
                                {
6392
                                        _fnAddData( oSettings, oInit.aaData[ i ] );
6393
                                }
6394
                        }
6395
                        else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' )
6396
                        {
6397
                                /* Grab the data from the page - only do this when deferred loading or no Ajax
6398
                                 * source since there is no point in reading the DOM data if we are then going
6399
                                 * to replace it with Ajax data
6400
                                 */
6401
                                _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') );
6402
                        }
6403
 
6404
                        /* Copy the data index array */
6405
                        oSettings.aiDisplay = oSettings.aiDisplayMaster.slice();
6406
 
6407
                        /* Initialisation complete - table can be drawn */
6408
                        oSettings.bInitialised = true;
6409
 
6410
                        /* Check if we need to initialise the table (it might not have been handed off to the
6411
                         * language processor)
6412
                         */
6413
                        if ( bInitHandedOff === false )
6414
                        {
6415
                                _fnInitialise( oSettings );
6416
                        }
6417
                } );
6418
                _that = null;
6419
                return this;
6420
        };
6421
 
6422
 
6423
 
6424
        /**
6425
         * Computed structure of the DataTables API, defined by the options passed to
6426
         * `DataTable.Api.register()` when building the API.
6427
         *
6428
         * The structure is built in order to speed creation and extension of the Api
6429
         * objects since the extensions are effectively pre-parsed.
6430
         *
6431
         * The array is an array of objects with the following structure, where this
6432
         * base array represents the Api prototype base:
6433
         *
6434
         *     [
6435
         *       {
6436
         *         name:      'data'                -- string   - Property name
6437
         *         val:       function () {},       -- function - Api method (or undefined if just an object
6438
         *         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6439
         *         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6440
         *       },
6441
         *       {
6442
         *         name:     'row'
6443
         *         val:       {},
6444
         *         methodExt: [ ... ],
6445
         *         propExt:   [
6446
         *           {
6447
         *             name:      'data'
6448
         *             val:       function () {},
6449
         *             methodExt: [ ... ],
6450
         *             propExt:   [ ... ]
6451
         *           },
6452
         *           ...
6453
         *         ]
6454
         *       }
6455
         *     ]
6456
         *
6457
         * @type {Array}
6458
         * @ignore
6459
         */
6460
        var __apiStruct = [];
6461
 
6462
 
6463
        /**
6464
         * `Array.prototype` reference.
6465
         *
6466
         * @type object
6467
         * @ignore
6468
         */
6469
        var __arrayProto = Array.prototype;
6470
 
6471
 
6472
        /**
6473
         * Abstraction for `context` parameter of the `Api` constructor to allow it to
6474
         * take several different forms for ease of use.
6475
         *
6476
         * Each of the input parameter types will be converted to a DataTables settings
6477
         * object where possible.
6478
         *
6479
         * @param  {string|node|jQuery|object} mixed DataTable identifier. Can be one
6480
         *   of:
6481
         *
6482
         *   * `string` - jQuery selector. Any DataTables' matching the given selector
6483
         *     with be found and used.
6484
         *   * `node` - `TABLE` node which has already been formed into a DataTable.
6485
         *   * `jQuery` - A jQuery object of `TABLE` nodes.
6486
         *   * `object` - DataTables settings object
6487
         *   * `DataTables.Api` - API instance
6488
         * @return {array|null} Matching DataTables settings objects. `null` or
6489
         *   `undefined` is returned if no matching DataTable is found.
6490
         * @ignore
6491
         */
6492
        var _toSettings = function ( mixed )
6493
        {
6494
                var idx, jq;
6495
                var settings = DataTable.settings;
6496
                var tables = $.map( settings, function (el, i) {
6497
                        return el.nTable;
6498
                } );
6499
 
6500
                if ( ! mixed ) {
6501
                        return [];
6502
                }
6503
                else if ( mixed.nTable && mixed.oApi ) {
6504
                        // DataTables settings object
6505
                        return [ mixed ];
6506
                }
6507
                else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) {
6508
                        // Table node
6509
                        idx = $.inArray( mixed, tables );
6510
                        return idx !== -1 ? [ settings[idx] ] : null;
6511
                }
6512
                else if ( mixed && typeof mixed.settings === 'function' ) {
6513
                        return mixed.settings().toArray();
6514
                }
6515
                else if ( typeof mixed === 'string' ) {
6516
                        // jQuery selector
6517
                        jq = $(mixed);
6518
                }
6519
                else if ( mixed instanceof $ ) {
6520
                        // jQuery object (also DataTables instance)
6521
                        jq = mixed;
6522
                }
6523
 
6524
                if ( jq ) {
6525
                        return jq.map( function(i) {
6526
                                idx = $.inArray( this, tables );
6527
                                return idx !== -1 ? settings[idx] : null;
6528
                        } ).toArray();
6529
                }
6530
        };
6531
 
6532
 
6533
        /**
6534
         * DataTables API class - used to control and interface with  one or more
6535
         * DataTables enhanced tables.
6536
         *
6537
         * The API class is heavily based on jQuery, presenting a chainable interface
6538
         * that you can use to interact with tables. Each instance of the API class has
6539
         * a "context" - i.e. the tables that it will operate on. This could be a single
6540
         * table, all tables on a page or a sub-set thereof.
6541
         *
6542
         * Additionally the API is designed to allow you to easily work with the data in
6543
         * the tables, retrieving and manipulating it as required. This is done by
6544
         * presenting the API class as an array like interface. The contents of the
6545
         * array depend upon the actions requested by each method (for example
6546
         * `rows().nodes()` will return an array of nodes, while `rows().data()` will
6547
         * return an array of objects or arrays depending upon your table's
6548
         * configuration). The API object has a number of array like methods (`push`,
6549
         * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`,
6550
         * `unique` etc) to assist your working with the data held in a table.
6551
         *
6552
         * Most methods (those which return an Api instance) are chainable, which means
6553
         * the return from a method call also has all of the methods available that the
6554
         * top level object had. For example, these two calls are equivalent:
6555
         *
6556
         *     // Not chained
6557
         *     api.row.add( {...} );
6558
         *     api.draw();
6559
         *
6560
         *     // Chained
6561
         *     api.row.add( {...} ).draw();
6562
         *
6563
         * @class DataTable.Api
6564
         * @param {array|object|string|jQuery} context DataTable identifier. This is
6565
         *   used to define which DataTables enhanced tables this API will operate on.
6566
         *   Can be one of:
6567
         *
6568
         *   * `string` - jQuery selector. Any DataTables' matching the given selector
6569
         *     with be found and used.
6570
         *   * `node` - `TABLE` node which has already been formed into a DataTable.
6571
         *   * `jQuery` - A jQuery object of `TABLE` nodes.
6572
         *   * `object` - DataTables settings object
6573
         * @param {array} [data] Data to initialise the Api instance with.
6574
         *
6575
         * @example
6576
         *   // Direct initialisation during DataTables construction
6577
         *   var api = $('#example').DataTable();
6578
         *
6579
         * @example
6580
         *   // Initialisation using a DataTables jQuery object
6581
         *   var api = $('#example').dataTable().api();
6582
         *
6583
         * @example
6584
         *   // Initialisation as a constructor
6585
         *   var api = new $.fn.DataTable.Api( 'table.dataTable' );
6586
         */
6587
        _Api = function ( context, data )
6588
        {
6589
                if ( ! this instanceof _Api ) {
6590
                        throw 'DT API must be constructed as a new object';
6591
                        // or should it do the 'new' for the caller?
6592
                        // return new _Api.apply( this, arguments );
6593
                }
6594
 
6595
                var settings = [];
6596
                var ctxSettings = function ( o ) {
6597
                        var a = _toSettings( o );
6598
                        if ( a ) {
6599
                                settings.push.apply( settings, a );
6600
                        }
6601
                };
6602
 
6603
                if ( $.isArray( context ) ) {
6604
                        for ( var i=0, ien=context.length ; i<ien ; i++ ) {
6605
                                ctxSettings( context[i] );
6606
                        }
6607
                }
6608
                else {
6609
                        ctxSettings( context );
6610
                }
6611
 
6612
                // Remove duplicates
6613
                this.context = _unique( settings );
6614
 
6615
                // Initial data
6616
                if ( data ) {
6617
                        this.push.apply( this, data.toArray ? data.toArray() : data );
6618
                }
6619
 
6620
                // selector
6621
                this.selector = {
6622
                        rows: null,
6623
                        cols: null,
6624
                        opts: null
6625
                };
6626
 
6627
                _Api.extend( this, this, __apiStruct );
6628
        };
6629
 
6630
        DataTable.Api = _Api;
6631
 
6632
        _Api.prototype = /** @lends DataTables.Api */{
6633
                /**
6634
                 * Return a new Api instance, comprised of the data held in the current
6635
                 * instance, join with the other array(s) and/or value(s).
6636
                 *
6637
                 * An alias for `Array.prototype.concat`.
6638
                 *
6639
                 * @type method
6640
                 * @param {*} value1 Arrays and/or values to concatenate.
6641
                 * @param {*} [...] Additional arrays and/or values to concatenate.
6642
                 * @returns {DataTables.Api} New API instance, comprising of the combined
6643
                 *   array.
6644
                 */
6645
                concat:  __arrayProto.concat,
6646
 
6647
 
6648
                context: [], // array of table settings objects
6649
 
6650
 
6651
                each: function ( fn )
6652
                {
6653
                        for ( var i=0, ien=this.length ; i<ien; i++ ) {
6654
                                fn.call( this, this[i], i, this );
6655
                        }
6656
 
6657
                        return this;
6658
                },
6659
 
6660
 
6661
                eq: function ( idx )
6662
                {
6663
                        var ctx = this.context;
6664
 
6665
                        return ctx.length > idx ?
6666
                                new _Api( ctx[idx], this[idx] ) :
6667
                                null;
6668
                },
6669
 
6670
 
6671
                filter: function ( fn )
6672
                {
6673
                        var a = [];
6674
 
6675
                        if ( __arrayProto.filter ) {
6676
                                a = __arrayProto.filter.call( this, fn, this );
6677
                        }
6678
                        else {
6679
                                // Compatibility for browsers without EMCA-252-5 (JS 1.6)
6680
                                for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6681
                                        if ( fn.call( this, this[i], i, this ) ) {
6682
                                                a.push( this[i] );
6683
                                        }
6684
                                }
6685
                        }
6686
 
6687
                        return new _Api( this.context, a );
6688
                },
6689
 
6690
 
6691
                flatten: function ()
6692
                {
6693
                        var a = [];
6694
                        return new _Api( this.context, a.concat.apply( a, this.toArray() ) );
6695
                },
6696
 
6697
 
6698
                join:    __arrayProto.join,
6699
 
6700
 
6701
                indexOf: __arrayProto.indexOf || function (obj, start)
6702
                {
6703
                        for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) {
6704
                                if ( this[i] === obj ) {
6705
                                        return i;
6706
                                }
6707
                        }
6708
                        return -1;
6709
                },
6710
 
6711
                // Internal only at the moment - relax?
6712
                iterator: function ( flatten, type, fn ) {
6713
                        var
6714
                                a = [], ret,
6715
                                i, ien, j, jen,
6716
                                context = this.context,
6717
                                rows, items, item,
6718
                                selector = this.selector;
6719
 
6720
                        // Argument shifting
6721
                        if ( typeof flatten === 'string' ) {
6722
                                fn = type;
6723
                                type = flatten;
6724
                                flatten = false;
6725
                        }
6726
 
6727
                        for ( i=0, ien=context.length ; i<ien ; i++ ) {
6728
                                if ( type === 'table' ) {
6729
                                        ret = fn( context[i], i );
6730
 
6731
                                        if ( ret !== undefined ) {
6732
                                                a.push( ret );
6733
                                        }
6734
                                }
6735
                                else if ( type === 'columns' || type === 'rows' ) {
6736
                                        // this has same length as context - one entry for each table
6737
                                        ret = fn( context[i], this[i], i );
6738
 
6739
                                        if ( ret !== undefined ) {
6740
                                                a.push( ret );
6741
                                        }
6742
                                }
6743
                                else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) {
6744
                                        // columns and rows share the same structure.
6745
                                        // 'this' is an array of column indexes for each context
6746
                                        items = this[i];
6747
 
6748
                                        if ( type === 'column-rows' ) {
6749
                                                rows = _selector_row_indexes( context[i], selector.opts );
6750
                                        }
6751
 
6752
                                        for ( j=0, jen=items.length ; j<jen ; j++ ) {
6753
                                                item = items[j];
6754
 
6755
                                                if ( type === 'cell' ) {
6756
                                                        ret = fn( context[i], item.row, item.column, i, j );
6757
                                                }
6758
                                                else {
6759
                                                        ret = fn( context[i], item, i, j, rows );
6760
                                                }
6761
 
6762
                                                if ( ret !== undefined ) {
6763
                                                        a.push( ret );
6764
                                                }
6765
                                        }
6766
                                }
6767
                        }
6768
 
6769
                        if ( a.length ) {
6770
                                var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a );
6771
                                var apiSelector = api.selector;
6772
                                apiSelector.rows = selector.rows;
6773
                                apiSelector.cols = selector.cols;
6774
                                apiSelector.opts = selector.opts;
6775
                                return api;
6776
                        }
6777
                        return this;
6778
                },
6779
 
6780
 
6781
                lastIndexOf: __arrayProto.lastIndexOf || function (obj, start)
6782
                {
6783
                        // Bit cheeky...
6784
                        return this.indexOf.apply( this.toArray.reverse(), arguments );
6785
                },
6786
 
6787
 
6788
                length:  0,
6789
 
6790
 
6791
                map: function ( fn )
6792
                {
6793
                        var a = [];
6794
 
6795
                        if ( __arrayProto.map ) {
6796
                                a = __arrayProto.map.call( this, fn, this );
6797
                        }
6798
                        else {
6799
                                // Compatibility for browsers without EMCA-252-5 (JS 1.6)
6800
                                for ( var i=0, ien=this.length ; i<ien ; i++ ) {
6801
                                        a.push( fn.call( this, this[i], i ) );
6802
                                }
6803
                        }
6804
 
6805
                        return new _Api( this.context, a );
6806
                },
6807
 
6808
 
6809
                pluck: function ( prop )
6810
                {
6811
                        return this.map( function ( el ) {
6812
                                return el[ prop ];
6813
                        } );
6814
                },
6815
 
6816
                pop:     __arrayProto.pop,
6817
 
6818
 
6819
                push:    __arrayProto.push,
6820
 
6821
 
6822
                // Does not return an API instance
6823
                reduce: __arrayProto.reduce || function ( fn, init )
6824
                {
6825
                        return _fnReduce( this, fn, init, 0, this.length, 1 );
6826
                },
6827
 
6828
 
6829
                reduceRight: __arrayProto.reduceRight || function ( fn, init )
6830
                {
6831
                        return _fnReduce( this, fn, init, this.length-1, -1, -1 );
6832
                },
6833
 
6834
 
6835
                reverse: __arrayProto.reverse,
6836
 
6837
 
6838
                // Object with rows, columns and opts
6839
                selector: null,
6840
 
6841
 
6842
                shift:   __arrayProto.shift,
6843
 
6844
 
6845
                sort:    __arrayProto.sort, // ? name - order?
6846
 
6847
 
6848
                splice:  __arrayProto.splice,
6849
 
6850
 
6851
                toArray: function ()
6852
                {
6853
                        return __arrayProto.slice.call( this );
6854
                },
6855
 
6856
 
6857
                to$: function ()
6858
                {
6859
                        return $( this );
6860
                },
6861
 
6862
 
6863
                toJQuery: function ()
6864
                {
6865
                        return $( this );
6866
                },
6867
 
6868
 
6869
                unique: function ()
6870
                {
6871
                        return new _Api( this.context, _unique(this) );
6872
                },
6873
 
6874
 
6875
                unshift: __arrayProto.unshift
6876
        };
6877
 
6878
 
6879
        _Api.extend = function ( scope, obj, ext )
6880
        {
6881
                // Only extend API instances and static properties of the API
6882
                if ( ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) {
6883
                        return;
6884
                }
6885
 
6886
                var
6887
                        i, ien,
6888
                        j, jen,
6889
                        struct, inner,
6890
                        methodScoping = function ( scope, fn, struc ) {
6891
                                return function () {
6892
                                        var ret = fn.apply( scope, arguments );
6893
 
6894
                                        // Method extension
6895
                                        _Api.extend( ret, ret, struc.methodExt );
6896
                                        return ret;
6897
                                };
6898
                        };
6899
 
6900
                for ( i=0, ien=ext.length ; i<ien ; i++ ) {
6901
                        struct = ext[i];
6902
 
6903
                        // Value
6904
                        obj[ struct.name ] = typeof struct.val === 'function' ?
6905
                                methodScoping( scope, struct.val, struct ) :
6906
                                $.isPlainObject( struct.val ) ?
6907
                                        {} :
6908
                                        struct.val;
6909
 
6910
                        obj[ struct.name ].__dt_wrapper = true;
6911
 
6912
                        // Property extension
6913
                        _Api.extend( scope, obj[ struct.name ], struct.propExt );
6914
                }
6915
        };
6916
 
6917
 
6918
        // @todo - Is there need for an augment function?
6919
        // _Api.augment = function ( inst, name )
6920
        // {
6921
        //      // Find src object in the structure from the name
6922
        //      var parts = name.split('.');
6923
 
6924
        //      _Api.extend( inst, obj );
6925
        // };
6926
 
6927
 
6928
        //     [
6929
        //       {
6930
        //         name:      'data'                -- string   - Property name
6931
        //         val:       function () {},       -- function - Api method (or undefined if just an object
6932
        //         methodExt: [ ... ],              -- array    - Array of Api object definitions to extend the method result
6933
        //         propExt:   [ ... ]               -- array    - Array of Api object definitions to extend the property
6934
        //       },
6935
        //       {
6936
        //         name:     'row'
6937
        //         val:       {},
6938
        //         methodExt: [ ... ],
6939
        //         propExt:   [
6940
        //           {
6941
        //             name:      'data'
6942
        //             val:       function () {},
6943
        //             methodExt: [ ... ],
6944
        //             propExt:   [ ... ]
6945
        //           },
6946
        //           ...
6947
        //         ]
6948
        //       }
6949
        //     ]
6950
 
6951
        _Api.register = _api_register = function ( name, val )
6952
        {
6953
                if ( $.isArray( name ) ) {
6954
                        for ( var j=0, jen=name.length ; j<jen ; j++ ) {
6955
                                _Api.register( name[j], val );
6956
                        }
6957
                        return;
6958
                }
6959
 
6960
                var
6961
                        i, ien,
6962
                        heir = name.split('.'),
6963
                        struct = __apiStruct,
6964
                        key, method;
6965
 
6966
                var find = function ( src, name ) {
6967
                        for ( var i=0, ien=src.length ; i<ien ; i++ ) {
6968
                                if ( src[i].name === name ) {
6969
                                        return src[i];
6970
                                }
6971
                        }
6972
                        return null;
6973
                };
6974
 
6975
                for ( i=0, ien=heir.length ; i<ien ; i++ ) {
6976
                        method = heir[i].indexOf('()') !== -1;
6977
                        key = method ?
6978
                                heir[i].replace('()', '') :
6979
                                heir[i];
6980
 
6981
                        var src = find( struct, key );
6982
                        if ( ! src ) {
6983
                                src = {
6984
                                        name:      key,
6985
                                        val:       {},
6986
                                        methodExt: [],
6987
                                        propExt:   []
6988
                                };
6989
                                struct.push( src );
6990
                        }
6991
 
6992
                        if ( i === ien-1 ) {
6993
                                src.val = val;
6994
                        }
6995
                        else {
6996
                                struct = method ?
6997
                                        src.methodExt :
6998
                                        src.propExt;
6999
                        }
7000
                }
7001
        };
7002
 
7003
 
7004
        _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) {
7005
                _Api.register( pluralName, val );
7006
 
7007
                _Api.register( singularName, function () {
7008
                        var ret = val.apply( this, arguments );
7009
 
7010
                        if ( ret === this ) {
7011
                                // Returned item is the API instance that was passed in, return it
7012
                                return this;
7013
                        }
7014
                        else if ( ret instanceof _Api ) {
7015
                                // New API instance returned, want the value from the first item
7016
                                // in the returned array for the singular result.
7017
                                return ret.length ?
7018
                                        $.isArray( ret[0] ) ?
7019
                                                new _Api( ret.context, ret[0] ) : // Array results are 'enhanced'
7020
                                                ret[0] :
7021
                                        undefined;
7022
                        }
7023
 
7024
                        // Non-API return - just fire it back
7025
                        return ret;
7026
                } );
7027
        };
7028
 
7029
 
7030
        /**
7031
         * Selector for HTML tables. Apply the given selector to the give array of
7032
         * DataTables settings objects.
7033
         *
7034
         * @param {string|integer} [selector] jQuery selector string or integer
7035
         * @param  {array} Array of DataTables settings objects to be filtered
7036
         * @return {array}
7037
         * @ignore
7038
         */
7039
        var __table_selector = function ( selector, a )
7040
        {
7041
                // Integer is used to pick out a table by index
7042
                if ( typeof selector === 'number' ) {
7043
                        return [ a[ selector ] ];
7044
                }
7045
 
7046
                // Perform a jQuery selector on the table nodes
7047
                var nodes = $.map( a, function (el, i) {
7048
                        return el.nTable;
7049
                } );
7050
 
7051
                return $(nodes)
7052
                        .filter( selector )
7053
                        .map( function (i) {
7054
                                // Need to translate back from the table node to the settings
7055
                                var idx = $.inArray( this, nodes );
7056
                                return a[ idx ];
7057
                        } )
7058
                        .toArray();
7059
        };
7060
 
7061
 
7062
 
7063
        /**
7064
         * Context selector for the API's context (i.e. the tables the API instance
7065
         * refers to.
7066
         *
7067
         * @name    DataTable.Api#tables
7068
         * @param {string|integer} [selector] Selector to pick which tables the iterator
7069
         *   should operate on. If not given, all tables in the current context are
7070
         *   used. This can be given as a jQuery selector (for example `':gt(0)'`) to
7071
         *   select multiple tables or as an integer to select a single table.
7072
         * @returns {DataTable.Api} Returns a new API instance if a selector is given.
7073
         */
7074
        _api_register( 'tables()', function ( selector ) {
7075
                // A new instance is created if there was a selector specified
7076
                return selector ?
7077
                        new _Api( __table_selector( selector, this.context ) ) :
7078
                        this;
7079
        } );
7080
 
7081
 
7082
        _api_register( 'table()', function ( selector ) {
7083
                var tables = this.tables( selector );
7084
                var ctx = tables.context;
7085
 
7086
                // Truncate to the first matched table
7087
                return ctx.length ?
7088
                        new _Api( ctx[0] ) :
7089
                        tables;
7090
        } );
7091
 
7092
 
7093
        _api_registerPlural( 'tables().nodes()', 'table().node()' , function () {
7094
                return this.iterator( 'table', function ( ctx ) {
7095
                        return ctx.nTable;
7096
                } );
7097
        } );
7098
 
7099
 
7100
        _api_registerPlural( 'tables().body()', 'table().body()' , function () {
7101
                return this.iterator( 'table', function ( ctx ) {
7102
                        return ctx.nTBody;
7103
                } );
7104
        } );
7105
 
7106
 
7107
        _api_registerPlural( 'tables().header()', 'table().header()' , function () {
7108
                return this.iterator( 'table', function ( ctx ) {
7109
                        return ctx.nTHead;
7110
                } );
7111
        } );
7112
 
7113
 
7114
        _api_registerPlural( 'tables().footer()', 'table().footer()' , function () {
7115
                return this.iterator( 'table', function ( ctx ) {
7116
                        return ctx.nTFoot;
7117
                } );
7118
        } );
7119
 
7120
 
7121
        _api_registerPlural( 'tables().containers()', 'table().container()' , function () {
7122
                return this.iterator( 'table', function ( ctx ) {
7123
                        return ctx.nTableWrapper;
7124
                } );
7125
        } );
7126
 
7127
 
7128
 
7129
        /**
7130
         * Redraw the tables in the current context.
7131
         *
7132
         * @param {boolean} [reset=true] Reset (default) or hold the current paging
7133
         *   position. A full re-sort and re-filter is performed when this method is
7134
         *   called, which is why the pagination reset is the default action.
7135
         * @returns {DataTables.Api} this
7136
         */
7137
        _api_register( 'draw()', function ( resetPaging ) {
7138
                return this.iterator( 'table', function ( settings ) {
7139
                        _fnReDraw( settings, resetPaging===false );
7140
                } );
7141
        } );
7142
 
7143
 
7144
 
7145
        /**
7146
         * Get the current page index.
7147
         *
7148
         * @return {integer} Current page index (zero based)
7149
         *//**
7150
         * Set the current page.
7151
         *
7152
         * Note that if you attempt to show a page which does not exist, DataTables will
7153
         * not throw an error, but rather reset the paging.
7154
         *
7155
         * @param {integer|string} action The paging action to take. This can be one of:
7156
         *  * `integer` - The page index to jump to
7157
         *  * `string` - An action to take:
7158
         *    * `first` - Jump to first page.
7159
         *    * `next` - Jump to the next page
7160
         *    * `previous` - Jump to previous page
7161
         *    * `last` - Jump to the last page.
7162
         * @returns {DataTables.Api} this
7163
         */
7164
        _api_register( 'page()', function ( action ) {
7165
                if ( action === undefined ) {
7166
                        return this.page.info().page; // not an expensive call
7167
                }
7168
 
7169
                // else, have an action to take on all tables
7170
                return this.iterator( 'table', function ( settings ) {
7171
                        _fnPageChange( settings, action );
7172
                } );
7173
        } );
7174
 
7175
 
7176
        /**
7177
         * Paging information for the first table in the current context.
7178
         *
7179
         * If you require paging information for another table, use the `table()` method
7180
         * with a suitable selector.
7181
         *
7182
         * @return {object} Object with the following properties set:
7183
         *  * `page` - Current page index (zero based - i.e. the first page is `0`)
7184
         *  * `pages` - Total number of pages
7185
         *  * `start` - Display index for the first record shown on the current page
7186
         *  * `end` - Display index for the last record shown on the current page
7187
         *  * `length` - Display length (number of records). Note that generally `start
7188
         *    + length = end`, but this is not always true, for example if there are
7189
         *    only 2 records to show on the final page, with a length of 10.
7190
         *  * `recordsTotal` - Full data set length
7191
         *  * `recordsDisplay` - Data set length once the current filtering criterion
7192
         *    are applied.
7193
         */
7194
        _api_register( 'page.info()', function ( action ) {
7195
                if ( this.context.length === 0 ) {
7196
                        return undefined;
7197
                }
7198
 
7199
                var
7200
                        settings   = this.context[0],
7201
                        start      = settings._iDisplayStart,
7202
                        len        = settings._iDisplayLength,
7203
                        visRecords = settings.fnRecordsDisplay(),
7204
                        all        = len === -1;
7205
 
7206
                return {
7207
                        "page":           all ? 0 : Math.floor( start / len ),
7208
                        "pages":          all ? 1 : Math.ceil( visRecords / len ),
7209
                        "start":          start,
7210
                        "end":            settings.fnDisplayEnd(),
7211
                        "length":         len,
7212
                        "recordsTotal":   settings.fnRecordsTotal(),
7213
                        "recordsDisplay": visRecords
7214
                };
7215
        } );
7216
 
7217
 
7218
        /**
7219
         * Get the current page length.
7220
         *
7221
         * @return {integer} Current page length. Note `-1` indicates that all records
7222
         *   are to be shown.
7223
         *//**
7224
         * Set the current page length.
7225
         *
7226
         * @param {integer} Page length to set. Use `-1` to show all records.
7227
         * @returns {DataTables.Api} this
7228
         */
7229
        _api_register( 'page.len()', function ( len ) {
7230
                // Note that we can't call this function 'length()' because `length`
7231
                // is a Javascript property of functions which defines how many arguments
7232
                // the function expects.
7233
                if ( len === undefined ) {
7234
                        return this.context.length !== 0 ?
7235
                                this.context[0]._iDisplayLength :
7236
                                undefined;
7237
                }
7238
 
7239
                // else, set the page length
7240
                return this.iterator( 'table', function ( settings ) {
7241
                        _fnLengthChange( settings, len );
7242
                } );
7243
        } );
7244
 
7245
 
7246
 
7247
        var __reload = function ( settings, holdPosition, callback ) {
7248
                if ( _fnDataSource( settings ) == 'ssp' ) {
7249
                        _fnReDraw( settings, holdPosition );
7250
                }
7251
                else {
7252
                        // Trigger xhr
7253
                        _fnProcessingDisplay( settings, true );
7254
 
7255
                        _fnBuildAjax( settings, [], function( json ) {
7256
                                _fnClearTable( settings );
7257
 
7258
                                var data = _fnAjaxDataSrc( settings, json );
7259
                                for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7260
                                        _fnAddData( settings, data[i] );
7261
                                }
7262
 
7263
                                _fnReDraw( settings, holdPosition );
7264
                                _fnProcessingDisplay( settings, false );
7265
                        } );
7266
                }
7267
 
7268
                // Use the draw event to trigger a callback, regardless of if it is an async
7269
                // or sync draw
7270
                if ( callback ) {
7271
                        var api = new _Api( settings );
7272
 
7273
                        api.one( 'draw', function () {
7274
                                callback( api.ajax.json() );
7275
                        } );
7276
                }
7277
        };
7278
 
7279
 
7280
        /**
7281
         * Get the JSON response from the last Ajax request that DataTables made to the
7282
         * server. Note that this returns the JSON from the first table in the current
7283
         * context.
7284
         *
7285
         * @return {object} JSON received from the server.
7286
         */
7287
        _api_register( 'ajax.json()', function () {
7288
                var ctx = this.context;
7289
 
7290
                if ( ctx.length > 0 ) {
7291
                        return ctx[0].json;
7292
                }
7293
 
7294
                // else return undefined;
7295
        } );
7296
 
7297
 
7298
        /**
7299
         * Get the data submitted in the last Ajax request
7300
         */
7301
        _api_register( 'ajax.params()', function () {
7302
                var ctx = this.context;
7303
 
7304
                if ( ctx.length > 0 ) {
7305
                        return ctx[0].oAjaxData;
7306
                }
7307
 
7308
                // else return undefined;
7309
        } );
7310
 
7311
 
7312
        /**
7313
         * Reload tables from the Ajax data source. Note that this function will
7314
         * automatically re-draw the table when the remote data has been loaded.
7315
         *
7316
         * @param {boolean} [reset=true] Reset (default) or hold the current paging
7317
         *   position. A full re-sort and re-filter is performed when this method is
7318
         *   called, which is why the pagination reset is the default action.
7319
         * @returns {DataTables.Api} this
7320
         */
7321
        _api_register( 'ajax.reload()', function ( callback, resetPaging ) {
7322
                return this.iterator( 'table', function (settings) {
7323
                        __reload( settings, resetPaging===false, callback );
7324
                } );
7325
        } );
7326
 
7327
 
7328
        /**
7329
         * Get the current Ajax URL. Note that this returns the URL from the first
7330
         * table in the current context.
7331
         *
7332
         * @return {string} Current Ajax source URL
7333
         *//**
7334
         * Set the Ajax URL. Note that this will set the URL for all tables in the
7335
         * current context.
7336
         *
7337
         * @param {string} url URL to set.
7338
         * @returns {DataTables.Api} this
7339
         */
7340
        _api_register( 'ajax.url()', function ( url ) {
7341
                var ctx = this.context;
7342
 
7343
                if ( url === undefined ) {
7344
                        // get
7345
                        if ( ctx.length === 0 ) {
7346
                                return undefined;
7347
                        }
7348
                        ctx = ctx[0];
7349
 
7350
                        return ctx.ajax ?
7351
                                $.isPlainObject( ctx.ajax ) ?
7352
                                        ctx.ajax.url :
7353
                                        ctx.ajax :
7354
                                ctx.sAjaxSource;
7355
                }
7356
 
7357
                // set
7358
                return this.iterator( 'table', function ( settings ) {
7359
                        if ( $.isPlainObject( settings.ajax ) ) {
7360
                                settings.ajax.url = url;
7361
                        }
7362
                        else {
7363
                                settings.ajax = url;
7364
                        }
7365
                        // No need to consider sAjaxSource here since DataTables gives priority
7366
                        // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any
7367
                        // value of `sAjaxSource` redundant.
7368
                } );
7369
        } );
7370
 
7371
 
7372
        /**
7373
         * Load data from the newly set Ajax URL. Note that this method is only
7374
         * available when `ajax.url()` is used to set a URL. Additionally, this method
7375
         * has the same effect as calling `ajax.reload()` but is provided for
7376
         * convenience when setting a new URL. Like `ajax.reload()` it will
7377
         * automatically redraw the table once the remote data has been loaded.
7378
         *
7379
         * @returns {DataTables.Api} this
7380
         */
7381
        _api_register( 'ajax.url().load()', function ( callback, resetPaging ) {
7382
                // Same as a reload, but makes sense to present it for easy access after a
7383
                // url change
7384
                return this.iterator( 'table', function ( ctx ) {
7385
                        __reload( ctx, resetPaging===false, callback );
7386
                } );
7387
        } );
7388
 
7389
 
7390
 
7391
 
7392
        var _selector_run = function ( selector, select )
7393
        {
7394
                var
7395
                        out = [], res,
7396
                        a, i, ien, j, jen;
7397
 
7398
                // Can't just check for isArray here, as an API or jQuery instance might be
7399
                // given with their array like look
7400
                if ( ! selector || typeof selector === 'string' || selector.length === undefined ) {
7401
                        selector = [ selector ];
7402
                }
7403
 
7404
                for ( i=0, ien=selector.length ; i<ien ; i++ ) {
7405
                        a = selector[i] && selector[i].split ?
7406
                                selector[i].split(',') :
7407
                                [ selector[i] ];
7408
 
7409
                        for ( j=0, jen=a.length ; j<jen ; j++ ) {
7410
                                res = select( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] );
7411
 
7412
                                if ( res && res.length ) {
7413
                                        out.push.apply( out, res );
7414
                                }
7415
                        }
7416
                }
7417
 
7418
                return out;
7419
        };
7420
 
7421
 
7422
        var _selector_opts = function ( opts )
7423
        {
7424
                if ( ! opts ) {
7425
                        opts = {};
7426
                }
7427
 
7428
                // Backwards compatibility for 1.9- which used the terminology filter rather
7429
                // than search
7430
                if ( opts.filter && ! opts.search ) {
7431
                        opts.search = opts.filter;
7432
                }
7433
 
7434
                return {
7435
                        search: opts.search || 'none',
7436
                        order:  opts.order  || 'current',
7437
                        page:   opts.page   || 'all'
7438
                };
7439
        };
7440
 
7441
 
7442
        var _selector_first = function ( inst )
7443
        {
7444
                // Reduce the API instance to the first item found
7445
                for ( var i=0, ien=inst.length ; i<ien ; i++ ) {
7446
                        if ( inst[i].length > 0 ) {
7447
                                // Assign the first element to the first item in the instance
7448
                                // and truncate the instance and context
7449
                                inst[0] = inst[i];
7450
                                inst.length = 1;
7451
                                inst.context = [ inst.context[i] ];
7452
 
7453
                                return inst;
7454
                        }
7455
                }
7456
 
7457
                // Not found - return an empty instance
7458
                inst.length = 0;
7459
                return inst;
7460
        };
7461
 
7462
 
7463
        var _selector_row_indexes = function ( settings, opts )
7464
        {
7465
                var
7466
                        i, ien, tmp, a=[],
7467
                        displayFiltered = settings.aiDisplay,
7468
                        displayMaster = settings.aiDisplayMaster;
7469
 
7470
                var
7471
                        search = opts.search,  // none, applied, removed
7472
                        order  = opts.order,   // applied, current, index (original - compatibility with 1.9)
7473
                        page   = opts.page;    // all, current
7474
 
7475
                if ( _fnDataSource( settings ) == 'ssp' ) {
7476
                        // In server-side processing mode, most options are irrelevant since
7477
                        // rows not shown don't exist and the index order is the applied order
7478
                        // Removed is a special case - for consistency just return an empty
7479
                        // array
7480
                        return search === 'removed' ?
7481
                                [] :
7482
                                _range( 0, displayMaster.length );
7483
                }
7484
                else if ( page == 'current' ) {
7485
                        // Current page implies that order=current and fitler=applied, since it is
7486
                        // fairly senseless otherwise, regardless of what order and search actually
7487
                        // are
7488
                        for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) {
7489
                                a.push( displayFiltered[i] );
7490
                        }
7491
                }
7492
                else if ( order == 'current' || order == 'applied' ) {
7493
                        a = search == 'none' ?
7494
                                displayMaster.slice() :                      // no search
7495
                                search == 'applied' ?
7496
                                        displayFiltered.slice() :                // applied search
7497
                                        $.map( displayMaster, function (el, i) { // removed search
7498
                                                return $.inArray( el, displayFiltered ) === -1 ? el : null;
7499
                                        } );
7500
                }
7501
                else if ( order == 'index' || order == 'original' ) {
7502
                        for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) {
7503
                                if ( search == 'none' ) {
7504
                                        a.push( i );
7505
                                }
7506
                                else { // applied | removed
7507
                                        tmp = $.inArray( i, displayFiltered );
7508
 
7509
                                        if ((tmp === -1 && search == 'removed') ||
7510
                                                (tmp >= 0   && search == 'applied') )
7511
                                        {
7512
                                                a.push( i );
7513
                                        }
7514
                                }
7515
                        }
7516
                }
7517
 
7518
                return a;
7519
        };
7520
 
7521
 
7522
        /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7523
         * Rows
7524
         *
7525
         * {}          - no selector - use all available rows
7526
         * {integer}   - row aoData index
7527
         * {node}      - TR node
7528
         * {string}    - jQuery selector to apply to the TR elements
7529
         * {array}     - jQuery array of nodes, or simply an array of TR nodes
7530
         *
7531
         */
7532
 
7533
 
7534
        var __row_selector = function ( settings, selector, opts )
7535
        {
7536
                return _selector_run( selector, function ( sel ) {
7537
                        var selInt = _intVal( sel );
7538
 
7539
                        // Short cut - selector is a number and no options provided (default is
7540
                        // all records, so no need to check if the index is in there, since it
7541
                        // must be - dev error if the index doesn't exist).
7542
                        if ( selInt !== null && ! opts ) {
7543
                                return [ selInt ];
7544
                        }
7545
 
7546
                        var rows = _selector_row_indexes( settings, opts );
7547
 
7548
                        if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) {
7549
                                // Selector - integer
7550
                                return [ selInt ];
7551
                        }
7552
                        else if ( ! sel ) {
7553
                                // Selector - none
7554
                                return rows;
7555
                        }
7556
 
7557
                        // Get nodes in the order from the `rows` array (can't use `pluck`) @todo - use pluck_order
7558
                        var nodes = [];
7559
                        for ( var i=0, ien=rows.length ; i<ien ; i++ ) {
7560
                                nodes.push( settings.aoData[ rows[i] ].nTr );
7561
                        }
7562
 
7563
                        if ( sel.nodeName ) {
7564
                                // Selector - node
7565
                                if ( $.inArray( sel, nodes ) !== -1 ) {
7566
                                        return [ sel._DT_RowIndex ];// sel is a TR node that is in the table
7567
                                                                                        // and DataTables adds a prop for fast lookup
7568
                                }
7569
                        }
7570
 
7571
                        // Selector - jQuery selector string, array of nodes or jQuery object/
7572
                        // As jQuery's .filter() allows jQuery objects to be passed in filter,
7573
                        // it also allows arrays, so this will cope with all three options
7574
                        return $(nodes)
7575
                                .filter( sel )
7576
                                .map( function () {
7577
                                        return this._DT_RowIndex;
7578
                                } )
7579
                                .toArray();
7580
                } );
7581
        };
7582
 
7583
 
7584
        /**
7585
         *
7586
         */
7587
        _api_register( 'rows()', function ( selector, opts ) {
7588
                // argument shifting
7589
                if ( selector === undefined ) {
7590
                        selector = '';
7591
                }
7592
                else if ( $.isPlainObject( selector ) ) {
7593
                        opts = selector;
7594
                        selector = '';
7595
                }
7596
 
7597
                opts = _selector_opts( opts );
7598
 
7599
                var inst = this.iterator( 'table', function ( settings ) {
7600
                        return __row_selector( settings, selector, opts );
7601
                } );
7602
 
7603
                // Want argument shifting here and in __row_selector?
7604
                inst.selector.rows = selector;
7605
                inst.selector.opts = opts;
7606
 
7607
                return inst;
7608
        } );
7609
 
7610
 
7611
        _api_register( 'rows().nodes()', function () {
7612
                return this.iterator( 'row', function ( settings, row ) {
7613
                        return settings.aoData[ row ].nTr || undefined;
7614
                } );
7615
        } );
7616
 
7617
        _api_register( 'rows().data()', function () {
7618
                return this.iterator( true, 'rows', function ( settings, rows ) {
7619
                        return _pluck_order( settings.aoData, rows, '_aData' );
7620
                } );
7621
        } );
7622
 
7623
        _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) {
7624
                return this.iterator( 'row', function ( settings, row ) {
7625
                        var r = settings.aoData[ row ];
7626
                        return type === 'search' ? r._aFilterData : r._aSortData;
7627
                } );
7628
        } );
7629
 
7630
        _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) {
7631
                return this.iterator( 'row', function ( settings, row ) {
7632
                        _fnInvalidateRow( settings, row, src );
7633
                } );
7634
        } );
7635
 
7636
        _api_registerPlural( 'rows().indexes()', 'row().index()', function () {
7637
                return this.iterator( 'row', function ( settings, row ) {
7638
                        return row;
7639
                } );
7640
        } );
7641
 
7642
        _api_registerPlural( 'rows().remove()', 'row().remove()', function () {
7643
                var that = this;
7644
 
7645
                return this.iterator( 'row', function ( settings, row, thatIdx ) {
7646
                        var data = settings.aoData;
7647
 
7648
                        data.splice( row, 1 );
7649
 
7650
                        // Update the _DT_RowIndex parameter on all rows in the table
7651
                        for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7652
                                if ( data[i].nTr !== null ) {
7653
                                        data[i].nTr._DT_RowIndex = i;
7654
                                }
7655
                        }
7656
 
7657
                        // Remove the target row from the search array
7658
                        var displayIndex = $.inArray( row, settings.aiDisplay );
7659
 
7660
                        // Delete from the display arrays
7661
                        _fnDeleteIndex( settings.aiDisplayMaster, row );
7662
                        _fnDeleteIndex( settings.aiDisplay, row );
7663
                        _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes
7664
 
7665
                        // Check for an 'overflow' they case for displaying the table
7666
                        _fnLengthOverflow( settings );
7667
                } );
7668
        } );
7669
 
7670
 
7671
        _api_register( 'rows.add()', function ( rows ) {
7672
                var newRows = this.iterator( 'table', function ( settings ) {
7673
                                var row, i, ien;
7674
                                var out = [];
7675
 
7676
                                for ( i=0, ien=rows.length ; i<ien ; i++ ) {
7677
                                        row = rows[i];
7678
 
7679
                                        if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
7680
                                                out.push( _fnAddTr( settings, row )[0] );
7681
                                        }
7682
                                        else {
7683
                                                out.push( _fnAddData( settings, row ) );
7684
                                        }
7685
                                }
7686
 
7687
                                return out;
7688
                        } );
7689
 
7690
                // Return an Api.rows() extended instance, so rows().nodes() etc can be used
7691
                var modRows = this.rows( -1 );
7692
                modRows.pop();
7693
                modRows.push.apply( modRows, newRows.toArray() );
7694
 
7695
                return modRows;
7696
        } );
7697
 
7698
 
7699
 
7700
 
7701
 
7702
        /**
7703
         *
7704
         */
7705
        _api_register( 'row()', function ( selector, opts ) {
7706
                return _selector_first( this.rows( selector, opts ) );
7707
        } );
7708
 
7709
 
7710
        _api_register( 'row().data()', function ( data ) {
7711
                var ctx = this.context;
7712
 
7713
                if ( data === undefined ) {
7714
                        // Get
7715
                        return ctx.length && this.length ?
7716
                                ctx[0].aoData[ this[0] ]._aData :
7717
                                undefined;
7718
                }
7719
 
7720
                // Set
7721
                ctx[0].aoData[ this[0] ]._aData = data;
7722
 
7723
                // Automatically invalidate
7724
                _fnInvalidateRow( ctx[0], this[0], 'data' );
7725
 
7726
                return this;
7727
        } );
7728
 
7729
 
7730
        _api_register( 'row().node()', function () {
7731
                var ctx = this.context;
7732
 
7733
                return ctx.length && this.length ?
7734
                        ctx[0].aoData[ this[0] ].nTr || null :
7735
                        null;
7736
        } );
7737
 
7738
 
7739
        _api_register( 'row.add()', function ( row ) {
7740
                // Allow a jQuery object to be passed in - only a single row is added from
7741
                // it though - the first element in the set
7742
                if ( row instanceof $ && row.length ) {
7743
                        row = row[0];
7744
                }
7745
 
7746
                var rows = this.iterator( 'table', function ( settings ) {
7747
                        if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) {
7748
                                return _fnAddTr( settings, row )[0];
7749
                        }
7750
                        return _fnAddData( settings, row );
7751
                } );
7752
 
7753
                // Return an Api.rows() extended instance, with the newly added row selected
7754
                return this.row( rows[0] );
7755
        } );
7756
 
7757
 
7758
 
7759
        var __details_add = function ( ctx, row, data, klass )
7760
        {
7761
                // Convert to array of TR elements
7762
                var rows = [];
7763
                var addRow = function ( r, k ) {
7764
                        // If we get a TR element, then just add it directly - up to the dev
7765
                        // to add the correct number of columns etc
7766
                        if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) {
7767
                                rows.push( r );
7768
                        }
7769
                        else {
7770
                                // Otherwise create a row with a wrapper
7771
                                var created = $('<tr><td/></tr>').addClass( k );
7772
                                $('td', created)
7773
                                        .addClass( k )
7774
                                        .html( r )
7775
                                        [0].colSpan = _fnVisbleColumns( ctx );
7776
 
7777
                                rows.push( created[0] );
7778
                        }
7779
                };
7780
 
7781
                if ( $.isArray( data ) || data instanceof $ ) {
7782
                        for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7783
                                addRow( data[i], klass );
7784
                        }
7785
                }
7786
                else {
7787
                        addRow( data, klass );
7788
                }
7789
 
7790
                if ( row._details ) {
7791
                        row._details.remove();
7792
                }
7793
 
7794
                row._details = $(rows);
7795
 
7796
                // If the children were already shown, that state should be retained
7797
                if ( row._detailsShow ) {
7798
                        row._details.insertAfter( row.nTr );
7799
                }
7800
        };
7801
 
7802
 
7803
        var __details_remove = function ( api )
7804
        {
7805
                var ctx = api.context;
7806
 
7807
                if ( ctx.length && api.length ) {
7808
                        var row = ctx[0].aoData[ api[0] ];
7809
 
7810
                        if ( row._details ) {
7811
                                row._details.remove();
7812
 
7813
                                row._detailsShow = undefined;
7814
                                row._details = undefined;
7815
                        }
7816
                }
7817
        };
7818
 
7819
 
7820
        var __details_display = function ( api, show ) {
7821
                var ctx = api.context;
7822
 
7823
                if ( ctx.length && api.length ) {
7824
                        var row = ctx[0].aoData[ api[0] ];
7825
 
7826
                        if ( row._details ) {
7827
                                row._detailsShow = show;
7828
 
7829
                                if ( show ) {
7830
                                        row._details.insertAfter( row.nTr );
7831
                                }
7832
                                else {
7833
                                        row._details.detach();
7834
                                }
7835
 
7836
                                __details_events( ctx[0] );
7837
                        }
7838
                }
7839
        };
7840
 
7841
 
7842
        var __details_events = function ( settings )
7843
        {
7844
                var api = new _Api( settings );
7845
                var namespace = '.dt.DT_details';
7846
                var drawEvent = 'draw'+namespace;
7847
                var colvisEvent = 'column-visibility'+namespace;
7848
                var destroyEvent = 'destroy'+namespace;
7849
                var data = settings.aoData;
7850
 
7851
                api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent );
7852
 
7853
                if ( _pluck( data, '_details' ).length > 0 ) {
7854
                        // On each draw, insert the required elements into the document
7855
                        api.on( drawEvent, function ( e, ctx ) {
7856
                                if ( settings !== ctx ) {
7857
                                        return;
7858
                                }
7859
 
7860
                                api.rows( {page:'current'} ).eq(0).each( function (idx) {
7861
                                        // Internal data grab
7862
                                        var row = data[ idx ];
7863
 
7864
                                        if ( row._detailsShow ) {
7865
                                                row._details.insertAfter( row.nTr );
7866
                                        }
7867
                                } );
7868
                        } );
7869
 
7870
                        // Column visibility change - update the colspan
7871
                        api.on( colvisEvent, function ( e, ctx, idx, vis ) {
7872
                                if ( settings !== ctx ) {
7873
                                        return;
7874
                                }
7875
 
7876
                                // Update the colspan for the details rows (note, only if it already has
7877
                                // a colspan)
7878
                                var row, visible = _fnVisbleColumns( ctx );
7879
 
7880
                                for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7881
                                        row = data[i];
7882
 
7883
                                        if ( row._details ) {
7884
                                                row._details.children('td[colspan]').attr('colspan', visible );
7885
                                        }
7886
                                }
7887
                        } );
7888
 
7889
                        // Table destroyed - nuke any child rows
7890
                        api.on( destroyEvent, function ( e, ctx ) {
7891
                                if ( settings !== ctx ) {
7892
                                        return;
7893
                                }
7894
 
7895
                                for ( var i=0, ien=data.length ; i<ien ; i++ ) {
7896
                                        if ( data[i]._details ) {
7897
                                                __details_remove( data[i] );
7898
                                        }
7899
                                }
7900
                        } );
7901
                }
7902
        };
7903
 
7904
        // Strings for the method names to help minification
7905
        var _emp = '';
7906
        var _child_obj = _emp+'row().child';
7907
        var _child_mth = _child_obj+'()';
7908
 
7909
        // data can be:
7910
        //  tr
7911
        //  string
7912
        //  jQuery or array of any of the above
7913
        _api_register( _child_mth, function ( data, klass ) {
7914
                var ctx = this.context;
7915
 
7916
                if ( data === undefined ) {
7917
                        // get
7918
                        return ctx.length && this.length ?
7919
                                ctx[0].aoData[ this[0] ]._details :
7920
                                undefined;
7921
                }
7922
                else if ( data === true ) {
7923
                        // show
7924
                        this.child.show();
7925
                }
7926
                else if ( data === false ) {
7927
                        // remove
7928
                        __details_remove( this );
7929
                }
7930
                else if ( ctx.length && this.length ) {
7931
                        // set
7932
                        __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass );
7933
                }
7934
 
7935
                return this;
7936
        } );
7937
 
7938
 
7939
        _api_register( [
7940
                _child_obj+'.show()',
7941
                _child_mth+'.show()' // only when `child()` was called with parameters (without
7942
        ], function ( show ) {   // it returns an object and this method is not executed)
7943
                __details_display( this, true );
7944
                return this;
7945
        } );
7946
 
7947
 
7948
        _api_register( [
7949
                _child_obj+'.hide()',
7950
                _child_mth+'.hide()' // only when `child()` was called with parameters (without
7951
        ], function () {         // it returns an object and this method is not executed)
7952
                __details_display( this, false );
7953
                return this;
7954
        } );
7955
 
7956
 
7957
        _api_register( [
7958
                _child_obj+'.remove()',
7959
                _child_mth+'.remove()' // only when `child()` was called with parameters (without
7960
        ], function () {           // it returns an object and this method is not executed)
7961
                __details_remove( this );
7962
                return this;
7963
        } );
7964
 
7965
 
7966
        _api_register( _child_obj+'.isShown()', function () {
7967
                var ctx = this.context;
7968
 
7969
                if ( ctx.length && this.length ) {
7970
                        // _detailsShown as false or undefined will fall through to return false
7971
                        return ctx[0].aoData[ this[0] ]._detailsShow || false;
7972
                }
7973
                return false;
7974
        } );
7975
 
7976
 
7977
 
7978
        /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *
7979
         * Columns
7980
         *
7981
         * {integer}           - column index (>=0 count from left, <0 count from right)
7982
         * "{integer}:visIdx"  - visible column index (i.e. translate to column index)  (>=0 count from left, <0 count from right)
7983
         * "{integer}:visible" - alias for {integer}:visIdx  (>=0 count from left, <0 count from right)
7984
         * "{string}:name"     - column name
7985
         * "{string}"          - jQuery selector on column header nodes
7986
         *
7987
         */
7988
 
7989
        // can be an array of these items, comma separated list, or an array of comma
7990
        // separated lists
7991
 
7992
        var __re_column_selector = /^(.+):(name|visIdx|visible)$/;
7993
 
7994
        var __column_selector = function ( settings, selector, opts )
7995
        {
7996
                var
7997
                        columns = settings.aoColumns,
7998
                        names = _pluck( columns, 'sName' ),
7999
                        nodes = _pluck( columns, 'nTh' );
8000
 
8001
                return _selector_run( selector, function ( s ) {
8002
                        var selInt = _intVal( s );
8003
 
8004
                        if ( s === '' ) {
8005
                                // All columns
8006
                                return _range( columns.length );
8007
                        }
8008
                        else if ( selInt !== null ) {
8009
                                // Integer selector
8010
                                return [ selInt >= 0 ?
8011
                                        selInt : // Count from left
8012
                                        columns.length + selInt // Count from right (+ because its a negative value)
8013
                                ];
8014
                        }
8015
                        else {
8016
                                var match = typeof s === 'string' ?
8017
                                        s.match( __re_column_selector ) :
8018
                                        '';
8019
 
8020
                                if ( match ) {
8021
                                        switch( match[2] ) {
8022
                                                case 'visIdx':
8023
                                                case 'visible':
8024
                                                        var idx = parseInt( match[1], 10 );
8025
                                                        // Visible index given, convert to column index
8026
                                                        if ( idx < 0 ) {
8027
                                                                // Counting from the right
8028
                                                                var visColumns = $.map( columns, function (col,i) {
8029
                                                                        return col.bVisible ? i : null;
8030
                                                                } );
8031
                                                                return [ visColumns[ visColumns.length + idx ] ];
8032
                                                        }
8033
                                                        // Counting from the left
8034
                                                        return [ _fnVisibleToColumnIndex( settings, idx ) ];
8035
 
8036
                                                case 'name':
8037
                                                        // match by name. `names` is column index complete and in order
8038
                                                        return $.map( names, function (name, i) {
8039
                                                                return name === match[1] ? i : null;
8040
                                                        } );
8041
                                        }
8042
                                }
8043
                                else {
8044
                                        // jQuery selector on the TH elements for the columns
8045
                                        return $( nodes )
8046
                                                .filter( s )
8047
                                                .map( function () {
8048
                                                        return $.inArray( this, nodes ); // `nodes` is column index complete and in order
8049
                                                } )
8050
                                                .toArray();
8051
                                }
8052
                        }
8053
                } );
8054
        };
8055
 
8056
 
8057
 
8058
 
8059
 
8060
        var __setColumnVis = function ( settings, column, vis, recalc ) {
8061
                var
8062
                        cols = settings.aoColumns,
8063
                        col  = cols[ column ],
8064
                        data = settings.aoData,
8065
                        row, cells, i, ien, tr;
8066
 
8067
                // Get
8068
                if ( vis === undefined ) {
8069
                        return col.bVisible;
8070
                }
8071
 
8072
                // Set
8073
                // No change
8074
                if ( col.bVisible === vis ) {
8075
                        return;
8076
                }
8077
 
8078
                if ( vis ) {
8079
                        // Insert column
8080
                        // Need to decide if we should use appendChild or insertBefore
8081
                        var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 );
8082
 
8083
                        for ( i=0, ien=data.length ; i<ien ; i++ ) {
8084
                                tr = data[i].nTr;
8085
                                cells = data[i].anCells;
8086
 
8087
                                if ( tr ) {
8088
                                        // insertBefore can act like appendChild if 2nd arg is null
8089
                                        tr.insertBefore( cells[ column ], cells[ insertBefore ] || null );
8090
                                }
8091
                        }
8092
                }
8093
                else {
8094
                        // Remove column
8095
                        $( _pluck( settings.aoData, 'anCells', column ) ).detach();
8096
                }
8097
 
8098
                // Common actions
8099
                col.bVisible = vis;
8100
                _fnDrawHead( settings, settings.aoHeader );
8101
                _fnDrawHead( settings, settings.aoFooter );
8102
 
8103
                if ( recalc === undefined || recalc ) {
8104
                        // Automatically adjust column sizing
8105
                        _fnAdjustColumnSizing( settings );
8106
 
8107
                        // Realign columns for scrolling
8108
                        if ( settings.oScroll.sX || settings.oScroll.sY ) {
8109
                                _fnScrollDraw( settings );
8110
                        }
8111
                }
8112
 
8113
                _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis] );
8114
 
8115
                _fnSaveState( settings );
8116
        };
8117
 
8118
 
8119
        /**
8120
         *
8121
         */
8122
        _api_register( 'columns()', function ( selector, opts ) {
8123
                // argument shifting
8124
                if ( selector === undefined ) {
8125
                        selector = '';
8126
                }
8127
                else if ( $.isPlainObject( selector ) ) {
8128
                        opts = selector;
8129
                        selector = '';
8130
                }
8131
 
8132
                opts = _selector_opts( opts );
8133
 
8134
                var inst = this.iterator( 'table', function ( settings ) {
8135
                        return __column_selector( settings, selector, opts );
8136
                } );
8137
 
8138
                // Want argument shifting here and in _row_selector?
8139
                inst.selector.cols = selector;
8140
                inst.selector.opts = opts;
8141
 
8142
                return inst;
8143
        } );
8144
 
8145
 
8146
        /**
8147
         *
8148
         */
8149
        _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) {
8150
                return this.iterator( 'column', function ( settings, column ) {
8151
                        return settings.aoColumns[column].nTh;
8152
                } );
8153
        } );
8154
 
8155
 
8156
        /**
8157
         *
8158
         */
8159
        _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) {
8160
                return this.iterator( 'column', function ( settings, column ) {
8161
                        return settings.aoColumns[column].nTf;
8162
                } );
8163
        } );
8164
 
8165
 
8166
        /**
8167
         *
8168
         */
8169
        _api_registerPlural( 'columns().data()', 'column().data()', function () {
8170
                return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8171
                        var a = [];
8172
                        for ( var row=0, ien=rows.length ; row<ien ; row++ ) {
8173
                                a.push( _fnGetCellData( settings, rows[row], column, '' ) );
8174
                        }
8175
                        return a;
8176
                } );
8177
        } );
8178
 
8179
 
8180
        _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) {
8181
                return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8182
                        return _pluck_order( settings.aoData, rows,
8183
                                type === 'search' ? '_aFilterData' : '_aSortData', column
8184
                        );
8185
                } );
8186
        } );
8187
 
8188
 
8189
        _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () {
8190
                return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) {
8191
                        return _pluck_order( settings.aoData, rows, 'anCells', column ) ;
8192
                } );
8193
        } );
8194
 
8195
 
8196
 
8197
        _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) {
8198
                return this.iterator( 'column', function ( settings, column ) {
8199
                        return vis === undefined ?
8200
                                settings.aoColumns[ column ].bVisible :
8201
                                __setColumnVis( settings, column, vis, calc );
8202
                } );
8203
        } );
8204
 
8205
 
8206
 
8207
        _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) {
8208
                return this.iterator( 'column', function ( settings, column ) {
8209
                        return type === 'visible' ?
8210
                                _fnColumnIndexToVisible( settings, column ) :
8211
                                column;
8212
                } );
8213
        } );
8214
 
8215
 
8216
        // _api_register( 'columns().show()', function () {
8217
        //      var selector = this.selector;
8218
        //      return this.columns( selector.cols, selector.opts ).visible( true );
8219
        // } );
8220
 
8221
 
8222
        // _api_register( 'columns().hide()', function () {
8223
        //      var selector = this.selector;
8224
        //      return this.columns( selector.cols, selector.opts ).visible( false );
8225
        // } );
8226
 
8227
 
8228
 
8229
        _api_register( 'columns.adjust()', function () {
8230
                return this.iterator( 'table', function ( settings ) {
8231
                        _fnAdjustColumnSizing( settings );
8232
                } );
8233
        } );
8234
 
8235
 
8236
        // Convert from one column index type, to another type
8237
        _api_register( 'column.index()', function ( type, idx ) {
8238
                if ( this.context.length !== 0 ) {
8239
                        var ctx = this.context[0];
8240
 
8241
                        if ( type === 'fromVisible' || type === 'toData' ) {
8242
                                return _fnVisibleToColumnIndex( ctx, idx );
8243
                        }
8244
                        else if ( type === 'fromData' || type === 'toVisible' ) {
8245
                                return _fnColumnIndexToVisible( ctx, idx );
8246
                        }
8247
                }
8248
        } );
8249
 
8250
 
8251
        _api_register( 'column()', function ( selector, opts ) {
8252
                return _selector_first( this.columns( selector, opts ) );
8253
        } );
8254
 
8255
 
8256
 
8257
 
8258
        var __cell_selector = function ( settings, selector, opts )
8259
        {
8260
                var data = settings.aoData;
8261
                var rows = _selector_row_indexes( settings, opts );
8262
                var cells = _pluck_order( data, rows, 'anCells' );
8263
                var allCells = $( [].concat.apply([], cells) );
8264
                var row;
8265
                var columns = settings.aoColumns.length;
8266
                var a, i, ien, j;
8267
 
8268
                return _selector_run( selector, function ( s ) {
8269
                        if ( s === null || s === undefined ) {
8270
                                // All cells
8271
                                a = [];
8272
 
8273
                                for ( i=0, ien=rows.length ; i<ien ; i++ ) {
8274
                                        row = rows[i];
8275
 
8276
                                        for ( j=0 ; j<columns ; j++ ) {
8277
                                                a.push( {
8278
                                                        row: row,
8279
                                                        column: j
8280
                                                } );
8281
                                        }
8282
                                }
8283
 
8284
                                return a;
8285
                        }
8286
                        else if ( $.isPlainObject( s ) ) {
8287
                                return [s];
8288
                        }
8289
 
8290
                        // jQuery filtered cells
8291
                        return allCells
8292
                                .filter( s )
8293
                                .map( function (i, el) {
8294
                                        row = el.parentNode._DT_RowIndex;
8295
 
8296
                                        return {
8297
                                                row: row,
8298
                                                column: $.inArray( el, data[ row ].anCells )
8299
                                        };
8300
                                } )
8301
                                .toArray();
8302
                } );
8303
        };
8304
 
8305
 
8306
 
8307
 
8308
        _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) {
8309
                // Argument shifting
8310
                if ( $.isPlainObject( rowSelector ) ) {
8311
                        // Indexes
8312
                        if ( typeof rowSelector.row !== undefined ) {
8313
                                opts = columnSelector;
8314
                                columnSelector = null;
8315
                        }
8316
                        else {
8317
                                opts = rowSelector;
8318
                                rowSelector = null;
8319
                        }
8320
                }
8321
                if ( $.isPlainObject( columnSelector ) ) {
8322
                        opts = columnSelector;
8323
                        columnSelector = null;
8324
                }
8325
 
8326
                // Cell selector
8327
                if ( columnSelector === null || columnSelector === undefined ) {
8328
                        return this.iterator( 'table', function ( settings ) {
8329
                                return __cell_selector( settings, rowSelector, _selector_opts( opts ) );
8330
                        } );
8331
                }
8332
 
8333
                // Row + column selector
8334
                var columns = this.columns( columnSelector, opts );
8335
                var rows = this.rows( rowSelector, opts );
8336
                var a, i, ien, j, jen;
8337
 
8338
                var cells = this.iterator( 'table', function ( settings, idx ) {
8339
                        a = [];
8340
 
8341
                        for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) {
8342
                                for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) {
8343
                                        a.push( {
8344
                                                row:    rows[idx][i],
8345
                                                column: columns[idx][j]
8346
                                        } );
8347
                                }
8348
                        }
8349
 
8350
                        return a;
8351
                } );
8352
 
8353
                $.extend( cells.selector, {
8354
                        cols: columnSelector,
8355
                        rows: rowSelector,
8356
                        opts: opts
8357
                } );
8358
 
8359
                return cells;
8360
        } );
8361
 
8362
 
8363
        _api_registerPlural( 'cells().nodes()', 'cell().node()', function () {
8364
                return this.iterator( 'cell', function ( settings, row, column ) {
8365
                        return settings.aoData[ row ].anCells[ column ];
8366
                } );
8367
        } );
8368
 
8369
 
8370
        _api_register( 'cells().data()', function () {
8371
                return this.iterator( 'cell', function ( settings, row, column ) {
8372
                        return _fnGetCellData( settings, row, column );
8373
                } );
8374
        } );
8375
 
8376
 
8377
        _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) {
8378
                type = type === 'search' ? '_aFilterData' : '_aSortData';
8379
 
8380
                return this.iterator( 'cell', function ( settings, row, column ) {
8381
                        return settings.aoData[ row ][ type ][ column ];
8382
                } );
8383
        } );
8384
 
8385
 
8386
        _api_registerPlural( 'cells().indexes()', 'cell().index()', function () {
8387
                return this.iterator( 'cell', function ( settings, row, column ) {
8388
                        return {
8389
                                row: row,
8390
                                column: column,
8391
                                columnVisible: _fnColumnIndexToVisible( settings, column )
8392
                        };
8393
                } );
8394
        } );
8395
 
8396
 
8397
        _api_register( [
8398
                'cells().invalidate()',
8399
                'cell().invalidate()'
8400
        ], function ( src ) {
8401
                var selector = this.selector;
8402
 
8403
                // Use the rows method of the instance to perform the invalidation, rather
8404
                // than doing it here. This avoids needing to handle duplicate rows from
8405
                // the cells.
8406
                this.rows( selector.rows, selector.opts ).invalidate( src );
8407
 
8408
                return this;
8409
        } );
8410
 
8411
 
8412
 
8413
 
8414
        _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) {
8415
                return _selector_first( this.cells( rowSelector, columnSelector, opts ) );
8416
        } );
8417
 
8418
 
8419
 
8420
        _api_register( 'cell().data()', function ( data ) {
8421
                var ctx = this.context;
8422
                var cell = this[0];
8423
 
8424
                if ( data === undefined ) {
8425
                        // Get
8426
                        return ctx.length && cell.length ?
8427
                                _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) :
8428
                                undefined;
8429
                }
8430
 
8431
                // Set
8432
                _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data );
8433
                _fnInvalidateRow( ctx[0], cell[0].row, 'data', cell[0].column );
8434
 
8435
                return this;
8436
        } );
8437
 
8438
 
8439
 
8440
        /**
8441
         * Get current ordering (sorting) that has been applied to the table.
8442
         *
8443
         * @returns {array} 2D array containing the sorting information for the first
8444
         *   table in the current context. Each element in the parent array represents
8445
         *   a column being sorted upon (i.e. multi-sorting with two columns would have
8446
         *   2 inner arrays). The inner arrays may have 2 or 3 elements. The first is
8447
         *   the column index that the sorting condition applies to, the second is the
8448
         *   direction of the sort (`desc` or `asc`) and, optionally, the third is the
8449
         *   index of the sorting order from the `column.sorting` initialisation array.
8450
         *//**
8451
         * Set the ordering for the table.
8452
         *
8453
         * @param {integer} order Column index to sort upon.
8454
         * @param {string} direction Direction of the sort to be applied (`asc` or `desc`)
8455
         * @returns {DataTables.Api} this
8456
         *//**
8457
         * Set the ordering for the table.
8458
         *
8459
         * @param {array} order 1D array of sorting information to be applied.
8460
         * @param {array} [...] Optional additional sorting conditions
8461
         * @returns {DataTables.Api} this
8462
         *//**
8463
         * Set the ordering for the table.
8464
         *
8465
         * @param {array} order 2D array of sorting information to be applied.
8466
         * @returns {DataTables.Api} this
8467
         */
8468
        _api_register( 'order()', function ( order, dir ) {
8469
                var ctx = this.context;
8470
 
8471
                if ( order === undefined ) {
8472
                        // get
8473
                        return ctx.length !== 0 ?
8474
                                ctx[0].aaSorting :
8475
                                undefined;
8476
                }
8477
 
8478
                // set
8479
                if ( typeof order === 'number' ) {
8480
                        // Simple column / direction passed in
8481
                        order = [ [ order, dir ] ];
8482
                }
8483
                else if ( ! $.isArray( order[0] ) ) {
8484
                        // Arguments passed in (list of 1D arrays)
8485
                        order = Array.prototype.slice.call( arguments );
8486
                }
8487
                // otherwise a 2D array was passed in
8488
 
8489
                return this.iterator( 'table', function ( settings ) {
8490
                        settings.aaSorting = order.slice();
8491
                } );
8492
        } );
8493
 
8494
 
8495
        /**
8496
         * Attach a sort listener to an element for a given column
8497
         *
8498
         * @param {node|jQuery|string} node Identifier for the element(s) to attach the
8499
         *   listener to. This can take the form of a single DOM node, a jQuery
8500
         *   collection of nodes or a jQuery selector which will identify the node(s).
8501
         * @param {integer} column the column that a click on this node will sort on
8502
         * @param {function} [callback] callback function when sort is run
8503
         * @returns {DataTables.Api} this
8504
         */
8505
        _api_register( 'order.listener()', function ( node, column, callback ) {
8506
                return this.iterator( 'table', function ( settings ) {
8507
                        _fnSortAttachListener( settings, node, column, callback );
8508
                } );
8509
        } );
8510
 
8511
 
8512
        // Order by the selected column(s)
8513
        _api_register( [
8514
                'columns().order()',
8515
                'column().order()'
8516
        ], function ( dir ) {
8517
                var that = this;
8518
 
8519
                return this.iterator( 'table', function ( settings, i ) {
8520
                        var sort = [];
8521
 
8522
                        $.each( that[i], function (j, col) {
8523
                                sort.push( [ col, dir ] );
8524
                        } );
8525
 
8526
                        settings.aaSorting = sort;
8527
                } );
8528
        } );
8529
 
8530
 
8531
 
8532
        _api_register( 'search()', function ( input, regex, smart, caseInsen ) {
8533
                var ctx = this.context;
8534
 
8535
                if ( input === undefined ) {
8536
                        // get
8537
                        return ctx.length !== 0 ?
8538
                                ctx[0].oPreviousSearch.sSearch :
8539
                                undefined;
8540
                }
8541
 
8542
                // set
8543
                return this.iterator( 'table', function ( settings ) {
8544
                        if ( ! settings.oFeatures.bFilter ) {
8545
                                return;
8546
                        }
8547
 
8548
                        _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, {
8549
                                "sSearch": input+"",
8550
                                "bRegex":  regex === null ? false : regex,
8551
                                "bSmart":  smart === null ? true  : smart,
8552
                                "bCaseInsensitive": caseInsen === null ? true : caseInsen
8553
                        } ), 1 );
8554
                } );
8555
        } );
8556
 
8557
 
8558
        _api_registerPlural(
8559
                'columns().search()',
8560
                'column().search()',
8561
                function ( input, regex, smart, caseInsen ) {
8562
                        return this.iterator( 'column', function ( settings, column ) {
8563
                                var preSearch = settings.aoPreSearchCols;
8564
 
8565
                                if ( input === undefined ) {
8566
                                        // get
8567
                                        return preSearch[ column ].sSearch;
8568
                                }
8569
 
8570
                                // set
8571
                                if ( ! settings.oFeatures.bFilter ) {
8572
                                        return;
8573
                                }
8574
 
8575
                                $.extend( preSearch[ column ], {
8576
                                        "sSearch": input+"",
8577
                                        "bRegex":  regex === null ? false : regex,
8578
                                        "bSmart":  smart === null ? true  : smart,
8579
                                        "bCaseInsensitive": caseInsen === null ? true : caseInsen
8580
                                } );
8581
 
8582
                                _fnFilterComplete( settings, settings.oPreviousSearch, 1 );
8583
                        } );
8584
                }
8585
        );
8586
 
8587
        /*
8588
         * State API methods
8589
         */
8590
 
8591
        _api_register( 'state()', function () {
8592
                return this.context.length ?
8593
                        this.context[0].oSavedState :
8594
                        null;
8595
        } );
8596
 
8597
 
8598
        _api_register( 'state.clear()', function () {
8599
                return this.iterator( 'table', function ( settings ) {
8600
                        // Save an empty object
8601
                        settings.fnStateSaveCallback.call( settings.oInstance, settings, {} );
8602
                } );
8603
        } );
8604
 
8605
 
8606
        _api_register( 'state.loaded()', function () {
8607
                return this.context.length ?
8608
                        this.context[0].oLoadedState :
8609
                        null;
8610
        } );
8611
 
8612
 
8613
        _api_register( 'state.save()', function () {
8614
                return this.iterator( 'table', function ( settings ) {
8615
                        _fnSaveState( settings );
8616
                } );
8617
        } );
8618
 
8619
 
8620
 
8621
        /**
8622
         * Provide a common method for plug-ins to check the version of DataTables being
8623
         * used, in order to ensure compatibility.
8624
         *
8625
         *  @param {string} version Version string to check for, in the format "X.Y.Z".
8626
         *    Note that the formats "X" and "X.Y" are also acceptable.
8627
         *  @returns {boolean} true if this version of DataTables is greater or equal to
8628
         *    the required version, or false if this version of DataTales is not
8629
         *    suitable
8630
         *  @static
8631
         *  @dtopt API-Static
8632
         *
8633
         *  @example
8634
         *    alert( $.fn.dataTable.versionCheck( '1.9.0' ) );
8635
         */
8636
        DataTable.versionCheck = DataTable.fnVersionCheck = function( version )
8637
        {
8638
                var aThis = DataTable.version.split('.');
8639
                var aThat = version.split('.');
8640
                var iThis, iThat;
8641
 
8642
                for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) {
8643
                        iThis = parseInt( aThis[i], 10 ) || 0;
8644
                        iThat = parseInt( aThat[i], 10 ) || 0;
8645
 
8646
                        // Parts are the same, keep comparing
8647
                        if (iThis === iThat) {
8648
                                continue;
8649
                        }
8650
 
8651
                        // Parts are different, return immediately
8652
                        return iThis > iThat;
8653
                }
8654
 
8655
                return true;
8656
        };
8657
 
8658
 
8659
        /**
8660
         * Check if a `<table>` node is a DataTable table already or not.
8661
         *
8662
         *  @param {node|jquery|string} table Table node, jQuery object or jQuery
8663
         *      selector for the table to test. Note that if more than more than one
8664
         *      table is passed on, only the first will be checked
8665
         *  @returns {boolean} true the table given is a DataTable, or false otherwise
8666
         *  @static
8667
         *  @dtopt API-Static
8668
         *
8669
         *  @example
8670
         *    if ( ! $.fn.DataTable.isDataTable( '#example' ) ) {
8671
         *      $('#example').dataTable();
8672
         *    }
8673
         */
8674
        DataTable.isDataTable = DataTable.fnIsDataTable = function ( table )
8675
        {
8676
                var t = $(table).get(0);
8677
                var is = false;
8678
 
8679
                $.each( DataTable.settings, function (i, o) {
8680
                        if ( o.nTable === t || o.nScrollHead === t || o.nScrollFoot === t ) {
8681
                                is = true;
8682
                        }
8683
                } );
8684
 
8685
                return is;
8686
        };
8687
 
8688
 
8689
        /**
8690
         * Get all DataTable tables that have been initialised - optionally you can
8691
         * select to get only currently visible tables.
8692
         *
8693
         *  @param {boolean} [visible=false] Flag to indicate if you want all (default)
8694
         *    or visible tables only.
8695
         *  @returns {array} Array of `table` nodes (not DataTable instances) which are
8696
         *    DataTables
8697
         *  @static
8698
         *  @dtopt API-Static
8699
         *
8700
         *  @example
8701
         *    $.each( $.fn.dataTable.tables(true), function () {
8702
         *      $(table).DataTable().columns.adjust();
8703
         *    } );
8704
         */
8705
        DataTable.tables = DataTable.fnTables = function ( visible )
8706
        {
8707
                return jQuery.map( DataTable.settings, function (o) {
8708
                        if ( !visible || (visible && $(o.nTable).is(':visible')) ) {
8709
                                return o.nTable;
8710
                        }
8711
                } );
8712
        };
8713
 
8714
 
8715
        /**
8716
         * Convert from camel case parameters to Hungarian notation. This is made public
8717
         * for the extensions to provide the same ability as DataTables core to accept
8718
         * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase
8719
         * parameters.
8720
         *
8721
         *  @param {object} src The model object which holds all parameters that can be
8722
         *    mapped.
8723
         *  @param {object} user The object to convert from camel case to Hungarian.
8724
         *  @param {boolean} force When set to `true`, properties which already have a
8725
         *    Hungarian value in the `user` object will be overwritten. Otherwise they
8726
         *    won't be.
8727
         */
8728
        DataTable.camelToHungarian = _fnCamelToHungarian;
8729
 
8730
 
8731
 
8732
        /**
8733
         *
8734
         */
8735
        _api_register( '$()', function ( selector, opts ) {
8736
                var
8737
                        rows   = this.rows( opts ).nodes(), // Get all rows
8738
                        jqRows = $(rows);
8739
 
8740
                return $( [].concat(
8741
                        jqRows.filter( selector ).toArray(),
8742
                        jqRows.find( selector ).toArray()
8743
                ) );
8744
        } );
8745
 
8746
 
8747
        // jQuery functions to operate on the tables
8748
        $.each( [ 'on', 'one', 'off' ], function (i, key) {
8749
                _api_register( key+'()', function ( /* event, handler */ ) {
8750
                        var args = Array.prototype.slice.call(arguments);
8751
 
8752
                        // Add the `dt` namespace automatically if it isn't already present
8753
                        if ( ! args[0].match(/\.dt\b/) ) {
8754
                                args[0] += '.dt';
8755
                        }
8756
 
8757
                        var inst = $( this.tables().nodes() );
8758
                        inst[key].apply( inst, args );
8759
                        return this;
8760
                } );
8761
        } );
8762
 
8763
 
8764
        _api_register( 'clear()', function () {
8765
                return this.iterator( 'table', function ( settings ) {
8766
                        _fnClearTable( settings );
8767
                } );
8768
        } );
8769
 
8770
 
8771
        _api_register( 'settings()', function () {
8772
                return new _Api( this.context, this.context );
8773
        } );
8774
 
8775
 
8776
        _api_register( 'data()', function () {
8777
                return this.iterator( 'table', function ( settings ) {
8778
                        return _pluck( settings.aoData, '_aData' );
8779
                } ).flatten();
8780
        } );
8781
 
8782
 
8783
        _api_register( 'destroy()', function ( remove ) {
8784
                remove = remove || false;
8785
 
8786
                return this.iterator( 'table', function ( settings ) {
8787
                        var orig      = settings.nTableWrapper.parentNode;
8788
                        var classes   = settings.oClasses;
8789
                        var table     = settings.nTable;
8790
                        var tbody     = settings.nTBody;
8791
                        var thead     = settings.nTHead;
8792
                        var tfoot     = settings.nTFoot;
8793
                        var jqTable   = $(table);
8794
                        var jqTbody   = $(tbody);
8795
                        var jqWrapper = $(settings.nTableWrapper);
8796
                        var rows      = $.map( settings.aoData, function (r) { return r.nTr; } );
8797
                        var i, ien;
8798
 
8799
                        // Flag to note that the table is currently being destroyed - no action
8800
                        // should be taken
8801
                        settings.bDestroying = true;
8802
 
8803
                        // Fire off the destroy callbacks for plug-ins etc
8804
                        _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] );
8805
 
8806
                        // If not being removed from the document, make all columns visible
8807
                        if ( ! remove ) {
8808
                                new _Api( settings ).columns().visible( true );
8809
                        }
8810
 
8811
                        // Blitz all `DT` namespaced events (these are internal events, the
8812
                        // lowercase, `dt` events are user subscribed and they are responsible
8813
                        // for removing them
8814
                        jqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT');
8815
                        $(window).unbind('.DT-'+settings.sInstance);
8816
 
8817
                        // When scrolling we had to break the table up - restore it
8818
                        if ( table != thead.parentNode ) {
8819
                                jqTable.children('thead').detach();
8820
                                jqTable.append( thead );
8821
                        }
8822
 
8823
                        if ( tfoot && table != tfoot.parentNode ) {
8824
                                jqTable.children('tfoot').detach();
8825
                                jqTable.append( tfoot );
8826
                        }
8827
 
8828
                        // Remove the DataTables generated nodes, events and classes
8829
                        jqTable.detach();
8830
                        jqWrapper.detach();
8831
 
8832
                        settings.aaSorting = [];
8833
                        settings.aaSortingFixed = [];
8834
                        _fnSortingClasses( settings );
8835
 
8836
                        $( rows ).removeClass( settings.asStripeClasses.join(' ') );
8837
 
8838
                        $('th, td', thead).removeClass( classes.sSortable+' '+
8839
                                classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone
8840
                        );
8841
 
8842
                        if ( settings.bJUI ) {
8843
                                $('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach();
8844
                                $('th, td', thead).each( function () {
8845
                                        var wrapper = $('div.'+classes.sSortJUIWrapper, this);
8846
                                        $(this).append( wrapper.contents() );
8847
                                        wrapper.detach();
8848
                                } );
8849
                        }
8850
 
8851
                        if ( ! remove && orig ) {
8852
                                // insertBefore acts like appendChild if !arg[1]
8853
                                orig.insertBefore( table, settings.nTableReinsertBefore );
8854
                        }
8855
 
8856
                        // Add the TR elements back into the table in their original order
8857
                        jqTbody.children().detach();
8858
                        jqTbody.append( rows );
8859
 
8860
                        // Restore the width of the original table - was read from the style property,
8861
                        // so we can restore directly to that
8862
                        jqTable
8863
                                .css( 'width', settings.sDestroyWidth )
8864
                                .removeClass( classes.sTable );
8865
 
8866
                        // If the were originally stripe classes - then we add them back here.
8867
                        // Note this is not fool proof (for example if not all rows had stripe
8868
                        // classes - but it's a good effort without getting carried away
8869
                        ien = settings.asDestroyStripes.length;
8870
 
8871
                        if ( ien ) {
8872
                                jqTbody.children().each( function (i) {
8873
                                        $(this).addClass( settings.asDestroyStripes[i % ien] );
8874
                                } );
8875
                        }
8876
 
8877
                        /* Remove the settings object from the settings array */
8878
                        var idx = $.inArray( settings, DataTable.settings );
8879
                        if ( idx !== -1 ) {
8880
                                DataTable.settings.splice( idx, 1 );
8881
                        }
8882
                } );
8883
        } );
8884
 
8885
 
8886
        /**
8887
         * Version string for plug-ins to check compatibility. Allowed format is
8888
         * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used
8889
         * only for non-release builds. See http://semver.org/ for more information.
8890
         *  @member
8891
         *  @type string
8892
         *  @default Version number
8893
         */
8894
        DataTable.version = "1.10.2";
8895
 
8896
        /**
8897
         * Private data store, containing all of the settings objects that are
8898
         * created for the tables on a given page.
8899
         *
8900
         * Note that the `DataTable.settings` object is aliased to
8901
         * `jQuery.fn.dataTableExt` through which it may be accessed and
8902
         * manipulated, or `jQuery.fn.dataTable.settings`.
8903
         *  @member
8904
         *  @type array
8905
         *  @default []
8906
         *  @private
8907
         */
8908
        DataTable.settings = [];
8909
 
8910
        /**
8911
         * Object models container, for the various models that DataTables has
8912
         * available to it. These models define the objects that are used to hold
8913
         * the active state and configuration of the table.
8914
         *  @namespace
8915
         */
8916
        DataTable.models = {};
8917
 
8918
 
8919
 
8920
        /**
8921
         * Template object for the way in which DataTables holds information about
8922
         * search information for the global filter and individual column filters.
8923
         *  @namespace
8924
         */
8925
        DataTable.models.oSearch = {
8926
                /**
8927
                 * Flag to indicate if the filtering should be case insensitive or not
8928
                 *  @type boolean
8929
                 *  @default true
8930
                 */
8931
                "bCaseInsensitive": true,
8932
 
8933
                /**
8934
                 * Applied search term
8935
                 *  @type string
8936
                 *  @default <i>Empty string</i>
8937
                 */
8938
                "sSearch": "",
8939
 
8940
                /**
8941
                 * Flag to indicate if the search term should be interpreted as a
8942
                 * regular expression (true) or not (false) and therefore and special
8943
                 * regex characters escaped.
8944
                 *  @type boolean
8945
                 *  @default false
8946
                 */
8947
                "bRegex": false,
8948
 
8949
                /**
8950
                 * Flag to indicate if DataTables is to use its smart filtering or not.
8951
                 *  @type boolean
8952
                 *  @default true
8953
                 */
8954
                "bSmart": true
8955
        };
8956
 
8957
 
8958
 
8959
 
8960
        /**
8961
         * Template object for the way in which DataTables holds information about
8962
         * each individual row. This is the object format used for the settings
8963
         * aoData array.
8964
         *  @namespace
8965
         */
8966
        DataTable.models.oRow = {
8967
                /**
8968
                 * TR element for the row
8969
                 *  @type node
8970
                 *  @default null
8971
                 */
8972
                "nTr": null,
8973
 
8974
                /**
8975
                 * Array of TD elements for each row. This is null until the row has been
8976
                 * created.
8977
                 *  @type array nodes
8978
                 *  @default []
8979
                 */
8980
                "anCells": null,
8981
 
8982
                /**
8983
                 * Data object from the original data source for the row. This is either
8984
                 * an array if using the traditional form of DataTables, or an object if
8985
                 * using mData options. The exact type will depend on the passed in
8986
                 * data from the data source, or will be an array if using DOM a data
8987
                 * source.
8988
                 *  @type array|object
8989
                 *  @default []
8990
                 */
8991
                "_aData": [],
8992
 
8993
                /**
8994
                 * Sorting data cache - this array is ostensibly the same length as the
8995
                 * number of columns (although each index is generated only as it is
8996
                 * needed), and holds the data that is used for sorting each column in the
8997
                 * row. We do this cache generation at the start of the sort in order that
8998
                 * the formatting of the sort data need be done only once for each cell
8999
                 * per sort. This array should not be read from or written to by anything
9000
                 * other than the master sorting methods.
9001
                 *  @type array
9002
                 *  @default null
9003
                 *  @private
9004
                 */
9005
                "_aSortData": null,
9006
 
9007
                /**
9008
                 * Per cell filtering data cache. As per the sort data cache, used to
9009
                 * increase the performance of the filtering in DataTables
9010
                 *  @type array
9011
                 *  @default null
9012
                 *  @private
9013
                 */
9014
                "_aFilterData": null,
9015
 
9016
                /**
9017
                 * Filtering data cache. This is the same as the cell filtering cache, but
9018
                 * in this case a string rather than an array. This is easily computed with
9019
                 * a join on `_aFilterData`, but is provided as a cache so the join isn't
9020
                 * needed on every search (memory traded for performance)
9021
                 *  @type array
9022
                 *  @default null
9023
                 *  @private
9024
                 */
9025
                "_sFilterRow": null,
9026
 
9027
                /**
9028
                 * Cache of the class name that DataTables has applied to the row, so we
9029
                 * can quickly look at this variable rather than needing to do a DOM check
9030
                 * on className for the nTr property.
9031
                 *  @type string
9032
                 *  @default <i>Empty string</i>
9033
                 *  @private
9034
                 */
9035
                "_sRowStripe": "",
9036
 
9037
                /**
9038
                 * Denote if the original data source was from the DOM, or the data source
9039
                 * object. This is used for invalidating data, so DataTables can
9040
                 * automatically read data from the original source, unless uninstructed
9041
                 * otherwise.
9042
                 *  @type string
9043
                 *  @default null
9044
                 *  @private
9045
                 */
9046
                "src": null
9047
        };
9048
 
9049
 
9050
        /**
9051
         * Template object for the column information object in DataTables. This object
9052
         * is held in the settings aoColumns array and contains all the information that
9053
         * DataTables needs about each individual column.
9054
         *
9055
         * Note that this object is related to {@link DataTable.defaults.column}
9056
         * but this one is the internal data store for DataTables's cache of columns.
9057
         * It should NOT be manipulated outside of DataTables. Any configuration should
9058
         * be done through the initialisation options.
9059
         *  @namespace
9060
         */
9061
        DataTable.models.oColumn = {
9062
                /**
9063
                 * Column index. This could be worked out on-the-fly with $.inArray, but it
9064
                 * is faster to just hold it as a variable
9065
                 *  @type integer
9066
                 *  @default null
9067
                 */
9068
                "idx": null,
9069
 
9070
                /**
9071
                 * A list of the columns that sorting should occur on when this column
9072
                 * is sorted. That this property is an array allows multi-column sorting
9073
                 * to be defined for a column (for example first name / last name columns
9074
                 * would benefit from this). The values are integers pointing to the
9075
                 * columns to be sorted on (typically it will be a single integer pointing
9076
                 * at itself, but that doesn't need to be the case).
9077
                 *  @type array
9078
                 */
9079
                "aDataSort": null,
9080
 
9081
                /**
9082
                 * Define the sorting directions that are applied to the column, in sequence
9083
                 * as the column is repeatedly sorted upon - i.e. the first value is used
9084
                 * as the sorting direction when the column if first sorted (clicked on).
9085
                 * Sort it again (click again) and it will move on to the next index.
9086
                 * Repeat until loop.
9087
                 *  @type array
9088
                 */
9089
                "asSorting": null,
9090
 
9091
                /**
9092
                 * Flag to indicate if the column is searchable, and thus should be included
9093
                 * in the filtering or not.
9094
                 *  @type boolean
9095
                 */
9096
                "bSearchable": null,
9097
 
9098
                /**
9099
                 * Flag to indicate if the column is sortable or not.
9100
                 *  @type boolean
9101
                 */
9102
                "bSortable": null,
9103
 
9104
                /**
9105
                 * Flag to indicate if the column is currently visible in the table or not
9106
                 *  @type boolean
9107
                 */
9108
                "bVisible": null,
9109
 
9110
                /**
9111
                 * Store for manual type assignment using the `column.type` option. This
9112
                 * is held in store so we can manipulate the column's `sType` property.
9113
                 *  @type string
9114
                 *  @default null
9115
                 *  @private
9116
                 */
9117
                "_sManualType": null,
9118
 
9119
                /**
9120
                 * Flag to indicate if HTML5 data attributes should be used as the data
9121
                 * source for filtering or sorting. True is either are.
9122
                 *  @type boolean
9123
                 *  @default false
9124
                 *  @private
9125
                 */
9126
                "_bAttrSrc": false,
9127
 
9128
                /**
9129
                 * Developer definable function that is called whenever a cell is created (Ajax source,
9130
                 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
9131
                 * allowing you to modify the DOM element (add background colour for example) when the
9132
                 * element is available.
9133
                 *  @type function
9134
                 *  @param {element} nTd The TD node that has been created
9135
                 *  @param {*} sData The Data for the cell
9136
                 *  @param {array|object} oData The data for the whole row
9137
                 *  @param {int} iRow The row index for the aoData data store
9138
                 *  @default null
9139
                 */
9140
                "fnCreatedCell": null,
9141
 
9142
                /**
9143
                 * Function to get data from a cell in a column. You should <b>never</b>
9144
                 * access data directly through _aData internally in DataTables - always use
9145
                 * the method attached to this property. It allows mData to function as
9146
                 * required. This function is automatically assigned by the column
9147
                 * initialisation method
9148
                 *  @type function
9149
                 *  @param {array|object} oData The data array/object for the array
9150
                 *    (i.e. aoData[]._aData)
9151
                 *  @param {string} sSpecific The specific data type you want to get -
9152
                 *    'display', 'type' 'filter' 'sort'
9153
                 *  @returns {*} The data for the cell from the given row's data
9154
                 *  @default null
9155
                 */
9156
                "fnGetData": null,
9157
 
9158
                /**
9159
                 * Function to set data for a cell in the column. You should <b>never</b>
9160
                 * set the data directly to _aData internally in DataTables - always use
9161
                 * this method. It allows mData to function as required. This function
9162
                 * is automatically assigned by the column initialisation method
9163
                 *  @type function
9164
                 *  @param {array|object} oData The data array/object for the array
9165
                 *    (i.e. aoData[]._aData)
9166
                 *  @param {*} sValue Value to set
9167
                 *  @default null
9168
                 */
9169
                "fnSetData": null,
9170
 
9171
                /**
9172
                 * Property to read the value for the cells in the column from the data
9173
                 * source array / object. If null, then the default content is used, if a
9174
                 * function is given then the return from the function is used.
9175
                 *  @type function|int|string|null
9176
                 *  @default null
9177
                 */
9178
                "mData": null,
9179
 
9180
                /**
9181
                 * Partner property to mData which is used (only when defined) to get
9182
                 * the data - i.e. it is basically the same as mData, but without the
9183
                 * 'set' option, and also the data fed to it is the result from mData.
9184
                 * This is the rendering method to match the data method of mData.
9185
                 *  @type function|int|string|null
9186
                 *  @default null
9187
                 */
9188
                "mRender": null,
9189
 
9190
                /**
9191
                 * Unique header TH/TD element for this column - this is what the sorting
9192
                 * listener is attached to (if sorting is enabled.)
9193
                 *  @type node
9194
                 *  @default null
9195
                 */
9196
                "nTh": null,
9197
 
9198
                /**
9199
                 * Unique footer TH/TD element for this column (if there is one). Not used
9200
                 * in DataTables as such, but can be used for plug-ins to reference the
9201
                 * footer for each column.
9202
                 *  @type node
9203
                 *  @default null
9204
                 */
9205
                "nTf": null,
9206
 
9207
                /**
9208
                 * The class to apply to all TD elements in the table's TBODY for the column
9209
                 *  @type string
9210
                 *  @default null
9211
                 */
9212
                "sClass": null,
9213
 
9214
                /**
9215
                 * When DataTables calculates the column widths to assign to each column,
9216
                 * it finds the longest string in each column and then constructs a
9217
                 * temporary table and reads the widths from that. The problem with this
9218
                 * is that "mmm" is much wider then "iiii", but the latter is a longer
9219
                 * string - thus the calculation can go wrong (doing it properly and putting
9220
                 * it into an DOM object and measuring that is horribly(!) slow). Thus as
9221
                 * a "work around" we provide this option. It will append its value to the
9222
                 * text that is found to be the longest string for the column - i.e. padding.
9223
                 *  @type string
9224
                 */
9225
                "sContentPadding": null,
9226
 
9227
                /**
9228
                 * Allows a default value to be given for a column's data, and will be used
9229
                 * whenever a null data source is encountered (this can be because mData
9230
                 * is set to null, or because the data source itself is null).
9231
                 *  @type string
9232
                 *  @default null
9233
                 */
9234
                "sDefaultContent": null,
9235
 
9236
                /**
9237
                 * Name for the column, allowing reference to the column by name as well as
9238
                 * by index (needs a lookup to work by name).
9239
                 *  @type string
9240
                 */
9241
                "sName": null,
9242
 
9243
                /**
9244
                 * Custom sorting data type - defines which of the available plug-ins in
9245
                 * afnSortData the custom sorting will use - if any is defined.
9246
                 *  @type string
9247
                 *  @default std
9248
                 */
9249
                "sSortDataType": 'std',
9250
 
9251
                /**
9252
                 * Class to be applied to the header element when sorting on this column
9253
                 *  @type string
9254
                 *  @default null
9255
                 */
9256
                "sSortingClass": null,
9257
 
9258
                /**
9259
                 * Class to be applied to the header element when sorting on this column -
9260
                 * when jQuery UI theming is used.
9261
                 *  @type string
9262
                 *  @default null
9263
                 */
9264
                "sSortingClassJUI": null,
9265
 
9266
                /**
9267
                 * Title of the column - what is seen in the TH element (nTh).
9268
                 *  @type string
9269
                 */
9270
                "sTitle": null,
9271
 
9272
                /**
9273
                 * Column sorting and filtering type
9274
                 *  @type string
9275
                 *  @default null
9276
                 */
9277
                "sType": null,
9278
 
9279
                /**
9280
                 * Width of the column
9281
                 *  @type string
9282
                 *  @default null
9283
                 */
9284
                "sWidth": null,
9285
 
9286
                /**
9287
                 * Width of the column when it was first "encountered"
9288
                 *  @type string
9289
                 *  @default null
9290
                 */
9291
                "sWidthOrig": null
9292
        };
9293
 
9294
 
9295
        /*
9296
         * Developer note: The properties of the object below are given in Hungarian
9297
         * notation, that was used as the interface for DataTables prior to v1.10, however
9298
         * from v1.10 onwards the primary interface is camel case. In order to avoid
9299
         * breaking backwards compatibility utterly with this change, the Hungarian
9300
         * version is still, internally the primary interface, but is is not documented
9301
         * - hence the @name tags in each doc comment. This allows a Javascript function
9302
         * to create a map from Hungarian notation to camel case (going the other direction
9303
         * would require each property to be listed, which would at around 3K to the size
9304
         * of DataTables, while this method is about a 0.5K hit.
9305
         *
9306
         * Ultimately this does pave the way for Hungarian notation to be dropped
9307
         * completely, but that is a massive amount of work and will break current
9308
         * installs (therefore is on-hold until v2).
9309
         */
9310
 
9311
        /**
9312
         * Initialisation options that can be given to DataTables at initialisation
9313
         * time.
9314
         *  @namespace
9315
         */
9316
        DataTable.defaults = {
9317
                /**
9318
                 * An array of data to use for the table, passed in at initialisation which
9319
                 * will be used in preference to any data which is already in the DOM. This is
9320
                 * particularly useful for constructing tables purely in Javascript, for
9321
                 * example with a custom Ajax call.
9322
                 *  @type array
9323
                 *  @default null
9324
                 *
9325
                 *  @dtopt Option
9326
                 *  @name DataTable.defaults.data
9327
                 *
9328
                 *  @example
9329
                 *    // Using a 2D array data source
9330
                 *    $(document).ready( function () {
9331
                 *      $('#example').dataTable( {
9332
                 *        "data": [
9333
                 *          ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'],
9334
                 *          ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'],
9335
                 *        ],
9336
                 *        "columns": [
9337
                 *          { "title": "Engine" },
9338
                 *          { "title": "Browser" },
9339
                 *          { "title": "Platform" },
9340
                 *          { "title": "Version" },
9341
                 *          { "title": "Grade" }
9342
                 *        ]
9343
                 *      } );
9344
                 *    } );
9345
                 *
9346
                 *  @example
9347
                 *    // Using an array of objects as a data source (`data`)
9348
                 *    $(document).ready( function () {
9349
                 *      $('#example').dataTable( {
9350
                 *        "data": [
9351
                 *          {
9352
                 *            "engine":   "Trident",
9353
                 *            "browser":  "Internet Explorer 4.0",
9354
                 *            "platform": "Win 95+",
9355
                 *            "version":  4,
9356
                 *            "grade":    "X"
9357
                 *          },
9358
                 *          {
9359
                 *            "engine":   "Trident",
9360
                 *            "browser":  "Internet Explorer 5.0",
9361
                 *            "platform": "Win 95+",
9362
                 *            "version":  5,
9363
                 *            "grade":    "C"
9364
                 *          }
9365
                 *        ],
9366
                 *        "columns": [
9367
                 *          { "title": "Engine",   "data": "engine" },
9368
                 *          { "title": "Browser",  "data": "browser" },
9369
                 *          { "title": "Platform", "data": "platform" },
9370
                 *          { "title": "Version",  "data": "version" },
9371
                 *          { "title": "Grade",    "data": "grade" }
9372
                 *        ]
9373
                 *      } );
9374
                 *    } );
9375
                 */
9376
                "aaData": null,
9377
 
9378
 
9379
                /**
9380
                 * If ordering is enabled, then DataTables will perform a first pass sort on
9381
                 * initialisation. You can define which column(s) the sort is performed
9382
                 * upon, and the sorting direction, with this variable. The `sorting` array
9383
                 * should contain an array for each column to be sorted initially containing
9384
                 * the column's index and a direction string ('asc' or 'desc').
9385
                 *  @type array
9386
                 *  @default [[0,'asc']]
9387
                 *
9388
                 *  @dtopt Option
9389
                 *  @name DataTable.defaults.order
9390
                 *
9391
                 *  @example
9392
                 *    // Sort by 3rd column first, and then 4th column
9393
                 *    $(document).ready( function() {
9394
                 *      $('#example').dataTable( {
9395
                 *        "order": [[2,'asc'], [3,'desc']]
9396
                 *      } );
9397
                 *    } );
9398
                 *
9399
                 *    // No initial sorting
9400
                 *    $(document).ready( function() {
9401
                 *      $('#example').dataTable( {
9402
                 *        "order": []
9403
                 *      } );
9404
                 *    } );
9405
                 */
9406
                "aaSorting": [[0,'asc']],
9407
 
9408
 
9409
                /**
9410
                 * This parameter is basically identical to the `sorting` parameter, but
9411
                 * cannot be overridden by user interaction with the table. What this means
9412
                 * is that you could have a column (visible or hidden) which the sorting
9413
                 * will always be forced on first - any sorting after that (from the user)
9414
                 * will then be performed as required. This can be useful for grouping rows
9415
                 * together.
9416
                 *  @type array
9417
                 *  @default null
9418
                 *
9419
                 *  @dtopt Option
9420
                 *  @name DataTable.defaults.orderFixed
9421
                 *
9422
                 *  @example
9423
                 *    $(document).ready( function() {
9424
                 *      $('#example').dataTable( {
9425
                 *        "orderFixed": [[0,'asc']]
9426
                 *      } );
9427
                 *    } )
9428
                 */
9429
                "aaSortingFixed": [],
9430
 
9431
 
9432
                /**
9433
                 * DataTables can be instructed to load data to display in the table from a
9434
                 * Ajax source. This option defines how that Ajax call is made and where to.
9435
                 *
9436
                 * The `ajax` property has three different modes of operation, depending on
9437
                 * how it is defined. These are:
9438
                 *
9439
                 * * `string` - Set the URL from where the data should be loaded from.
9440
                 * * `object` - Define properties for `jQuery.ajax`.
9441
                 * * `function` - Custom data get function
9442
                 *
9443
                 * `string`
9444
                 * --------
9445
                 *
9446
                 * As a string, the `ajax` property simply defines the URL from which
9447
                 * DataTables will load data.
9448
                 *
9449
                 * `object`
9450
                 * --------
9451
                 *
9452
                 * As an object, the parameters in the object are passed to
9453
                 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control
9454
                 * of the Ajax request. DataTables has a number of default parameters which
9455
                 * you can override using this option. Please refer to the jQuery
9456
                 * documentation for a full description of the options available, although
9457
                 * the following parameters provide additional options in DataTables or
9458
                 * require special consideration:
9459
                 *
9460
                 * * `data` - As with jQuery, `data` can be provided as an object, but it
9461
                 *   can also be used as a function to manipulate the data DataTables sends
9462
                 *   to the server. The function takes a single parameter, an object of
9463
                 *   parameters with the values that DataTables has readied for sending. An
9464
                 *   object may be returned which will be merged into the DataTables
9465
                 *   defaults, or you can add the items to the object that was passed in and
9466
                 *   not return anything from the function. This supersedes `fnServerParams`
9467
                 *   from DataTables 1.9-.
9468
                 *
9469
                 * * `dataSrc` - By default DataTables will look for the property `data` (or
9470
                 *   `aaData` for compatibility with DataTables 1.9-) when obtaining data
9471
                 *   from an Ajax source or for server-side processing - this parameter
9472
                 *   allows that property to be changed. You can use Javascript dotted
9473
                 *   object notation to get a data source for multiple levels of nesting, or
9474
                 *   it my be used as a function. As a function it takes a single parameter,
9475
                 *   the JSON returned from the server, which can be manipulated as
9476
                 *   required, with the returned value being that used by DataTables as the
9477
                 *   data source for the table. This supersedes `sAjaxDataProp` from
9478
                 *   DataTables 1.9-.
9479
                 *
9480
                 * * `success` - Should not be overridden it is used internally in
9481
                 *   DataTables. To manipulate / transform the data returned by the server
9482
                 *   use `ajax.dataSrc`, or use `ajax` as a function (see below).
9483
                 *
9484
                 * `function`
9485
                 * ----------
9486
                 *
9487
                 * As a function, making the Ajax call is left up to yourself allowing
9488
                 * complete control of the Ajax request. Indeed, if desired, a method other
9489
                 * than Ajax could be used to obtain the required data, such as Web storage
9490
                 * or an AIR database.
9491
                 *
9492
                 * The function is given four parameters and no return is required. The
9493
                 * parameters are:
9494
                 *
9495
                 * 1. _object_ - Data to send to the server
9496
                 * 2. _function_ - Callback function that must be executed when the required
9497
                 *    data has been obtained. That data should be passed into the callback
9498
                 *    as the only parameter
9499
                 * 3. _object_ - DataTables settings object for the table
9500
                 *
9501
                 * Note that this supersedes `fnServerData` from DataTables 1.9-.
9502
                 *
9503
                 *  @type string|object|function
9504
                 *  @default null
9505
                 *
9506
                 *  @dtopt Option
9507
                 *  @name DataTable.defaults.ajax
9508
                 *  @since 1.10.0
9509
                 *
9510
                 * @example
9511
                 *   // Get JSON data from a file via Ajax.
9512
                 *   // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default).
9513
                 *   $('#example').dataTable( {
9514
                 *     "ajax": "data.json"
9515
                 *   } );
9516
                 *
9517
                 * @example
9518
                 *   // Get JSON data from a file via Ajax, using `dataSrc` to change
9519
                 *   // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`)
9520
                 *   $('#example').dataTable( {
9521
                 *     "ajax": {
9522
                 *       "url": "data.json",
9523
                 *       "dataSrc": "tableData"
9524
                 *     }
9525
                 *   } );
9526
                 *
9527
                 * @example
9528
                 *   // Get JSON data from a file via Ajax, using `dataSrc` to read data
9529
                 *   // from a plain array rather than an array in an object
9530
                 *   $('#example').dataTable( {
9531
                 *     "ajax": {
9532
                 *       "url": "data.json",
9533
                 *       "dataSrc": ""
9534
                 *     }
9535
                 *   } );
9536
                 *
9537
                 * @example
9538
                 *   // Manipulate the data returned from the server - add a link to data
9539
                 *   // (note this can, should, be done using `render` for the column - this
9540
                 *   // is just a simple example of how the data can be manipulated).
9541
                 *   $('#example').dataTable( {
9542
                 *     "ajax": {
9543
                 *       "url": "data.json",
9544
                 *       "dataSrc": function ( json ) {
9545
                 *         for ( var i=0, ien=json.length ; i<ien ; i++ ) {
9546
                 *           json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>';
9547
                 *         }
9548
                 *         return json;
9549
                 *       }
9550
                 *     }
9551
                 *   } );
9552
                 *
9553
                 * @example
9554
                 *   // Add data to the request
9555
                 *   $('#example').dataTable( {
9556
                 *     "ajax": {
9557
                 *       "url": "data.json",
9558
                 *       "data": function ( d ) {
9559
                 *         return {
9560
                 *           "extra_search": $('#extra').val()
9561
                 *         };
9562
                 *       }
9563
                 *     }
9564
                 *   } );
9565
                 *
9566
                 * @example
9567
                 *   // Send request as POST
9568
                 *   $('#example').dataTable( {
9569
                 *     "ajax": {
9570
                 *       "url": "data.json",
9571
                 *       "type": "POST"
9572
                 *     }
9573
                 *   } );
9574
                 *
9575
                 * @example
9576
                 *   // Get the data from localStorage (could interface with a form for
9577
                 *   // adding, editing and removing rows).
9578
                 *   $('#example').dataTable( {
9579
                 *     "ajax": function (data, callback, settings) {
9580
                 *       callback(
9581
                 *         JSON.parse( localStorage.getItem('dataTablesData') )
9582
                 *       );
9583
                 *     }
9584
                 *   } );
9585
                 */
9586
                "ajax": null,
9587
 
9588
 
9589
                /**
9590
                 * This parameter allows you to readily specify the entries in the length drop
9591
                 * down menu that DataTables shows when pagination is enabled. It can be
9592
                 * either a 1D array of options which will be used for both the displayed
9593
                 * option and the value, or a 2D array which will use the array in the first
9594
                 * position as the value, and the array in the second position as the
9595
                 * displayed options (useful for language strings such as 'All').
9596
                 *
9597
                 * Note that the `pageLength` property will be automatically set to the
9598
                 * first value given in this array, unless `pageLength` is also provided.
9599
                 *  @type array
9600
                 *  @default [ 10, 25, 50, 100 ]
9601
                 *
9602
                 *  @dtopt Option
9603
                 *  @name DataTable.defaults.lengthMenu
9604
                 *
9605
                 *  @example
9606
                 *    $(document).ready( function() {
9607
                 *      $('#example').dataTable( {
9608
                 *        "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]]
9609
                 *      } );
9610
                 *    } );
9611
                 */
9612
                "aLengthMenu": [ 10, 25, 50, 100 ],
9613
 
9614
 
9615
                /**
9616
                 * The `columns` option in the initialisation parameter allows you to define
9617
                 * details about the way individual columns behave. For a full list of
9618
                 * column options that can be set, please see
9619
                 * {@link DataTable.defaults.column}. Note that if you use `columns` to
9620
                 * define your columns, you must have an entry in the array for every single
9621
                 * column that you have in your table (these can be null if you don't which
9622
                 * to specify any options).
9623
                 *  @member
9624
                 *
9625
                 *  @name DataTable.defaults.column
9626
                 */
9627
                "aoColumns": null,
9628
 
9629
                /**
9630
                 * Very similar to `columns`, `columnDefs` allows you to target a specific
9631
                 * column, multiple columns, or all columns, using the `targets` property of
9632
                 * each object in the array. This allows great flexibility when creating
9633
                 * tables, as the `columnDefs` arrays can be of any length, targeting the
9634
                 * columns you specifically want. `columnDefs` may use any of the column
9635
                 * options available: {@link DataTable.defaults.column}, but it _must_
9636
                 * have `targets` defined in each object in the array. Values in the `targets`
9637
                 * array may be:
9638
                 *   <ul>
9639
                 *     <li>a string - class name will be matched on the TH for the column</li>
9640
                 *     <li>0 or a positive integer - column index counting from the left</li>
9641
                 *     <li>a negative integer - column index counting from the right</li>
9642
                 *     <li>the string "_all" - all columns (i.e. assign a default)</li>
9643
                 *   </ul>
9644
                 *  @member
9645
                 *
9646
                 *  @name DataTable.defaults.columnDefs
9647
                 */
9648
                "aoColumnDefs": null,
9649
 
9650
 
9651
                /**
9652
                 * Basically the same as `search`, this parameter defines the individual column
9653
                 * filtering state at initialisation time. The array must be of the same size
9654
                 * as the number of columns, and each element be an object with the parameters
9655
                 * `search` and `escapeRegex` (the latter is optional). 'null' is also
9656
                 * accepted and the default will be used.
9657
                 *  @type array
9658
                 *  @default []
9659
                 *
9660
                 *  @dtopt Option
9661
                 *  @name DataTable.defaults.searchCols
9662
                 *
9663
                 *  @example
9664
                 *    $(document).ready( function() {
9665
                 *      $('#example').dataTable( {
9666
                 *        "searchCols": [
9667
                 *          null,
9668
                 *          { "search": "My filter" },
9669
                 *          null,
9670
                 *          { "search": "^[0-9]", "escapeRegex": false }
9671
                 *        ]
9672
                 *      } );
9673
                 *    } )
9674
                 */
9675
                "aoSearchCols": [],
9676
 
9677
 
9678
                /**
9679
                 * An array of CSS classes that should be applied to displayed rows. This
9680
                 * array may be of any length, and DataTables will apply each class
9681
                 * sequentially, looping when required.
9682
                 *  @type array
9683
                 *  @default null <i>Will take the values determined by the `oClasses.stripe*`
9684
                 *    options</i>
9685
                 *
9686
                 *  @dtopt Option
9687
                 *  @name DataTable.defaults.stripeClasses
9688
                 *
9689
                 *  @example
9690
                 *    $(document).ready( function() {
9691
                 *      $('#example').dataTable( {
9692
                 *        "stripeClasses": [ 'strip1', 'strip2', 'strip3' ]
9693
                 *      } );
9694
                 *    } )
9695
                 */
9696
                "asStripeClasses": null,
9697
 
9698
 
9699
                /**
9700
                 * Enable or disable automatic column width calculation. This can be disabled
9701
                 * as an optimisation (it takes some time to calculate the widths) if the
9702
                 * tables widths are passed in using `columns`.
9703
                 *  @type boolean
9704
                 *  @default true
9705
                 *
9706
                 *  @dtopt Features
9707
                 *  @name DataTable.defaults.autoWidth
9708
                 *
9709
                 *  @example
9710
                 *    $(document).ready( function () {
9711
                 *      $('#example').dataTable( {
9712
                 *        "autoWidth": false
9713
                 *      } );
9714
                 *    } );
9715
                 */
9716
                "bAutoWidth": true,
9717
 
9718
 
9719
                /**
9720
                 * Deferred rendering can provide DataTables with a huge speed boost when you
9721
                 * are using an Ajax or JS data source for the table. This option, when set to
9722
                 * true, will cause DataTables to defer the creation of the table elements for
9723
                 * each row until they are needed for a draw - saving a significant amount of
9724
                 * time.
9725
                 *  @type boolean
9726
                 *  @default false
9727
                 *
9728
                 *  @dtopt Features
9729
                 *  @name DataTable.defaults.deferRender
9730
                 *
9731
                 *  @example
9732
                 *    $(document).ready( function() {
9733
                 *      $('#example').dataTable( {
9734
                 *        "ajax": "sources/arrays.txt",
9735
                 *        "deferRender": true
9736
                 *      } );
9737
                 *    } );
9738
                 */
9739
                "bDeferRender": false,
9740
 
9741
 
9742
                /**
9743
                 * Replace a DataTable which matches the given selector and replace it with
9744
                 * one which has the properties of the new initialisation object passed. If no
9745
                 * table matches the selector, then the new DataTable will be constructed as
9746
                 * per normal.
9747
                 *  @type boolean
9748
                 *  @default false
9749
                 *
9750
                 *  @dtopt Options
9751
                 *  @name DataTable.defaults.destroy
9752
                 *
9753
                 *  @example
9754
                 *    $(document).ready( function() {
9755
                 *      $('#example').dataTable( {
9756
                 *        "srollY": "200px",
9757
                 *        "paginate": false
9758
                 *      } );
9759
                 *
9760
                 *      // Some time later....
9761
                 *      $('#example').dataTable( {
9762
                 *        "filter": false,
9763
                 *        "destroy": true
9764
                 *      } );
9765
                 *    } );
9766
                 */
9767
                "bDestroy": false,
9768
 
9769
 
9770
                /**
9771
                 * Enable or disable filtering of data. Filtering in DataTables is "smart" in
9772
                 * that it allows the end user to input multiple words (space separated) and
9773
                 * will match a row containing those words, even if not in the order that was
9774
                 * specified (this allow matching across multiple columns). Note that if you
9775
                 * wish to use filtering in DataTables this must remain 'true' - to remove the
9776
                 * default filtering input box and retain filtering abilities, please use
9777
                 * {@link DataTable.defaults.dom}.
9778
                 *  @type boolean
9779
                 *  @default true
9780
                 *
9781
                 *  @dtopt Features
9782
                 *  @name DataTable.defaults.searching
9783
                 *
9784
                 *  @example
9785
                 *    $(document).ready( function () {
9786
                 *      $('#example').dataTable( {
9787
                 *        "searching": false
9788
                 *      } );
9789
                 *    } );
9790
                 */
9791
                "bFilter": true,
9792
 
9793
 
9794
                /**
9795
                 * Enable or disable the table information display. This shows information
9796
                 * about the data that is currently visible on the page, including information
9797
                 * about filtered data if that action is being performed.
9798
                 *  @type boolean
9799
                 *  @default true
9800
                 *
9801
                 *  @dtopt Features
9802
                 *  @name DataTable.defaults.info
9803
                 *
9804
                 *  @example
9805
                 *    $(document).ready( function () {
9806
                 *      $('#example').dataTable( {
9807
                 *        "info": false
9808
                 *      } );
9809
                 *    } );
9810
                 */
9811
                "bInfo": true,
9812
 
9813
 
9814
                /**
9815
                 * Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some
9816
                 * slightly different and additional mark-up from what DataTables has
9817
                 * traditionally used).
9818
                 *  @type boolean
9819
                 *  @default false
9820
                 *
9821
                 *  @dtopt Features
9822
                 *  @name DataTable.defaults.jQueryUI
9823
                 *
9824
                 *  @example
9825
                 *    $(document).ready( function() {
9826
                 *      $('#example').dataTable( {
9827
                 *        "jQueryUI": true
9828
                 *      } );
9829
                 *    } );
9830
                 */
9831
                "bJQueryUI": false,
9832
 
9833
 
9834
                /**
9835
                 * Allows the end user to select the size of a formatted page from a select
9836
                 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`).
9837
                 *  @type boolean
9838
                 *  @default true
9839
                 *
9840
                 *  @dtopt Features
9841
                 *  @name DataTable.defaults.lengthChange
9842
                 *
9843
                 *  @example
9844
                 *    $(document).ready( function () {
9845
                 *      $('#example').dataTable( {
9846
                 *        "lengthChange": false
9847
                 *      } );
9848
                 *    } );
9849
                 */
9850
                "bLengthChange": true,
9851
 
9852
 
9853
                /**
9854
                 * Enable or disable pagination.
9855
                 *  @type boolean
9856
                 *  @default true
9857
                 *
9858
                 *  @dtopt Features
9859
                 *  @name DataTable.defaults.paging
9860
                 *
9861
                 *  @example
9862
                 *    $(document).ready( function () {
9863
                 *      $('#example').dataTable( {
9864
                 *        "paging": false
9865
                 *      } );
9866
                 *    } );
9867
                 */
9868
                "bPaginate": true,
9869
 
9870
 
9871
                /**
9872
                 * Enable or disable the display of a 'processing' indicator when the table is
9873
                 * being processed (e.g. a sort). This is particularly useful for tables with
9874
                 * large amounts of data where it can take a noticeable amount of time to sort
9875
                 * the entries.
9876
                 *  @type boolean
9877
                 *  @default false
9878
                 *
9879
                 *  @dtopt Features
9880
                 *  @name DataTable.defaults.processing
9881
                 *
9882
                 *  @example
9883
                 *    $(document).ready( function () {
9884
                 *      $('#example').dataTable( {
9885
                 *        "processing": true
9886
                 *      } );
9887
                 *    } );
9888
                 */
9889
                "bProcessing": false,
9890
 
9891
 
9892
                /**
9893
                 * Retrieve the DataTables object for the given selector. Note that if the
9894
                 * table has already been initialised, this parameter will cause DataTables
9895
                 * to simply return the object that has already been set up - it will not take
9896
                 * account of any changes you might have made to the initialisation object
9897
                 * passed to DataTables (setting this parameter to true is an acknowledgement
9898
                 * that you understand this). `destroy` can be used to reinitialise a table if
9899
                 * you need.
9900
                 *  @type boolean
9901
                 *  @default false
9902
                 *
9903
                 *  @dtopt Options
9904
                 *  @name DataTable.defaults.retrieve
9905
                 *
9906
                 *  @example
9907
                 *    $(document).ready( function() {
9908
                 *      initTable();
9909
                 *      tableActions();
9910
                 *    } );
9911
                 *
9912
                 *    function initTable ()
9913
                 *    {
9914
                 *      return $('#example').dataTable( {
9915
                 *        "scrollY": "200px",
9916
                 *        "paginate": false,
9917
                 *        "retrieve": true
9918
                 *      } );
9919
                 *    }
9920
                 *
9921
                 *    function tableActions ()
9922
                 *    {
9923
                 *      var table = initTable();
9924
                 *      // perform API operations with oTable
9925
                 *    }
9926
                 */
9927
                "bRetrieve": false,
9928
 
9929
 
9930
                /**
9931
                 * When vertical (y) scrolling is enabled, DataTables will force the height of
9932
                 * the table's viewport to the given height at all times (useful for layout).
9933
                 * However, this can look odd when filtering data down to a small data set,
9934
                 * and the footer is left "floating" further down. This parameter (when
9935
                 * enabled) will cause DataTables to collapse the table's viewport down when
9936
                 * the result set will fit within the given Y height.
9937
                 *  @type boolean
9938
                 *  @default false
9939
                 *
9940
                 *  @dtopt Options
9941
                 *  @name DataTable.defaults.scrollCollapse
9942
                 *
9943
                 *  @example
9944
                 *    $(document).ready( function() {
9945
                 *      $('#example').dataTable( {
9946
                 *        "scrollY": "200",
9947
                 *        "scrollCollapse": true
9948
                 *      } );
9949
                 *    } );
9950
                 */
9951
                "bScrollCollapse": false,
9952
 
9953
 
9954
                /**
9955
                 * Configure DataTables to use server-side processing. Note that the
9956
                 * `ajax` parameter must also be given in order to give DataTables a
9957
                 * source to obtain the required data for each draw.
9958
                 *  @type boolean
9959
                 *  @default false
9960
                 *
9961
                 *  @dtopt Features
9962
                 *  @dtopt Server-side
9963
                 *  @name DataTable.defaults.serverSide
9964
                 *
9965
                 *  @example
9966
                 *    $(document).ready( function () {
9967
                 *      $('#example').dataTable( {
9968
                 *        "serverSide": true,
9969
                 *        "ajax": "xhr.php"
9970
                 *      } );
9971
                 *    } );
9972
                 */
9973
                "bServerSide": false,
9974
 
9975
 
9976
                /**
9977
                 * Enable or disable sorting of columns. Sorting of individual columns can be
9978
                 * disabled by the `sortable` option for each column.
9979
                 *  @type boolean
9980
                 *  @default true
9981
                 *
9982
                 *  @dtopt Features
9983
                 *  @name DataTable.defaults.ordering
9984
                 *
9985
                 *  @example
9986
                 *    $(document).ready( function () {
9987
                 *      $('#example').dataTable( {
9988
                 *        "ordering": false
9989
                 *      } );
9990
                 *    } );
9991
                 */
9992
                "bSort": true,
9993
 
9994
 
9995
                /**
9996
                 * Enable or display DataTables' ability to sort multiple columns at the
9997
                 * same time (activated by shift-click by the user).
9998
                 *  @type boolean
9999
                 *  @default true
10000
                 *
10001
                 *  @dtopt Options
10002
                 *  @name DataTable.defaults.orderMulti
10003
                 *
10004
                 *  @example
10005
                 *    // Disable multiple column sorting ability
10006
                 *    $(document).ready( function () {
10007
                 *      $('#example').dataTable( {
10008
                 *        "orderMulti": false
10009
                 *      } );
10010
                 *    } );
10011
                 */
10012
                "bSortMulti": true,
10013
 
10014
 
10015
                /**
10016
                 * Allows control over whether DataTables should use the top (true) unique
10017
                 * cell that is found for a single column, or the bottom (false - default).
10018
                 * This is useful when using complex headers.
10019
                 *  @type boolean
10020
                 *  @default false
10021
                 *
10022
                 *  @dtopt Options
10023
                 *  @name DataTable.defaults.orderCellsTop
10024
                 *
10025
                 *  @example
10026
                 *    $(document).ready( function() {
10027
                 *      $('#example').dataTable( {
10028
                 *        "orderCellsTop": true
10029
                 *      } );
10030
                 *    } );
10031
                 */
10032
                "bSortCellsTop": false,
10033
 
10034
 
10035
                /**
10036
                 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and
10037
                 * `sorting\_3` to the columns which are currently being sorted on. This is
10038
                 * presented as a feature switch as it can increase processing time (while
10039
                 * classes are removed and added) so for large data sets you might want to
10040
                 * turn this off.
10041
                 *  @type boolean
10042
                 *  @default true
10043
                 *
10044
                 *  @dtopt Features
10045
                 *  @name DataTable.defaults.orderClasses
10046
                 *
10047
                 *  @example
10048
                 *    $(document).ready( function () {
10049
                 *      $('#example').dataTable( {
10050
                 *        "orderClasses": false
10051
                 *      } );
10052
                 *    } );
10053
                 */
10054
                "bSortClasses": true,
10055
 
10056
 
10057
                /**
10058
                 * Enable or disable state saving. When enabled HTML5 `localStorage` will be
10059
                 * used to save table display information such as pagination information,
10060
                 * display length, filtering and sorting. As such when the end user reloads
10061
                 * the page the display display will match what thy had previously set up.
10062
                 *
10063
                 * Due to the use of `localStorage` the default state saving is not supported
10064
                 * in IE6 or 7. If state saving is required in those browsers, use
10065
                 * `stateSaveCallback` to provide a storage solution such as cookies.
10066
                 *  @type boolean
10067
                 *  @default false
10068
                 *
10069
                 *  @dtopt Features
10070
                 *  @name DataTable.defaults.stateSave
10071
                 *
10072
                 *  @example
10073
                 *    $(document).ready( function () {
10074
                 *      $('#example').dataTable( {
10075
                 *        "stateSave": true
10076
                 *      } );
10077
                 *    } );
10078
                 */
10079
                "bStateSave": false,
10080
 
10081
 
10082
                /**
10083
                 * This function is called when a TR element is created (and all TD child
10084
                 * elements have been inserted), or registered if using a DOM source, allowing
10085
                 * manipulation of the TR element (adding classes etc).
10086
                 *  @type function
10087
                 *  @param {node} row "TR" element for the current row
10088
                 *  @param {array} data Raw data array for this row
10089
                 *  @param {int} dataIndex The index of this row in the internal aoData array
10090
                 *
10091
                 *  @dtopt Callbacks
10092
                 *  @name DataTable.defaults.createdRow
10093
                 *
10094
                 *  @example
10095
                 *    $(document).ready( function() {
10096
                 *      $('#example').dataTable( {
10097
                 *        "createdRow": function( row, data, dataIndex ) {
10098
                 *          // Bold the grade for all 'A' grade browsers
10099
                 *          if ( data[4] == "A" )
10100
                 *          {
10101
                 *            $('td:eq(4)', row).html( '<b>A</b>' );
10102
                 *          }
10103
                 *        }
10104
                 *      } );
10105
                 *    } );
10106
                 */
10107
                "fnCreatedRow": null,
10108
 
10109
 
10110
                /**
10111
                 * This function is called on every 'draw' event, and allows you to
10112
                 * dynamically modify any aspect you want about the created DOM.
10113
                 *  @type function
10114
                 *  @param {object} settings DataTables settings object
10115
                 *
10116
                 *  @dtopt Callbacks
10117
                 *  @name DataTable.defaults.drawCallback
10118
                 *
10119
                 *  @example
10120
                 *    $(document).ready( function() {
10121
                 *      $('#example').dataTable( {
10122
                 *        "drawCallback": function( settings ) {
10123
                 *          alert( 'DataTables has redrawn the table' );
10124
                 *        }
10125
                 *      } );
10126
                 *    } );
10127
                 */
10128
                "fnDrawCallback": null,
10129
 
10130
 
10131
                /**
10132
                 * Identical to fnHeaderCallback() but for the table footer this function
10133
                 * allows you to modify the table footer on every 'draw' event.
10134
                 *  @type function
10135
                 *  @param {node} foot "TR" element for the footer
10136
                 *  @param {array} data Full table data (as derived from the original HTML)
10137
                 *  @param {int} start Index for the current display starting point in the
10138
                 *    display array
10139
                 *  @param {int} end Index for the current display ending point in the
10140
                 *    display array
10141
                 *  @param {array int} display Index array to translate the visual position
10142
                 *    to the full data array
10143
                 *
10144
                 *  @dtopt Callbacks
10145
                 *  @name DataTable.defaults.footerCallback
10146
                 *
10147
                 *  @example
10148
                 *    $(document).ready( function() {
10149
                 *      $('#example').dataTable( {
10150
                 *        "footerCallback": function( tfoot, data, start, end, display ) {
10151
                 *          tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start;
10152
                 *        }
10153
                 *      } );
10154
                 *    } )
10155
                 */
10156
                "fnFooterCallback": null,
10157
 
10158
 
10159
                /**
10160
                 * When rendering large numbers in the information element for the table
10161
                 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers
10162
                 * to have a comma separator for the 'thousands' units (e.g. 1 million is
10163
                 * rendered as "1,000,000") to help readability for the end user. This
10164
                 * function will override the default method DataTables uses.
10165
                 *  @type function
10166
                 *  @member
10167
                 *  @param {int} toFormat number to be formatted
10168
                 *  @returns {string} formatted string for DataTables to show the number
10169
                 *
10170
                 *  @dtopt Callbacks
10171
                 *  @name DataTable.defaults.formatNumber
10172
                 *
10173
                 *  @example
10174
                 *    // Format a number using a single quote for the separator (note that
10175
                 *    // this can also be done with the language.thousands option)
10176
                 *    $(document).ready( function() {
10177
                 *      $('#example').dataTable( {
10178
                 *        "formatNumber": function ( toFormat ) {
10179
                 *          return toFormat.toString().replace(
10180
                 *            /\B(?=(\d{3})+(?!\d))/g, "'"
10181
                 *          );
10182
                 *        };
10183
                 *      } );
10184
                 *    } );
10185
                 */
10186
                "fnFormatNumber": function ( toFormat ) {
10187
                        return toFormat.toString().replace(
10188
                                /\B(?=(\d{3})+(?!\d))/g,
10189
                                this.oLanguage.sThousands
10190
                        );
10191
                },
10192
 
10193
 
10194
                /**
10195
                 * This function is called on every 'draw' event, and allows you to
10196
                 * dynamically modify the header row. This can be used to calculate and
10197
                 * display useful information about the table.
10198
                 *  @type function
10199
                 *  @param {node} head "TR" element for the header
10200
                 *  @param {array} data Full table data (as derived from the original HTML)
10201
                 *  @param {int} start Index for the current display starting point in the
10202
                 *    display array
10203
                 *  @param {int} end Index for the current display ending point in the
10204
                 *    display array
10205
                 *  @param {array int} display Index array to translate the visual position
10206
                 *    to the full data array
10207
                 *
10208
                 *  @dtopt Callbacks
10209
                 *  @name DataTable.defaults.headerCallback
10210
                 *
10211
                 *  @example
10212
                 *    $(document).ready( function() {
10213
                 *      $('#example').dataTable( {
10214
                 *        "fheaderCallback": function( head, data, start, end, display ) {
10215
                 *          head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records";
10216
                 *        }
10217
                 *      } );
10218
                 *    } )
10219
                 */
10220
                "fnHeaderCallback": null,
10221
 
10222
 
10223
                /**
10224
                 * The information element can be used to convey information about the current
10225
                 * state of the table. Although the internationalisation options presented by
10226
                 * DataTables are quite capable of dealing with most customisations, there may
10227
                 * be times where you wish to customise the string further. This callback
10228
                 * allows you to do exactly that.
10229
                 *  @type function
10230
                 *  @param {object} oSettings DataTables settings object
10231
                 *  @param {int} start Starting position in data for the draw
10232
                 *  @param {int} end End position in data for the draw
10233
                 *  @param {int} max Total number of rows in the table (regardless of
10234
                 *    filtering)
10235
                 *  @param {int} total Total number of rows in the data set, after filtering
10236
                 *  @param {string} pre The string that DataTables has formatted using it's
10237
                 *    own rules
10238
                 *  @returns {string} The string to be displayed in the information element.
10239
                 *
10240
                 *  @dtopt Callbacks
10241
                 *  @name DataTable.defaults.infoCallback
10242
                 *
10243
                 *  @example
10244
                 *    $('#example').dataTable( {
10245
                 *      "infoCallback": function( settings, start, end, max, total, pre ) {
10246
                 *        return start +" to "+ end;
10247
                 *      }
10248
                 *    } );
10249
                 */
10250
                "fnInfoCallback": null,
10251
 
10252
 
10253
                /**
10254
                 * Called when the table has been initialised. Normally DataTables will
10255
                 * initialise sequentially and there will be no need for this function,
10256
                 * however, this does not hold true when using external language information
10257
                 * since that is obtained using an async XHR call.
10258
                 *  @type function
10259
                 *  @param {object} settings DataTables settings object
10260
                 *  @param {object} json The JSON object request from the server - only
10261
                 *    present if client-side Ajax sourced data is used
10262
                 *
10263
                 *  @dtopt Callbacks
10264
                 *  @name DataTable.defaults.initComplete
10265
                 *
10266
                 *  @example
10267
                 *    $(document).ready( function() {
10268
                 *      $('#example').dataTable( {
10269
                 *        "initComplete": function(settings, json) {
10270
                 *          alert( 'DataTables has finished its initialisation.' );
10271
                 *        }
10272
                 *      } );
10273
                 *    } )
10274
                 */
10275
                "fnInitComplete": null,
10276
 
10277
 
10278
                /**
10279
                 * Called at the very start of each table draw and can be used to cancel the
10280
                 * draw by returning false, any other return (including undefined) results in
10281
                 * the full draw occurring).
10282
                 *  @type function
10283
                 *  @param {object} settings DataTables settings object
10284
                 *  @returns {boolean} False will cancel the draw, anything else (including no
10285
                 *    return) will allow it to complete.
10286
                 *
10287
                 *  @dtopt Callbacks
10288
                 *  @name DataTable.defaults.preDrawCallback
10289
                 *
10290
                 *  @example
10291
                 *    $(document).ready( function() {
10292
                 *      $('#example').dataTable( {
10293
                 *        "preDrawCallback": function( settings ) {
10294
                 *          if ( $('#test').val() == 1 ) {
10295
                 *            return false;
10296
                 *          }
10297
                 *        }
10298
                 *      } );
10299
                 *    } );
10300
                 */
10301
                "fnPreDrawCallback": null,
10302
 
10303
 
10304
                /**
10305
                 * This function allows you to 'post process' each row after it have been
10306
                 * generated for each table draw, but before it is rendered on screen. This
10307
                 * function might be used for setting the row class name etc.
10308
                 *  @type function
10309
                 *  @param {node} row "TR" element for the current row
10310
                 *  @param {array} data Raw data array for this row
10311
                 *  @param {int} displayIndex The display index for the current table draw
10312
                 *  @param {int} displayIndexFull The index of the data in the full list of
10313
                 *    rows (after filtering)
10314
                 *
10315
                 *  @dtopt Callbacks
10316
                 *  @name DataTable.defaults.rowCallback
10317
                 *
10318
                 *  @example
10319
                 *    $(document).ready( function() {
10320
                 *      $('#example').dataTable( {
10321
                 *        "rowCallback": function( row, data, displayIndex, displayIndexFull ) {
10322
                 *          // Bold the grade for all 'A' grade browsers
10323
                 *          if ( data[4] == "A" ) {
10324
                 *            $('td:eq(4)', row).html( '<b>A</b>' );
10325
                 *          }
10326
                 *        }
10327
                 *      } );
10328
                 *    } );
10329
                 */
10330
                "fnRowCallback": null,
10331
 
10332
 
10333
                /**
10334
                 * __Deprecated__ The functionality provided by this parameter has now been
10335
                 * superseded by that provided through `ajax`, which should be used instead.
10336
                 *
10337
                 * This parameter allows you to override the default function which obtains
10338
                 * the data from the server so something more suitable for your application.
10339
                 * For example you could use POST data, or pull information from a Gears or
10340
                 * AIR database.
10341
                 *  @type function
10342
                 *  @member
10343
                 *  @param {string} source HTTP source to obtain the data from (`ajax`)
10344
                 *  @param {array} data A key/value pair object containing the data to send
10345
                 *    to the server
10346
                 *  @param {function} callback to be called on completion of the data get
10347
                 *    process that will draw the data on the page.
10348
                 *  @param {object} settings DataTables settings object
10349
                 *
10350
                 *  @dtopt Callbacks
10351
                 *  @dtopt Server-side
10352
                 *  @name DataTable.defaults.serverData
10353
                 *
10354
                 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10355
                 */
10356
                "fnServerData": null,
10357
 
10358
 
10359
                /**
10360
                 * __Deprecated__ The functionality provided by this parameter has now been
10361
                 * superseded by that provided through `ajax`, which should be used instead.
10362
                 *
10363
                 *  It is often useful to send extra data to the server when making an Ajax
10364
                 * request - for example custom filtering information, and this callback
10365
                 * function makes it trivial to send extra information to the server. The
10366
                 * passed in parameter is the data set that has been constructed by
10367
                 * DataTables, and you can add to this or modify it as you require.
10368
                 *  @type function
10369
                 *  @param {array} data Data array (array of objects which are name/value
10370
                 *    pairs) that has been constructed by DataTables and will be sent to the
10371
                 *    server. In the case of Ajax sourced data with server-side processing
10372
                 *    this will be an empty array, for server-side processing there will be a
10373
                 *    significant number of parameters!
10374
                 *  @returns {undefined} Ensure that you modify the data array passed in,
10375
                 *    as this is passed by reference.
10376
                 *
10377
                 *  @dtopt Callbacks
10378
                 *  @dtopt Server-side
10379
                 *  @name DataTable.defaults.serverParams
10380
                 *
10381
                 *  @deprecated 1.10. Please use `ajax` for this functionality now.
10382
                 */
10383
                "fnServerParams": null,
10384
 
10385
 
10386
                /**
10387
                 * Load the table state. With this function you can define from where, and how, the
10388
                 * state of a table is loaded. By default DataTables will load from `localStorage`
10389
                 * but you might wish to use a server-side database or cookies.
10390
                 *  @type function
10391
                 *  @member
10392
                 *  @param {object} settings DataTables settings object
10393
                 *  @return {object} The DataTables state object to be loaded
10394
                 *
10395
                 *  @dtopt Callbacks
10396
                 *  @name DataTable.defaults.stateLoadCallback
10397
                 *
10398
                 *  @example
10399
                 *    $(document).ready( function() {
10400
                 *      $('#example').dataTable( {
10401
                 *        "stateSave": true,
10402
                 *        "stateLoadCallback": function (settings) {
10403
                 *          var o;
10404
                 *
10405
                 *          // Send an Ajax request to the server to get the data. Note that
10406
                 *          // this is a synchronous request.
10407
                 *          $.ajax( {
10408
                 *            "url": "/state_load",
10409
                 *            "async": false,
10410
                 *            "dataType": "json",
10411
                 *            "success": function (json) {
10412
                 *              o = json;
10413
                 *            }
10414
                 *          } );
10415
                 *
10416
                 *          return o;
10417
                 *        }
10418
                 *      } );
10419
                 *    } );
10420
                 */
10421
                "fnStateLoadCallback": function ( settings ) {
10422
                        try {
10423
                                return JSON.parse(
10424
                                        (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem(
10425
                                                'DataTables_'+settings.sInstance+'_'+location.pathname
10426
                                        )
10427
                                );
10428
                        } catch (e) {}
10429
                },
10430
 
10431
 
10432
                /**
10433
                 * Callback which allows modification of the saved state prior to loading that state.
10434
                 * This callback is called when the table is loading state from the stored data, but
10435
                 * prior to the settings object being modified by the saved state. Note that for
10436
                 * plug-in authors, you should use the `stateLoadParams` event to load parameters for
10437
                 * a plug-in.
10438
                 *  @type function
10439
                 *  @param {object} settings DataTables settings object
10440
                 *  @param {object} data The state object that is to be loaded
10441
                 *
10442
                 *  @dtopt Callbacks
10443
                 *  @name DataTable.defaults.stateLoadParams
10444
                 *
10445
                 *  @example
10446
                 *    // Remove a saved filter, so filtering is never loaded
10447
                 *    $(document).ready( function() {
10448
                 *      $('#example').dataTable( {
10449
                 *        "stateSave": true,
10450
                 *        "stateLoadParams": function (settings, data) {
10451
                 *          data.oSearch.sSearch = "";
10452
                 *        }
10453
                 *      } );
10454
                 *    } );
10455
                 *
10456
                 *  @example
10457
                 *    // Disallow state loading by returning false
10458
                 *    $(document).ready( function() {
10459
                 *      $('#example').dataTable( {
10460
                 *        "stateSave": true,
10461
                 *        "stateLoadParams": function (settings, data) {
10462
                 *          return false;
10463
                 *        }
10464
                 *      } );
10465
                 *    } );
10466
                 */
10467
                "fnStateLoadParams": null,
10468
 
10469
 
10470
                /**
10471
                 * Callback that is called when the state has been loaded from the state saving method
10472
                 * and the DataTables settings object has been modified as a result of the loaded state.
10473
                 *  @type function
10474
                 *  @param {object} settings DataTables settings object
10475
                 *  @param {object} data The state object that was loaded
10476
                 *
10477
                 *  @dtopt Callbacks
10478
                 *  @name DataTable.defaults.stateLoaded
10479
                 *
10480
                 *  @example
10481
                 *    // Show an alert with the filtering value that was saved
10482
                 *    $(document).ready( function() {
10483
                 *      $('#example').dataTable( {
10484
                 *        "stateSave": true,
10485
                 *        "stateLoaded": function (settings, data) {
10486
                 *          alert( 'Saved filter was: '+data.oSearch.sSearch );
10487
                 *        }
10488
                 *      } );
10489
                 *    } );
10490
                 */
10491
                "fnStateLoaded": null,
10492
 
10493
 
10494
                /**
10495
                 * Save the table state. This function allows you to define where and how the state
10496
                 * information for the table is stored By default DataTables will use `localStorage`
10497
                 * but you might wish to use a server-side database or cookies.
10498
                 *  @type function
10499
                 *  @member
10500
                 *  @param {object} settings DataTables settings object
10501
                 *  @param {object} data The state object to be saved
10502
                 *
10503
                 *  @dtopt Callbacks
10504
                 *  @name DataTable.defaults.stateSaveCallback
10505
                 *
10506
                 *  @example
10507
                 *    $(document).ready( function() {
10508
                 *      $('#example').dataTable( {
10509
                 *        "stateSave": true,
10510
                 *        "stateSaveCallback": function (settings, data) {
10511
                 *          // Send an Ajax request to the server with the state object
10512
                 *          $.ajax( {
10513
                 *            "url": "/state_save",
10514
                 *            "data": data,
10515
                 *            "dataType": "json",
10516
                 *            "method": "POST"
10517
                 *            "success": function () {}
10518
                 *          } );
10519
                 *        }
10520
                 *      } );
10521
                 *    } );
10522
                 */
10523
                "fnStateSaveCallback": function ( settings, data ) {
10524
                        try {
10525
                                (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem(
10526
                                        'DataTables_'+settings.sInstance+'_'+location.pathname,
10527
                                        JSON.stringify( data )
10528
                                );
10529
                        } catch (e) {}
10530
                },
10531
 
10532
 
10533
                /**
10534
                 * Callback which allows modification of the state to be saved. Called when the table
10535
                 * has changed state a new state save is required. This method allows modification of
10536
                 * the state saving object prior to actually doing the save, including addition or
10537
                 * other state properties or modification. Note that for plug-in authors, you should
10538
                 * use the `stateSaveParams` event to save parameters for a plug-in.
10539
                 *  @type function
10540
                 *  @param {object} settings DataTables settings object
10541
                 *  @param {object} data The state object to be saved
10542
                 *
10543
                 *  @dtopt Callbacks
10544
                 *  @name DataTable.defaults.stateSaveParams
10545
                 *
10546
                 *  @example
10547
                 *    // Remove a saved filter, so filtering is never saved
10548
                 *    $(document).ready( function() {
10549
                 *      $('#example').dataTable( {
10550
                 *        "stateSave": true,
10551
                 *        "stateSaveParams": function (settings, data) {
10552
                 *          data.oSearch.sSearch = "";
10553
                 *        }
10554
                 *      } );
10555
                 *    } );
10556
                 */
10557
                "fnStateSaveParams": null,
10558
 
10559
 
10560
                /**
10561
                 * Duration for which the saved state information is considered valid. After this period
10562
                 * has elapsed the state will be returned to the default.
10563
                 * Value is given in seconds.
10564
                 *  @type int
10565
                 *  @default 7200 <i>(2 hours)</i>
10566
                 *
10567
                 *  @dtopt Options
10568
                 *  @name DataTable.defaults.stateDuration
10569
                 *
10570
                 *  @example
10571
                 *    $(document).ready( function() {
10572
                 *      $('#example').dataTable( {
10573
                 *        "stateDuration": 60*60*24; // 1 day
10574
                 *      } );
10575
                 *    } )
10576
                 */
10577
                "iStateDuration": 7200,
10578
 
10579
 
10580
                /**
10581
                 * When enabled DataTables will not make a request to the server for the first
10582
                 * page draw - rather it will use the data already on the page (no sorting etc
10583
                 * will be applied to it), thus saving on an XHR at load time. `deferLoading`
10584
                 * is used to indicate that deferred loading is required, but it is also used
10585
                 * to tell DataTables how many records there are in the full table (allowing
10586
                 * the information element and pagination to be displayed correctly). In the case
10587
                 * where a filtering is applied to the table on initial load, this can be
10588
                 * indicated by giving the parameter as an array, where the first element is
10589
                 * the number of records available after filtering and the second element is the
10590
                 * number of records without filtering (allowing the table information element
10591
                 * to be shown correctly).
10592
                 *  @type int | array
10593
                 *  @default null
10594
                 *
10595
                 *  @dtopt Options
10596
                 *  @name DataTable.defaults.deferLoading
10597
                 *
10598
                 *  @example
10599
                 *    // 57 records available in the table, no filtering applied
10600
                 *    $(document).ready( function() {
10601
                 *      $('#example').dataTable( {
10602
                 *        "serverSide": true,
10603
                 *        "ajax": "scripts/server_processing.php",
10604
                 *        "deferLoading": 57
10605
                 *      } );
10606
                 *    } );
10607
                 *
10608
                 *  @example
10609
                 *    // 57 records after filtering, 100 without filtering (an initial filter applied)
10610
                 *    $(document).ready( function() {
10611
                 *      $('#example').dataTable( {
10612
                 *        "serverSide": true,
10613
                 *        "ajax": "scripts/server_processing.php",
10614
                 *        "deferLoading": [ 57, 100 ],
10615
                 *        "search": {
10616
                 *          "search": "my_filter"
10617
                 *        }
10618
                 *      } );
10619
                 *    } );
10620
                 */
10621
                "iDeferLoading": null,
10622
 
10623
 
10624
                /**
10625
                 * Number of rows to display on a single page when using pagination. If
10626
                 * feature enabled (`lengthChange`) then the end user will be able to override
10627
                 * this to a custom setting using a pop-up menu.
10628
                 *  @type int
10629
                 *  @default 10
10630
                 *
10631
                 *  @dtopt Options
10632
                 *  @name DataTable.defaults.pageLength
10633
                 *
10634
                 *  @example
10635
                 *    $(document).ready( function() {
10636
                 *      $('#example').dataTable( {
10637
                 *        "pageLength": 50
10638
                 *      } );
10639
                 *    } )
10640
                 */
10641
                "iDisplayLength": 10,
10642
 
10643
 
10644
                /**
10645
                 * Define the starting point for data display when using DataTables with
10646
                 * pagination. Note that this parameter is the number of records, rather than
10647
                 * the page number, so if you have 10 records per page and want to start on
10648
                 * the third page, it should be "20".
10649
                 *  @type int
10650
                 *  @default 0
10651
                 *
10652
                 *  @dtopt Options
10653
                 *  @name DataTable.defaults.displayStart
10654
                 *
10655
                 *  @example
10656
                 *    $(document).ready( function() {
10657
                 *      $('#example').dataTable( {
10658
                 *        "displayStart": 20
10659
                 *      } );
10660
                 *    } )
10661
                 */
10662
                "iDisplayStart": 0,
10663
 
10664
 
10665
                /**
10666
                 * By default DataTables allows keyboard navigation of the table (sorting, paging,
10667
                 * and filtering) by adding a `tabindex` attribute to the required elements. This
10668
                 * allows you to tab through the controls and press the enter key to activate them.
10669
                 * The tabindex is default 0, meaning that the tab follows the flow of the document.
10670
                 * You can overrule this using this parameter if you wish. Use a value of -1 to
10671
                 * disable built-in keyboard navigation.
10672
                 *  @type int
10673
                 *  @default 0
10674
                 *
10675
                 *  @dtopt Options
10676
                 *  @name DataTable.defaults.tabIndex
10677
                 *
10678
                 *  @example
10679
                 *    $(document).ready( function() {
10680
                 *      $('#example').dataTable( {
10681
                 *        "tabIndex": 1
10682
                 *      } );
10683
                 *    } );
10684
                 */
10685
                "iTabIndex": 0,
10686
 
10687
 
10688
                /**
10689
                 * Classes that DataTables assigns to the various components and features
10690
                 * that it adds to the HTML table. This allows classes to be configured
10691
                 * during initialisation in addition to through the static
10692
                 * {@link DataTable.ext.oStdClasses} object).
10693
                 *  @namespace
10694
                 *  @name DataTable.defaults.classes
10695
                 */
10696
                "oClasses": {},
10697
 
10698
 
10699
                /**
10700
                 * All strings that DataTables uses in the user interface that it creates
10701
                 * are defined in this object, allowing you to modified them individually or
10702
                 * completely replace them all as required.
10703
                 *  @namespace
10704
                 *  @name DataTable.defaults.language
10705
                 */
10706
                "oLanguage": {
10707
                        /**
10708
                         * Strings that are used for WAI-ARIA labels and controls only (these are not
10709
                         * actually visible on the page, but will be read by screenreaders, and thus
10710
                         * must be internationalised as well).
10711
                         *  @namespace
10712
                         *  @name DataTable.defaults.language.aria
10713
                         */
10714
                        "oAria": {
10715
                                /**
10716
                                 * ARIA label that is added to the table headers when the column may be
10717
                                 * sorted ascending by activing the column (click or return when focused).
10718
                                 * Note that the column header is prefixed to this string.
10719
                                 *  @type string
10720
                                 *  @default : activate to sort column ascending
10721
                                 *
10722
                                 *  @dtopt Language
10723
                                 *  @name DataTable.defaults.language.aria.sortAscending
10724
                                 *
10725
                                 *  @example
10726
                                 *    $(document).ready( function() {
10727
                                 *      $('#example').dataTable( {
10728
                                 *        "language": {
10729
                                 *          "aria": {
10730
                                 *            "sortAscending": " - click/return to sort ascending"
10731
                                 *          }
10732
                                 *        }
10733
                                 *      } );
10734
                                 *    } );
10735
                                 */
10736
                                "sSortAscending": ": activate to sort column ascending",
10737
 
10738
                                /**
10739
                                 * ARIA label that is added to the table headers when the column may be
10740
                                 * sorted descending by activing the column (click or return when focused).
10741
                                 * Note that the column header is prefixed to this string.
10742
                                 *  @type string
10743
                                 *  @default : activate to sort column ascending
10744
                                 *
10745
                                 *  @dtopt Language
10746
                                 *  @name DataTable.defaults.language.aria.sortDescending
10747
                                 *
10748
                                 *  @example
10749
                                 *    $(document).ready( function() {
10750
                                 *      $('#example').dataTable( {
10751
                                 *        "language": {
10752
                                 *          "aria": {
10753
                                 *            "sortDescending": " - click/return to sort descending"
10754
                                 *          }
10755
                                 *        }
10756
                                 *      } );
10757
                                 *    } );
10758
                                 */
10759
                                "sSortDescending": ": activate to sort column descending"
10760
                        },
10761
 
10762
                        /**
10763
                         * Pagination string used by DataTables for the built-in pagination
10764
                         * control types.
10765
                         *  @namespace
10766
                         *  @name DataTable.defaults.language.paginate
10767
                         */
10768
                        "oPaginate": {
10769
                                /**
10770
                                 * Text to use when using the 'full_numbers' type of pagination for the
10771
                                 * button to take the user to the first page.
10772
                                 *  @type string
10773
                                 *  @default First
10774
                                 *
10775
                                 *  @dtopt Language
10776
                                 *  @name DataTable.defaults.language.paginate.first
10777
                                 *
10778
                                 *  @example
10779
                                 *    $(document).ready( function() {
10780
                                 *      $('#example').dataTable( {
10781
                                 *        "language": {
10782
                                 *          "paginate": {
10783
                                 *            "first": "First page"
10784
                                 *          }
10785
                                 *        }
10786
                                 *      } );
10787
                                 *    } );
10788
                                 */
10789
                                "sFirst": "First",
10790
 
10791
 
10792
                                /**
10793
                                 * Text to use when using the 'full_numbers' type of pagination for the
10794
                                 * button to take the user to the last page.
10795
                                 *  @type string
10796
                                 *  @default Last
10797
                                 *
10798
                                 *  @dtopt Language
10799
                                 *  @name DataTable.defaults.language.paginate.last
10800
                                 *
10801
                                 *  @example
10802
                                 *    $(document).ready( function() {
10803
                                 *      $('#example').dataTable( {
10804
                                 *        "language": {
10805
                                 *          "paginate": {
10806
                                 *            "last": "Last page"
10807
                                 *          }
10808
                                 *        }
10809
                                 *      } );
10810
                                 *    } );
10811
                                 */
10812
                                "sLast": "Last",
10813
 
10814
 
10815
                                /**
10816
                                 * Text to use for the 'next' pagination button (to take the user to the
10817
                                 * next page).
10818
                                 *  @type string
10819
                                 *  @default Next
10820
                                 *
10821
                                 *  @dtopt Language
10822
                                 *  @name DataTable.defaults.language.paginate.next
10823
                                 *
10824
                                 *  @example
10825
                                 *    $(document).ready( function() {
10826
                                 *      $('#example').dataTable( {
10827
                                 *        "language": {
10828
                                 *          "paginate": {
10829
                                 *            "next": "Next page"
10830
                                 *          }
10831
                                 *        }
10832
                                 *      } );
10833
                                 *    } );
10834
                                 */
10835
                                "sNext": "Next",
10836
 
10837
 
10838
                                /**
10839
                                 * Text to use for the 'previous' pagination button (to take the user to
10840
                                 * the previous page).
10841
                                 *  @type string
10842
                                 *  @default Previous
10843
                                 *
10844
                                 *  @dtopt Language
10845
                                 *  @name DataTable.defaults.language.paginate.previous
10846
                                 *
10847
                                 *  @example
10848
                                 *    $(document).ready( function() {
10849
                                 *      $('#example').dataTable( {
10850
                                 *        "language": {
10851
                                 *          "paginate": {
10852
                                 *            "previous": "Previous page"
10853
                                 *          }
10854
                                 *        }
10855
                                 *      } );
10856
                                 *    } );
10857
                                 */
10858
                                "sPrevious": "Previous"
10859
                        },
10860
 
10861
                        /**
10862
                         * This string is shown in preference to `zeroRecords` when the table is
10863
                         * empty of data (regardless of filtering). Note that this is an optional
10864
                         * parameter - if it is not given, the value of `zeroRecords` will be used
10865
                         * instead (either the default or given value).
10866
                         *  @type string
10867
                         *  @default No data available in table
10868
                         *
10869
                         *  @dtopt Language
10870
                         *  @name DataTable.defaults.language.emptyTable
10871
                         *
10872
                         *  @example
10873
                         *    $(document).ready( function() {
10874
                         *      $('#example').dataTable( {
10875
                         *        "language": {
10876
                         *          "emptyTable": "No data available in table"
10877
                         *        }
10878
                         *      } );
10879
                         *    } );
10880
                         */
10881
                        "sEmptyTable": "No data available in table",
10882
 
10883
 
10884
                        /**
10885
                         * This string gives information to the end user about the information
10886
                         * that is current on display on the page. The following tokens can be
10887
                         * used in the string and will be dynamically replaced as the table
10888
                         * display updates. This tokens can be placed anywhere in the string, or
10889
                         * removed as needed by the language requires:
10890
                         *
10891
                         * * `\_START\_` - Display index of the first record on the current page
10892
                         * * `\_END\_` - Display index of the last record on the current page
10893
                         * * `\_TOTAL\_` - Number of records in the table after filtering
10894
                         * * `\_MAX\_` - Number of records in the table without filtering
10895
                         * * `\_PAGE\_` - Current page number
10896
                         * * `\_PAGES\_` - Total number of pages of data in the table
10897
                         *
10898
                         *  @type string
10899
                         *  @default Showing _START_ to _END_ of _TOTAL_ entries
10900
                         *
10901
                         *  @dtopt Language
10902
                         *  @name DataTable.defaults.language.info
10903
                         *
10904
                         *  @example
10905
                         *    $(document).ready( function() {
10906
                         *      $('#example').dataTable( {
10907
                         *        "language": {
10908
                         *          "info": "Showing page _PAGE_ of _PAGES_"
10909
                         *        }
10910
                         *      } );
10911
                         *    } );
10912
                         */
10913
                        "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries",
10914
 
10915
 
10916
                        /**
10917
                         * Display information string for when the table is empty. Typically the
10918
                         * format of this string should match `info`.
10919
                         *  @type string
10920
                         *  @default Showing 0 to 0 of 0 entries
10921
                         *
10922
                         *  @dtopt Language
10923
                         *  @name DataTable.defaults.language.infoEmpty
10924
                         *
10925
                         *  @example
10926
                         *    $(document).ready( function() {
10927
                         *      $('#example').dataTable( {
10928
                         *        "language": {
10929
                         *          "infoEmpty": "No entries to show"
10930
                         *        }
10931
                         *      } );
10932
                         *    } );
10933
                         */
10934
                        "sInfoEmpty": "Showing 0 to 0 of 0 entries",
10935
 
10936
 
10937
                        /**
10938
                         * When a user filters the information in a table, this string is appended
10939
                         * to the information (`info`) to give an idea of how strong the filtering
10940
                         * is. The variable _MAX_ is dynamically updated.
10941
                         *  @type string
10942
                         *  @default (filtered from _MAX_ total entries)
10943
                         *
10944
                         *  @dtopt Language
10945
                         *  @name DataTable.defaults.language.infoFiltered
10946
                         *
10947
                         *  @example
10948
                         *    $(document).ready( function() {
10949
                         *      $('#example').dataTable( {
10950
                         *        "language": {
10951
                         *          "infoFiltered": " - filtering from _MAX_ records"
10952
                         *        }
10953
                         *      } );
10954
                         *    } );
10955
                         */
10956
                        "sInfoFiltered": "(filtered from _MAX_ total entries)",
10957
 
10958
 
10959
                        /**
10960
                         * If can be useful to append extra information to the info string at times,
10961
                         * and this variable does exactly that. This information will be appended to
10962
                         * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are
10963
                         * being used) at all times.
10964
                         *  @type string
10965
                         *  @default <i>Empty string</i>
10966
                         *
10967
                         *  @dtopt Language
10968
                         *  @name DataTable.defaults.language.infoPostFix
10969
                         *
10970
                         *  @example
10971
                         *    $(document).ready( function() {
10972
                         *      $('#example').dataTable( {
10973
                         *        "language": {
10974
                         *          "infoPostFix": "All records shown are derived from real information."
10975
                         *        }
10976
                         *      } );
10977
                         *    } );
10978
                         */
10979
                        "sInfoPostFix": "",
10980
 
10981
 
10982
                        /**
10983
                         * This decimal place operator is a little different from the other
10984
                         * language options since DataTables doesn't output floating point
10985
                         * numbers, so it won't ever use this for display of a number. Rather,
10986
                         * what this parameter does is modify the sort methods of the table so
10987
                         * that numbers which are in a format which has a character other than
10988
                         * a period (`.`) as a decimal place will be sorted numerically.
10989
                         *
10990
                         * Note that numbers with different decimal places cannot be shown in
10991
                         * the same table and still be sortable, the table must be consistent.
10992
                         * However, multiple different tables on the page can use different
10993
                         * decimal place characters.
10994
                         *  @type string
10995
                         *  @default
10996
                         *
10997
                         *  @dtopt Language
10998
                         *  @name DataTable.defaults.language.decimal
10999
                         *
11000
                         *  @example
11001
                         *    $(document).ready( function() {
11002
                         *      $('#example').dataTable( {
11003
                         *        "language": {
11004
                         *          "decimal": ","
11005
                         *          "thousands": "."
11006
                         *        }
11007
                         *      } );
11008
                         *    } );
11009
                         */
11010
                        "sDecimal": "",
11011
 
11012
 
11013
                        /**
11014
                         * DataTables has a build in number formatter (`formatNumber`) which is
11015
                         * used to format large numbers that are used in the table information.
11016
                         * By default a comma is used, but this can be trivially changed to any
11017
                         * character you wish with this parameter.
11018
                         *  @type string
11019
                         *  @default ,
11020
                         *
11021
                         *  @dtopt Language
11022
                         *  @name DataTable.defaults.language.thousands
11023
                         *
11024
                         *  @example
11025
                         *    $(document).ready( function() {
11026
                         *      $('#example').dataTable( {
11027
                         *        "language": {
11028
                         *          "thousands": "'"
11029
                         *        }
11030
                         *      } );
11031
                         *    } );
11032
                         */
11033
                        "sThousands": ",",
11034
 
11035
 
11036
                        /**
11037
                         * Detail the action that will be taken when the drop down menu for the
11038
                         * pagination length option is changed. The '_MENU_' variable is replaced
11039
                         * with a default select list of 10, 25, 50 and 100, and can be replaced
11040
                         * with a custom select box if required.
11041
                         *  @type string
11042
                         *  @default Show _MENU_ entries
11043
                         *
11044
                         *  @dtopt Language
11045
                         *  @name DataTable.defaults.language.lengthMenu
11046
                         *
11047
                         *  @example
11048
                         *    // Language change only
11049
                         *    $(document).ready( function() {
11050
                         *      $('#example').dataTable( {
11051
                         *        "language": {
11052
                         *          "lengthMenu": "Display _MENU_ records"
11053
                         *        }
11054
                         *      } );
11055
                         *    } );
11056
                         *
11057
                         *  @example
11058
                         *    // Language and options change
11059
                         *    $(document).ready( function() {
11060
                         *      $('#example').dataTable( {
11061
                         *        "language": {
11062
                         *          "lengthMenu": 'Display <select>'+
11063
                         *            '<option value="10">10</option>'+
11064
                         *            '<option value="20">20</option>'+
11065
                         *            '<option value="30">30</option>'+
11066
                         *            '<option value="40">40</option>'+
11067
                         *            '<option value="50">50</option>'+
11068
                         *            '<option value="-1">All</option>'+
11069
                         *            '</select> records'
11070
                         *        }
11071
                         *      } );
11072
                         *    } );
11073
                         */
11074
                        "sLengthMenu": "Show _MENU_ entries",
11075
 
11076
 
11077
                        /**
11078
                         * When using Ajax sourced data and during the first draw when DataTables is
11079
                         * gathering the data, this message is shown in an empty row in the table to
11080
                         * indicate to the end user the the data is being loaded. Note that this
11081
                         * parameter is not used when loading data by server-side processing, just
11082
                         * Ajax sourced data with client-side processing.
11083
                         *  @type string
11084
                         *  @default Loading...
11085
                         *
11086
                         *  @dtopt Language
11087
                         *  @name DataTable.defaults.language.loadingRecords
11088
                         *
11089
                         *  @example
11090
                         *    $(document).ready( function() {
11091
                         *      $('#example').dataTable( {
11092
                         *        "language": {
11093
                         *          "loadingRecords": "Please wait - loading..."
11094
                         *        }
11095
                         *      } );
11096
                         *    } );
11097
                         */
11098
                        "sLoadingRecords": "Loading...",
11099
 
11100
 
11101
                        /**
11102
                         * Text which is displayed when the table is processing a user action
11103
                         * (usually a sort command or similar).
11104
                         *  @type string
11105
                         *  @default Processing...
11106
                         *
11107
                         *  @dtopt Language
11108
                         *  @name DataTable.defaults.language.processing
11109
                         *
11110
                         *  @example
11111
                         *    $(document).ready( function() {
11112
                         *      $('#example').dataTable( {
11113
                         *        "language": {
11114
                         *          "processing": "DataTables is currently busy"
11115
                         *        }
11116
                         *      } );
11117
                         *    } );
11118
                         */
11119
                        "sProcessing": "Processing...",
11120
 
11121
 
11122
                        /**
11123
                         * Details the actions that will be taken when the user types into the
11124
                         * filtering input text box. The variable "_INPUT_", if used in the string,
11125
                         * is replaced with the HTML text box for the filtering input allowing
11126
                         * control over where it appears in the string. If "_INPUT_" is not given
11127
                         * then the input box is appended to the string automatically.
11128
                         *  @type string
11129
                         *  @default Search:
11130
                         *
11131
                         *  @dtopt Language
11132
                         *  @name DataTable.defaults.language.search
11133
                         *
11134
                         *  @example
11135
                         *    // Input text box will be appended at the end automatically
11136
                         *    $(document).ready( function() {
11137
                         *      $('#example').dataTable( {
11138
                         *        "language": {
11139
                         *          "search": "Filter records:"
11140
                         *        }
11141
                         *      } );
11142
                         *    } );
11143
                         *
11144
                         *  @example
11145
                         *    // Specify where the filter should appear
11146
                         *    $(document).ready( function() {
11147
                         *      $('#example').dataTable( {
11148
                         *        "language": {
11149
                         *          "search": "Apply filter _INPUT_ to table"
11150
                         *        }
11151
                         *      } );
11152
                         *    } );
11153
                         */
11154
                        "sSearch": "Search:",
11155
 
11156
 
11157
                        /**
11158
                         * Assign a `placeholder` attribute to the search `input` element
11159
                         *  @type string
11160
                         *  @default
11161
                         *
11162
                         *  @dtopt Language
11163
                         *  @name DataTable.defaults.language.searchPlaceholder
11164
                         */
11165
                        "sSearchPlaceholder": "",
11166
 
11167
 
11168
                        /**
11169
                         * All of the language information can be stored in a file on the
11170
                         * server-side, which DataTables will look up if this parameter is passed.
11171
                         * It must store the URL of the language file, which is in a JSON format,
11172
                         * and the object has the same properties as the oLanguage object in the
11173
                         * initialiser object (i.e. the above parameters). Please refer to one of
11174
                         * the example language files to see how this works in action.
11175
                         *  @type string
11176
                         *  @default <i>Empty string - i.e. disabled</i>
11177
                         *
11178
                         *  @dtopt Language
11179
                         *  @name DataTable.defaults.language.url
11180
                         *
11181
                         *  @example
11182
                         *    $(document).ready( function() {
11183
                         *      $('#example').dataTable( {
11184
                         *        "language": {
11185
                         *          "url": "http://www.sprymedia.co.uk/dataTables/lang.txt"
11186
                         *        }
11187
                         *      } );
11188
                         *    } );
11189
                         */
11190
                        "sUrl": "",
11191
 
11192
 
11193
                        /**
11194
                         * Text shown inside the table records when the is no information to be
11195
                         * displayed after filtering. `emptyTable` is shown when there is simply no
11196
                         * information in the table at all (regardless of filtering).
11197
                         *  @type string
11198
                         *  @default No matching records found
11199
                         *
11200
                         *  @dtopt Language
11201
                         *  @name DataTable.defaults.language.zeroRecords
11202
                         *
11203
                         *  @example
11204
                         *    $(document).ready( function() {
11205
                         *      $('#example').dataTable( {
11206
                         *        "language": {
11207
                         *          "zeroRecords": "No records to display"
11208
                         *        }
11209
                         *      } );
11210
                         *    } );
11211
                         */
11212
                        "sZeroRecords": "No matching records found"
11213
                },
11214
 
11215
 
11216
                /**
11217
                 * This parameter allows you to have define the global filtering state at
11218
                 * initialisation time. As an object the `search` parameter must be
11219
                 * defined, but all other parameters are optional. When `regex` is true,
11220
                 * the search string will be treated as a regular expression, when false
11221
                 * (default) it will be treated as a straight string. When `smart`
11222
                 * DataTables will use it's smart filtering methods (to word match at
11223
                 * any point in the data), when false this will not be done.
11224
                 *  @namespace
11225
                 *  @extends DataTable.models.oSearch
11226
                 *
11227
                 *  @dtopt Options
11228
                 *  @name DataTable.defaults.search
11229
                 *
11230
                 *  @example
11231
                 *    $(document).ready( function() {
11232
                 *      $('#example').dataTable( {
11233
                 *        "search": {"search": "Initial search"}
11234
                 *      } );
11235
                 *    } )
11236
                 */
11237
                "oSearch": $.extend( {}, DataTable.models.oSearch ),
11238
 
11239
 
11240
                /**
11241
                 * __Deprecated__ The functionality provided by this parameter has now been
11242
                 * superseded by that provided through `ajax`, which should be used instead.
11243
                 *
11244
                 * By default DataTables will look for the property `data` (or `aaData` for
11245
                 * compatibility with DataTables 1.9-) when obtaining data from an Ajax
11246
                 * source or for server-side processing - this parameter allows that
11247
                 * property to be changed. You can use Javascript dotted object notation to
11248
                 * get a data source for multiple levels of nesting.
11249
                 *  @type string
11250
                 *  @default data
11251
                 *
11252
                 *  @dtopt Options
11253
                 *  @dtopt Server-side
11254
                 *  @name DataTable.defaults.ajaxDataProp
11255
                 *
11256
                 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11257
                 */
11258
                "sAjaxDataProp": "data",
11259
 
11260
 
11261
                /**
11262
                 * __Deprecated__ The functionality provided by this parameter has now been
11263
                 * superseded by that provided through `ajax`, which should be used instead.
11264
                 *
11265
                 * You can instruct DataTables to load data from an external
11266
                 * source using this parameter (use aData if you want to pass data in you
11267
                 * already have). Simply provide a url a JSON object can be obtained from.
11268
                 *  @type string
11269
                 *  @default null
11270
                 *
11271
                 *  @dtopt Options
11272
                 *  @dtopt Server-side
11273
                 *  @name DataTable.defaults.ajaxSource
11274
                 *
11275
                 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11276
                 */
11277
                "sAjaxSource": null,
11278
 
11279
 
11280
                /**
11281
                 * This initialisation variable allows you to specify exactly where in the
11282
                 * DOM you want DataTables to inject the various controls it adds to the page
11283
                 * (for example you might want the pagination controls at the top of the
11284
                 * table). DIV elements (with or without a custom class) can also be added to
11285
                 * aid styling. The follow syntax is used:
11286
                 *   <ul>
11287
                 *     <li>The following options are allowed:
11288
                 *       <ul>
11289
                 *         <li>'l' - Length changing</li>
11290
                 *         <li>'f' - Filtering input</li>
11291
                 *         <li>'t' - The table!</li>
11292
                 *         <li>'i' - Information</li>
11293
                 *         <li>'p' - Pagination</li>
11294
                 *         <li>'r' - pRocessing</li>
11295
                 *       </ul>
11296
                 *     </li>
11297
                 *     <li>The following constants are allowed:
11298
                 *       <ul>
11299
                 *         <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li>
11300
                 *         <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li>
11301
                 *       </ul>
11302
                 *     </li>
11303
                 *     <li>The following syntax is expected:
11304
                 *       <ul>
11305
                 *         <li>'&lt;' and '&gt;' - div elements</li>
11306
                 *         <li>'&lt;"class" and '&gt;' - div with a class</li>
11307
                 *         <li>'&lt;"#id" and '&gt;' - div with an ID</li>
11308
                 *       </ul>
11309
                 *     </li>
11310
                 *     <li>Examples:
11311
                 *       <ul>
11312
                 *         <li>'&lt;"wrapper"flipt&gt;'</li>
11313
                 *         <li>'&lt;lf&lt;t&gt;ip&gt;'</li>
11314
                 *       </ul>
11315
                 *     </li>
11316
                 *   </ul>
11317
                 *  @type string
11318
                 *  @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b>
11319
                 *    <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i>
11320
                 *
11321
                 *  @dtopt Options
11322
                 *  @name DataTable.defaults.dom
11323
                 *
11324
                 *  @example
11325
                 *    $(document).ready( function() {
11326
                 *      $('#example').dataTable( {
11327
                 *        "dom": '&lt;"top"i&gt;rt&lt;"bottom"flp&gt;&lt;"clear"&gt;'
11328
                 *      } );
11329
                 *    } );
11330
                 */
11331
                "sDom": "lfrtip",
11332
 
11333
 
11334
                /**
11335
                 * DataTables features four different built-in options for the buttons to
11336
                 * display for pagination control:
11337
                 *
11338
                 * * `simple` - 'Previous' and 'Next' buttons only
11339
                 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers
11340
                 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons
11341
                 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus
11342
                 *   page numbers
11343
                 *  
11344
                 * Further methods can be added using {@link DataTable.ext.oPagination}.
11345
                 *  @type string
11346
                 *  @default simple_numbers
11347
                 *
11348
                 *  @dtopt Options
11349
                 *  @name DataTable.defaults.pagingType
11350
                 *
11351
                 *  @example
11352
                 *    $(document).ready( function() {
11353
                 *      $('#example').dataTable( {
11354
                 *        "pagingType": "full_numbers"
11355
                 *      } );
11356
                 *    } )
11357
                 */
11358
                "sPaginationType": "simple_numbers",
11359
 
11360
 
11361
                /**
11362
                 * Enable horizontal scrolling. When a table is too wide to fit into a
11363
                 * certain layout, or you have a large number of columns in the table, you
11364
                 * can enable x-scrolling to show the table in a viewport, which can be
11365
                 * scrolled. This property can be `true` which will allow the table to
11366
                 * scroll horizontally when needed, or any CSS unit, or a number (in which
11367
                 * case it will be treated as a pixel measurement). Setting as simply `true`
11368
                 * is recommended.
11369
                 *  @type boolean|string
11370
                 *  @default <i>blank string - i.e. disabled</i>
11371
                 *
11372
                 *  @dtopt Features
11373
                 *  @name DataTable.defaults.scrollX
11374
                 *
11375
                 *  @example
11376
                 *    $(document).ready( function() {
11377
                 *      $('#example').dataTable( {
11378
                 *        "scrollX": true,
11379
                 *        "scrollCollapse": true
11380
                 *      } );
11381
                 *    } );
11382
                 */
11383
                "sScrollX": "",
11384
 
11385
 
11386
                /**
11387
                 * This property can be used to force a DataTable to use more width than it
11388
                 * might otherwise do when x-scrolling is enabled. For example if you have a
11389
                 * table which requires to be well spaced, this parameter is useful for
11390
                 * "over-sizing" the table, and thus forcing scrolling. This property can by
11391
                 * any CSS unit, or a number (in which case it will be treated as a pixel
11392
                 * measurement).
11393
                 *  @type string
11394
                 *  @default <i>blank string - i.e. disabled</i>
11395
                 *
11396
                 *  @dtopt Options
11397
                 *  @name DataTable.defaults.scrollXInner
11398
                 *
11399
                 *  @example
11400
                 *    $(document).ready( function() {
11401
                 *      $('#example').dataTable( {
11402
                 *        "scrollX": "100%",
11403
                 *        "scrollXInner": "110%"
11404
                 *      } );
11405
                 *    } );
11406
                 */
11407
                "sScrollXInner": "",
11408
 
11409
 
11410
                /**
11411
                 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable
11412
                 * to the given height, and enable scrolling for any data which overflows the
11413
                 * current viewport. This can be used as an alternative to paging to display
11414
                 * a lot of data in a small area (although paging and scrolling can both be
11415
                 * enabled at the same time). This property can be any CSS unit, or a number
11416
                 * (in which case it will be treated as a pixel measurement).
11417
                 *  @type string
11418
                 *  @default <i>blank string - i.e. disabled</i>
11419
                 *
11420
                 *  @dtopt Features
11421
                 *  @name DataTable.defaults.scrollY
11422
                 *
11423
                 *  @example
11424
                 *    $(document).ready( function() {
11425
                 *      $('#example').dataTable( {
11426
                 *        "scrollY": "200px",
11427
                 *        "paginate": false
11428
                 *      } );
11429
                 *    } );
11430
                 */
11431
                "sScrollY": "",
11432
 
11433
 
11434
                /**
11435
                 * __Deprecated__ The functionality provided by this parameter has now been
11436
                 * superseded by that provided through `ajax`, which should be used instead.
11437
                 *
11438
                 * Set the HTTP method that is used to make the Ajax call for server-side
11439
                 * processing or Ajax sourced data.
11440
                 *  @type string
11441
                 *  @default GET
11442
                 *
11443
                 *  @dtopt Options
11444
                 *  @dtopt Server-side
11445
                 *  @name DataTable.defaults.serverMethod
11446
                 *
11447
                 *  @deprecated 1.10. Please use `ajax` for this functionality now.
11448
                 */
11449
                "sServerMethod": "GET",
11450
 
11451
 
11452
                /**
11453
                 * DataTables makes use of renderers when displaying HTML elements for
11454
                 * a table. These renderers can be added or modified by plug-ins to
11455
                 * generate suitable mark-up for a site. For example the Bootstrap
11456
                 * integration plug-in for DataTables uses a paging button renderer to
11457
                 * display pagination buttons in the mark-up required by Bootstrap.
11458
                 *
11459
                 * For further information about the renderers available see
11460
                 * DataTable.ext.renderer
11461
                 *  @type string|object
11462
                 *  @default null
11463
                 *
11464
                 *  @name DataTable.defaults.renderer
11465
                 *
11466
                 */
11467
                "renderer": null
11468
        };
11469
 
11470
        _fnHungarianMap( DataTable.defaults );
11471
 
11472
 
11473
 
11474
        /*
11475
         * Developer note - See note in model.defaults.js about the use of Hungarian
11476
         * notation and camel case.
11477
         */
11478
 
11479
        /**
11480
         * Column options that can be given to DataTables at initialisation time.
11481
         *  @namespace
11482
         */
11483
        DataTable.defaults.column = {
11484
                /**
11485
                 * Define which column(s) an order will occur on for this column. This
11486
                 * allows a column's ordering to take multiple columns into account when
11487
                 * doing a sort or use the data from a different column. For example first
11488
                 * name / last name columns make sense to do a multi-column sort over the
11489
                 * two columns.
11490
                 *  @type array|int
11491
                 *  @default null <i>Takes the value of the column index automatically</i>
11492
                 *
11493
                 *  @name DataTable.defaults.column.orderData
11494
                 *  @dtopt Columns
11495
                 *
11496
                 *  @example
11497
                 *    // Using `columnDefs`
11498
                 *    $(document).ready( function() {
11499
                 *      $('#example').dataTable( {
11500
                 *        "columnDefs": [
11501
                 *          { "orderData": [ 0, 1 ], "targets": [ 0 ] },
11502
                 *          { "orderData": [ 1, 0 ], "targets": [ 1 ] },
11503
                 *          { "orderData": 2, "targets": [ 2 ] }
11504
                 *        ]
11505
                 *      } );
11506
                 *    } );
11507
                 *
11508
                 *  @example
11509
                 *    // Using `columns`
11510
                 *    $(document).ready( function() {
11511
                 *      $('#example').dataTable( {
11512
                 *        "columns": [
11513
                 *          { "orderData": [ 0, 1 ] },
11514
                 *          { "orderData": [ 1, 0 ] },
11515
                 *          { "orderData": 2 },
11516
                 *          null,
11517
                 *          null
11518
                 *        ]
11519
                 *      } );
11520
                 *    } );
11521
                 */
11522
                "aDataSort": null,
11523
                "iDataSort": -1,
11524
 
11525
 
11526
                /**
11527
                 * You can control the default ordering direction, and even alter the
11528
                 * behaviour of the sort handler (i.e. only allow ascending ordering etc)
11529
                 * using this parameter.
11530
                 *  @type array
11531
                 *  @default [ 'asc', 'desc' ]
11532
                 *
11533
                 *  @name DataTable.defaults.column.orderSequence
11534
                 *  @dtopt Columns
11535
                 *
11536
                 *  @example
11537
                 *    // Using `columnDefs`
11538
                 *    $(document).ready( function() {
11539
                 *      $('#example').dataTable( {
11540
                 *        "columnDefs": [
11541
                 *          { "orderSequence": [ "asc" ], "targets": [ 1 ] },
11542
                 *          { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] },
11543
                 *          { "orderSequence": [ "desc" ], "targets": [ 3 ] }
11544
                 *        ]
11545
                 *      } );
11546
                 *    } );
11547
                 *
11548
                 *  @example
11549
                 *    // Using `columns`
11550
                 *    $(document).ready( function() {
11551
                 *      $('#example').dataTable( {
11552
                 *        "columns": [
11553
                 *          null,
11554
                 *          { "orderSequence": [ "asc" ] },
11555
                 *          { "orderSequence": [ "desc", "asc", "asc" ] },
11556
                 *          { "orderSequence": [ "desc" ] },
11557
                 *          null
11558
                 *        ]
11559
                 *      } );
11560
                 *    } );
11561
                 */
11562
                "asSorting": [ 'asc', 'desc' ],
11563
 
11564
 
11565
                /**
11566
                 * Enable or disable filtering on the data in this column.
11567
                 *  @type boolean
11568
                 *  @default true
11569
                 *
11570
                 *  @name DataTable.defaults.column.searchable
11571
                 *  @dtopt Columns
11572
                 *
11573
                 *  @example
11574
                 *    // Using `columnDefs`
11575
                 *    $(document).ready( function() {
11576
                 *      $('#example').dataTable( {
11577
                 *        "columnDefs": [
11578
                 *          { "searchable": false, "targets": [ 0 ] }
11579
                 *        ] } );
11580
                 *    } );
11581
                 *
11582
                 *  @example
11583
                 *    // Using `columns`
11584
                 *    $(document).ready( function() {
11585
                 *      $('#example').dataTable( {
11586
                 *        "columns": [
11587
                 *          { "searchable": false },
11588
                 *          null,
11589
                 *          null,
11590
                 *          null,
11591
                 *          null
11592
                 *        ] } );
11593
                 *    } );
11594
                 */
11595
                "bSearchable": true,
11596
 
11597
 
11598
                /**
11599
                 * Enable or disable ordering on this column.
11600
                 *  @type boolean
11601
                 *  @default true
11602
                 *
11603
                 *  @name DataTable.defaults.column.orderable
11604
                 *  @dtopt Columns
11605
                 *
11606
                 *  @example
11607
                 *    // Using `columnDefs`
11608
                 *    $(document).ready( function() {
11609
                 *      $('#example').dataTable( {
11610
                 *        "columnDefs": [
11611
                 *          { "orderable": false, "targets": [ 0 ] }
11612
                 *        ] } );
11613
                 *    } );
11614
                 *
11615
                 *  @example
11616
                 *    // Using `columns`
11617
                 *    $(document).ready( function() {
11618
                 *      $('#example').dataTable( {
11619
                 *        "columns": [
11620
                 *          { "orderable": false },
11621
                 *          null,
11622
                 *          null,
11623
                 *          null,
11624
                 *          null
11625
                 *        ] } );
11626
                 *    } );
11627
                 */
11628
                "bSortable": true,
11629
 
11630
 
11631
                /**
11632
                 * Enable or disable the display of this column.
11633
                 *  @type boolean
11634
                 *  @default true
11635
                 *
11636
                 *  @name DataTable.defaults.column.visible
11637
                 *  @dtopt Columns
11638
                 *
11639
                 *  @example
11640
                 *    // Using `columnDefs`
11641
                 *    $(document).ready( function() {
11642
                 *      $('#example').dataTable( {
11643
                 *        "columnDefs": [
11644
                 *          { "visible": false, "targets": [ 0 ] }
11645
                 *        ] } );
11646
                 *    } );
11647
                 *
11648
                 *  @example
11649
                 *    // Using `columns`
11650
                 *    $(document).ready( function() {
11651
                 *      $('#example').dataTable( {
11652
                 *        "columns": [
11653
                 *          { "visible": false },
11654
                 *          null,
11655
                 *          null,
11656
                 *          null,
11657
                 *          null
11658
                 *        ] } );
11659
                 *    } );
11660
                 */
11661
                "bVisible": true,
11662
 
11663
 
11664
                /**
11665
                 * Developer definable function that is called whenever a cell is created (Ajax source,
11666
                 * etc) or processed for input (DOM source). This can be used as a compliment to mRender
11667
                 * allowing you to modify the DOM element (add background colour for example) when the
11668
                 * element is available.
11669
                 *  @type function
11670
                 *  @param {element} td The TD node that has been created
11671
                 *  @param {*} cellData The Data for the cell
11672
                 *  @param {array|object} rowData The data for the whole row
11673
                 *  @param {int} row The row index for the aoData data store
11674
                 *  @param {int} col The column index for aoColumns
11675
                 *
11676
                 *  @name DataTable.defaults.column.createdCell
11677
                 *  @dtopt Columns
11678
                 *
11679
                 *  @example
11680
                 *    $(document).ready( function() {
11681
                 *      $('#example').dataTable( {
11682
                 *        "columnDefs": [ {
11683
                 *          "targets": [3],
11684
                 *          "createdCell": function (td, cellData, rowData, row, col) {
11685
                 *            if ( cellData == "1.7" ) {
11686
                 *              $(td).css('color', 'blue')
11687
                 *            }
11688
                 *          }
11689
                 *        } ]
11690
                 *      });
11691
                 *    } );
11692
                 */
11693
                "fnCreatedCell": null,
11694
 
11695
 
11696
                /**
11697
                 * This parameter has been replaced by `data` in DataTables to ensure naming
11698
                 * consistency. `dataProp` can still be used, as there is backwards
11699
                 * compatibility in DataTables for this option, but it is strongly
11700
                 * recommended that you use `data` in preference to `dataProp`.
11701
                 *  @name DataTable.defaults.column.dataProp
11702
                 */
11703
 
11704
 
11705
                /**
11706
                 * This property can be used to read data from any data source property,
11707
                 * including deeply nested objects / properties. `data` can be given in a
11708
                 * number of different ways which effect its behaviour:
11709
                 *
11710
                 * * `integer` - treated as an array index for the data source. This is the
11711
                 *   default that DataTables uses (incrementally increased for each column).
11712
                 * * `string` - read an object property from the data source. There are
11713
                 *   three 'special' options that can be used in the string to alter how
11714
                 *   DataTables reads the data from the source object:
11715
                 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
11716
                 *      Javascript to read from nested objects, so to can the options
11717
                 *      specified in `data`. For example: `browser.version` or
11718
                 *      `browser.name`. If your object parameter name contains a period, use
11719
                 *      `\\` to escape it - i.e. `first\\.name`.
11720
                 *    * `[]` - Array notation. DataTables can automatically combine data
11721
                 *      from and array source, joining the data with the characters provided
11722
                 *      between the two brackets. For example: `name[, ]` would provide a
11723
                 *      comma-space separated list from the source array. If no characters
11724
                 *      are provided between the brackets, the original array source is
11725
                 *      returned.
11726
                 *    * `()` - Function notation. Adding `()` to the end of a parameter will
11727
                 *      execute a function of the name given. For example: `browser()` for a
11728
                 *      simple function on the data source, `browser.version()` for a
11729
                 *      function in a nested property or even `browser().version` to get an
11730
                 *      object property if the function called returns an object. Note that
11731
                 *      function notation is recommended for use in `render` rather than
11732
                 *      `data` as it is much simpler to use as a renderer.
11733
                 * * `null` - use the original data source for the row rather than plucking
11734
                 *   data directly from it. This action has effects on two other
11735
                 *   initialisation options:
11736
                 *    * `defaultContent` - When null is given as the `data` option and
11737
                 *      `defaultContent` is specified for the column, the value defined by
11738
                 *      `defaultContent` will be used for the cell.
11739
                 *    * `render` - When null is used for the `data` option and the `render`
11740
                 *      option is specified for the column, the whole data source for the
11741
                 *      row is used for the renderer.
11742
                 * * `function` - the function given will be executed whenever DataTables
11743
                 *   needs to set or get the data for a cell in the column. The function
11744
                 *   takes three parameters:
11745
                 *    * Parameters:
11746
                 *      * `{array|object}` The data source for the row
11747
                 *      * `{string}` The type call data requested - this will be 'set' when
11748
                 *        setting data or 'filter', 'display', 'type', 'sort' or undefined
11749
                 *        when gathering data. Note that when `undefined` is given for the
11750
                 *        type DataTables expects to get the raw data for the object back<
11751
                 *      * `{*}` Data to set when the second parameter is 'set'.
11752
                 *    * Return:
11753
                 *      * The return value from the function is not required when 'set' is
11754
                 *        the type of call, but otherwise the return is what will be used
11755
                 *        for the data requested.
11756
                 *
11757
                 * Note that `data` is a getter and setter option. If you just require
11758
                 * formatting of data for output, you will likely want to use `render` which
11759
                 * is simply a getter and thus simpler to use.
11760
                 *
11761
                 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The
11762
                 * name change reflects the flexibility of this property and is consistent
11763
                 * with the naming of mRender. If 'mDataProp' is given, then it will still
11764
                 * be used by DataTables, as it automatically maps the old name to the new
11765
                 * if required.
11766
                 *
11767
                 *  @type string|int|function|null
11768
                 *  @default null <i>Use automatically calculated column index</i>
11769
                 *
11770
                 *  @name DataTable.defaults.column.data
11771
                 *  @dtopt Columns
11772
                 *
11773
                 *  @example
11774
                 *    // Read table data from objects
11775
                 *    // JSON structure for each row:
11776
                 *    //   {
11777
                 *    //      "engine": {value},
11778
                 *    //      "browser": {value},
11779
                 *    //      "platform": {value},
11780
                 *    //      "version": {value},
11781
                 *    //      "grade": {value}
11782
                 *    //   }
11783
                 *    $(document).ready( function() {
11784
                 *      $('#example').dataTable( {
11785
                 *        "ajaxSource": "sources/objects.txt",
11786
                 *        "columns": [
11787
                 *          { "data": "engine" },
11788
                 *          { "data": "browser" },
11789
                 *          { "data": "platform" },
11790
                 *          { "data": "version" },
11791
                 *          { "data": "grade" }
11792
                 *        ]
11793
                 *      } );
11794
                 *    } );
11795
                 *
11796
                 *  @example
11797
                 *    // Read information from deeply nested objects
11798
                 *    // JSON structure for each row:
11799
                 *    //   {
11800
                 *    //      "engine": {value},
11801
                 *    //      "browser": {value},
11802
                 *    //      "platform": {
11803
                 *    //         "inner": {value}
11804
                 *    //      },
11805
                 *    //      "details": [
11806
                 *    //         {value}, {value}
11807
                 *    //      ]
11808
                 *    //   }
11809
                 *    $(document).ready( function() {
11810
                 *      $('#example').dataTable( {
11811
                 *        "ajaxSource": "sources/deep.txt",
11812
                 *        "columns": [
11813
                 *          { "data": "engine" },
11814
                 *          { "data": "browser" },
11815
                 *          { "data": "platform.inner" },
11816
                 *          { "data": "platform.details.0" },
11817
                 *          { "data": "platform.details.1" }
11818
                 *        ]
11819
                 *      } );
11820
                 *    } );
11821
                 *
11822
                 *  @example
11823
                 *    // Using `data` as a function to provide different information for
11824
                 *    // sorting, filtering and display. In this case, currency (price)
11825
                 *    $(document).ready( function() {
11826
                 *      $('#example').dataTable( {
11827
                 *        "columnDefs": [ {
11828
                 *          "targets": [ 0 ],
11829
                 *          "data": function ( source, type, val ) {
11830
                 *            if (type === 'set') {
11831
                 *              source.price = val;
11832
                 *              // Store the computed dislay and filter values for efficiency
11833
                 *              source.price_display = val=="" ? "" : "$"+numberFormat(val);
11834
                 *              source.price_filter  = val=="" ? "" : "$"+numberFormat(val)+" "+val;
11835
                 *              return;
11836
                 *            }
11837
                 *            else if (type === 'display') {
11838
                 *              return source.price_display;
11839
                 *            }
11840
                 *            else if (type === 'filter') {
11841
                 *              return source.price_filter;
11842
                 *            }
11843
                 *            // 'sort', 'type' and undefined all just use the integer
11844
                 *            return source.price;
11845
                 *          }
11846
                 *        } ]
11847
                 *      } );
11848
                 *    } );
11849
                 *
11850
                 *  @example
11851
                 *    // Using default content
11852
                 *    $(document).ready( function() {
11853
                 *      $('#example').dataTable( {
11854
                 *        "columnDefs": [ {
11855
                 *          "targets": [ 0 ],
11856
                 *          "data": null,
11857
                 *          "defaultContent": "Click to edit"
11858
                 *        } ]
11859
                 *      } );
11860
                 *    } );
11861
                 *
11862
                 *  @example
11863
                 *    // Using array notation - outputting a list from an array
11864
                 *    $(document).ready( function() {
11865
                 *      $('#example').dataTable( {
11866
                 *        "columnDefs": [ {
11867
                 *          "targets": [ 0 ],
11868
                 *          "data": "name[, ]"
11869
                 *        } ]
11870
                 *      } );
11871
                 *    } );
11872
                 *
11873
                 */
11874
                "mData": null,
11875
 
11876
 
11877
                /**
11878
                 * This property is the rendering partner to `data` and it is suggested that
11879
                 * when you want to manipulate data for display (including filtering,
11880
                 * sorting etc) without altering the underlying data for the table, use this
11881
                 * property. `render` can be considered to be the the read only companion to
11882
                 * `data` which is read / write (then as such more complex). Like `data`
11883
                 * this option can be given in a number of different ways to effect its
11884
                 * behaviour:
11885
                 *
11886
                 * * `integer` - treated as an array index for the data source. This is the
11887
                 *   default that DataTables uses (incrementally increased for each column).
11888
                 * * `string` - read an object property from the data source. There are
11889
                 *   three 'special' options that can be used in the string to alter how
11890
                 *   DataTables reads the data from the source object:
11891
                 *    * `.` - Dotted Javascript notation. Just as you use a `.` in
11892
                 *      Javascript to read from nested objects, so to can the options
11893
                 *      specified in `data`. For example: `browser.version` or
11894
                 *      `browser.name`. If your object parameter name contains a period, use
11895
                 *      `\\` to escape it - i.e. `first\\.name`.
11896
                 *    * `[]` - Array notation. DataTables can automatically combine data
11897
                 *      from and array source, joining the data with the characters provided
11898
                 *      between the two brackets. For example: `name[, ]` would provide a
11899
                 *      comma-space separated list from the source array. If no characters
11900
                 *      are provided between the brackets, the original array source is
11901
                 *      returned.
11902
                 *    * `()` - Function notation. Adding `()` to the end of a parameter will
11903
                 *      execute a function of the name given. For example: `browser()` for a
11904
                 *      simple function on the data source, `browser.version()` for a
11905
                 *      function in a nested property or even `browser().version` to get an
11906
                 *      object property if the function called returns an object.
11907
                 * * `object` - use different data for the different data types requested by
11908
                 *   DataTables ('filter', 'display', 'type' or 'sort'). The property names
11909
                 *   of the object is the data type the property refers to and the value can
11910
                 *   defined using an integer, string or function using the same rules as
11911
                 *   `render` normally does. Note that an `_` option _must_ be specified.
11912
                 *   This is the default value to use if you haven't specified a value for
11913
                 *   the data type requested by DataTables.
11914
                 * * `function` - the function given will be executed whenever DataTables
11915
                 *   needs to set or get the data for a cell in the column. The function
11916
                 *   takes three parameters:
11917
                 *    * Parameters:
11918
                 *      * {array|object} The data source for the row (based on `data`)
11919
                 *      * {string} The type call data requested - this will be 'filter',
11920
                 *        'display', 'type' or 'sort'.
11921
                 *      * {array|object} The full data source for the row (not based on
11922
                 *        `data`)
11923
                 *    * Return:
11924
                 *      * The return value from the function is what will be used for the
11925
                 *        data requested.
11926
                 *
11927
                 *  @type string|int|function|object|null
11928
                 *  @default null Use the data source value.
11929
                 *
11930
                 *  @name DataTable.defaults.column.render
11931
                 *  @dtopt Columns
11932
                 *
11933
                 *  @example
11934
                 *    // Create a comma separated list from an array of objects
11935
                 *    $(document).ready( function() {
11936
                 *      $('#example').dataTable( {
11937
                 *        "ajaxSource": "sources/deep.txt",
11938
                 *        "columns": [
11939
                 *          { "data": "engine" },
11940
                 *          { "data": "browser" },
11941
                 *          {
11942
                 *            "data": "platform",
11943
                 *            "render": "[, ].name"
11944
                 *          }
11945
                 *        ]
11946
                 *      } );
11947
                 *    } );
11948
                 *
11949
                 *  @example
11950
                 *    // Execute a function to obtain data
11951
                 *    $(document).ready( function() {
11952
                 *      $('#example').dataTable( {
11953
                 *        "columnDefs": [ {
11954
                 *          "targets": [ 0 ],
11955
                 *          "data": null, // Use the full data source object for the renderer's source
11956
                 *          "render": "browserName()"
11957
                 *        } ]
11958
                 *      } );
11959
                 *    } );
11960
                 *
11961
                 *  @example
11962
                 *    // As an object, extracting different data for the different types
11963
                 *    // This would be used with a data source such as:
11964
                 *    //   { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" }
11965
                 *    // Here the `phone` integer is used for sorting and type detection, while `phone_filter`
11966
                 *    // (which has both forms) is used for filtering for if a user inputs either format, while
11967
                 *    // the formatted phone number is the one that is shown in the table.
11968
                 *    $(document).ready( function() {
11969
                 *      $('#example').dataTable( {
11970
                 *        "columnDefs": [ {
11971
                 *          "targets": [ 0 ],
11972
                 *          "data": null, // Use the full data source object for the renderer's source
11973
                 *          "render": {
11974
                 *            "_": "phone",
11975
                 *            "filter": "phone_filter",
11976
                 *            "display": "phone_display"
11977
                 *          }
11978
                 *        } ]
11979
                 *      } );
11980
                 *    } );
11981
                 *
11982
                 *  @example
11983
                 *    // Use as a function to create a link from the data source
11984
                 *    $(document).ready( function() {
11985
                 *      $('#example').dataTable( {
11986
                 *        "columnDefs": [ {
11987
                 *          "targets": [ 0 ],
11988
                 *          "data": "download_link",
11989
                 *          "render": function ( data, type, full ) {
11990
                 *            return '<a href="'+data+'">Download</a>';
11991
                 *          }
11992
                 *        } ]
11993
                 *      } );
11994
                 *    } );
11995
                 */
11996
                "mRender": null,
11997
 
11998
 
11999
                /**
12000
                 * Change the cell type created for the column - either TD cells or TH cells. This
12001
                 * can be useful as TH cells have semantic meaning in the table body, allowing them
12002
                 * to act as a header for a row (you may wish to add scope='row' to the TH elements).
12003
                 *  @type string
12004
                 *  @default td
12005
                 *
12006
                 *  @name DataTable.defaults.column.cellType
12007
                 *  @dtopt Columns
12008
                 *
12009
                 *  @example
12010
                 *    // Make the first column use TH cells
12011
                 *    $(document).ready( function() {
12012
                 *      $('#example').dataTable( {
12013
                 *        "columnDefs": [ {
12014
                 *          "targets": [ 0 ],
12015
                 *          "cellType": "th"
12016
                 *        } ]
12017
                 *      } );
12018
                 *    } );
12019
                 */
12020
                "sCellType": "td",
12021
 
12022
 
12023
                /**
12024
                 * Class to give to each cell in this column.
12025
                 *  @type string
12026
                 *  @default <i>Empty string</i>
12027
                 *
12028
                 *  @name DataTable.defaults.column.class
12029
                 *  @dtopt Columns
12030
                 *
12031
                 *  @example
12032
                 *    // Using `columnDefs`
12033
                 *    $(document).ready( function() {
12034
                 *      $('#example').dataTable( {
12035
                 *        "columnDefs": [
12036
                 *          { "class": "my_class", "targets": [ 0 ] }
12037
                 *        ]
12038
                 *      } );
12039
                 *    } );
12040
                 *
12041
                 *  @example
12042
                 *    // Using `columns`
12043
                 *    $(document).ready( function() {
12044
                 *      $('#example').dataTable( {
12045
                 *        "columns": [
12046
                 *          { "class": "my_class" },
12047
                 *          null,
12048
                 *          null,
12049
                 *          null,
12050
                 *          null
12051
                 *        ]
12052
                 *      } );
12053
                 *    } );
12054
                 */
12055
                "sClass": "",
12056
 
12057
                /**
12058
                 * When DataTables calculates the column widths to assign to each column,
12059
                 * it finds the longest string in each column and then constructs a
12060
                 * temporary table and reads the widths from that. The problem with this
12061
                 * is that "mmm" is much wider then "iiii", but the latter is a longer
12062
                 * string - thus the calculation can go wrong (doing it properly and putting
12063
                 * it into an DOM object and measuring that is horribly(!) slow). Thus as
12064
                 * a "work around" we provide this option. It will append its value to the
12065
                 * text that is found to be the longest string for the column - i.e. padding.
12066
                 * Generally you shouldn't need this!
12067
                 *  @type string
12068
                 *  @default <i>Empty string<i>
12069
                 *
12070
                 *  @name DataTable.defaults.column.contentPadding
12071
                 *  @dtopt Columns
12072
                 *
12073
                 *  @example
12074
                 *    // Using `columns`
12075
                 *    $(document).ready( function() {
12076
                 *      $('#example').dataTable( {
12077
                 *        "columns": [
12078
                 *          null,
12079
                 *          null,
12080
                 *          null,
12081
                 *          {
12082
                 *            "contentPadding": "mmm"
12083
                 *          }
12084
                 *        ]
12085
                 *      } );
12086
                 *    } );
12087
                 */
12088
                "sContentPadding": "",
12089
 
12090
 
12091
                /**
12092
                 * Allows a default value to be given for a column's data, and will be used
12093
                 * whenever a null data source is encountered (this can be because `data`
12094
                 * is set to null, or because the data source itself is null).
12095
                 *  @type string
12096
                 *  @default null
12097
                 *
12098
                 *  @name DataTable.defaults.column.defaultContent
12099
                 *  @dtopt Columns
12100
                 *
12101
                 *  @example
12102
                 *    // Using `columnDefs`
12103
                 *    $(document).ready( function() {
12104
                 *      $('#example').dataTable( {
12105
                 *        "columnDefs": [
12106
                 *          {
12107
                 *            "data": null,
12108
                 *            "defaultContent": "Edit",
12109
                 *            "targets": [ -1 ]
12110
                 *          }
12111
                 *        ]
12112
                 *      } );
12113
                 *    } );
12114
                 *
12115
                 *  @example
12116
                 *    // Using `columns`
12117
                 *    $(document).ready( function() {
12118
                 *      $('#example').dataTable( {
12119
                 *        "columns": [
12120
                 *          null,
12121
                 *          null,
12122
                 *          null,
12123
                 *          {
12124
                 *            "data": null,
12125
                 *            "defaultContent": "Edit"
12126
                 *          }
12127
                 *        ]
12128
                 *      } );
12129
                 *    } );
12130
                 */
12131
                "sDefaultContent": null,
12132
 
12133
 
12134
                /**
12135
                 * This parameter is only used in DataTables' server-side processing. It can
12136
                 * be exceptionally useful to know what columns are being displayed on the
12137
                 * client side, and to map these to database fields. When defined, the names
12138
                 * also allow DataTables to reorder information from the server if it comes
12139
                 * back in an unexpected order (i.e. if you switch your columns around on the
12140
                 * client-side, your server-side code does not also need updating).
12141
                 *  @type string
12142
                 *  @default <i>Empty string</i>
12143
                 *
12144
                 *  @name DataTable.defaults.column.name
12145
                 *  @dtopt Columns
12146
                 *
12147
                 *  @example
12148
                 *    // Using `columnDefs`
12149
                 *    $(document).ready( function() {
12150
                 *      $('#example').dataTable( {
12151
                 *        "columnDefs": [
12152
                 *          { "name": "engine", "targets": [ 0 ] },
12153
                 *          { "name": "browser", "targets": [ 1 ] },
12154
                 *          { "name": "platform", "targets": [ 2 ] },
12155
                 *          { "name": "version", "targets": [ 3 ] },
12156
                 *          { "name": "grade", "targets": [ 4 ] }
12157
                 *        ]
12158
                 *      } );
12159
                 *    } );
12160
                 *
12161
                 *  @example
12162
                 *    // Using `columns`
12163
                 *    $(document).ready( function() {
12164
                 *      $('#example').dataTable( {
12165
                 *        "columns": [
12166
                 *          { "name": "engine" },
12167
                 *          { "name": "browser" },
12168
                 *          { "name": "platform" },
12169
                 *          { "name": "version" },
12170
                 *          { "name": "grade" }
12171
                 *        ]
12172
                 *      } );
12173
                 *    } );
12174
                 */
12175
                "sName": "",
12176
 
12177
 
12178
                /**
12179
                 * Defines a data source type for the ordering which can be used to read
12180
                 * real-time information from the table (updating the internally cached
12181
                 * version) prior to ordering. This allows ordering to occur on user
12182
                 * editable elements such as form inputs.
12183
                 *  @type string
12184
                 *  @default std
12185
                 *
12186
                 *  @name DataTable.defaults.column.orderDataType
12187
                 *  @dtopt Columns
12188
                 *
12189
                 *  @example
12190
                 *    // Using `columnDefs`
12191
                 *    $(document).ready( function() {
12192
                 *      $('#example').dataTable( {
12193
                 *        "columnDefs": [
12194
                 *          { "orderDataType": "dom-text", "targets": [ 2, 3 ] },
12195
                 *          { "type": "numeric", "targets": [ 3 ] },
12196
                 *          { "orderDataType": "dom-select", "targets": [ 4 ] },
12197
                 *          { "orderDataType": "dom-checkbox", "targets": [ 5 ] }
12198
                 *        ]
12199
                 *      } );
12200
                 *    } );
12201
                 *
12202
                 *  @example
12203
                 *    // Using `columns`
12204
                 *    $(document).ready( function() {
12205
                 *      $('#example').dataTable( {
12206
                 *        "columns": [
12207
                 *          null,
12208
                 *          null,
12209
                 *          { "orderDataType": "dom-text" },
12210
                 *          { "orderDataType": "dom-text", "type": "numeric" },
12211
                 *          { "orderDataType": "dom-select" },
12212
                 *          { "orderDataType": "dom-checkbox" }
12213
                 *        ]
12214
                 *      } );
12215
                 *    } );
12216
                 */
12217
                "sSortDataType": "std",
12218
 
12219
 
12220
                /**
12221
                 * The title of this column.
12222
                 *  @type string
12223
                 *  @default null <i>Derived from the 'TH' value for this column in the
12224
                 *    original HTML table.</i>
12225
                 *
12226
                 *  @name DataTable.defaults.column.title
12227
                 *  @dtopt Columns
12228
                 *
12229
                 *  @example
12230
                 *    // Using `columnDefs`
12231
                 *    $(document).ready( function() {
12232
                 *      $('#example').dataTable( {
12233
                 *        "columnDefs": [
12234
                 *          { "title": "My column title", "targets": [ 0 ] }
12235
                 *        ]
12236
                 *      } );
12237
                 *    } );
12238
                 *
12239
                 *  @example
12240
                 *    // Using `columns`
12241
                 *    $(document).ready( function() {
12242
                 *      $('#example').dataTable( {
12243
                 *        "columns": [
12244
                 *          { "title": "My column title" },
12245
                 *          null,
12246
                 *          null,
12247
                 *          null,
12248
                 *          null
12249
                 *        ]
12250
                 *      } );
12251
                 *    } );
12252
                 */
12253
                "sTitle": null,
12254
 
12255
 
12256
                /**
12257
                 * The type allows you to specify how the data for this column will be
12258
                 * ordered. Four types (string, numeric, date and html (which will strip
12259
                 * HTML tags before ordering)) are currently available. Note that only date
12260
                 * formats understood by Javascript's Date() object will be accepted as type
12261
                 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string',
12262
                 * 'numeric', 'date' or 'html' (by default). Further types can be adding
12263
                 * through plug-ins.
12264
                 *  @type string
12265
                 *  @default null <i>Auto-detected from raw data</i>
12266
                 *
12267
                 *  @name DataTable.defaults.column.type
12268
                 *  @dtopt Columns
12269
                 *
12270
                 *  @example
12271
                 *    // Using `columnDefs`
12272
                 *    $(document).ready( function() {
12273
                 *      $('#example').dataTable( {
12274
                 *        "columnDefs": [
12275
                 *          { "type": "html", "targets": [ 0 ] }
12276
                 *        ]
12277
                 *      } );
12278
                 *    } );
12279
                 *
12280
                 *  @example
12281
                 *    // Using `columns`
12282
                 *    $(document).ready( function() {
12283
                 *      $('#example').dataTable( {
12284
                 *        "columns": [
12285
                 *          { "type": "html" },
12286
                 *          null,
12287
                 *          null,
12288
                 *          null,
12289
                 *          null
12290
                 *        ]
12291
                 *      } );
12292
                 *    } );
12293
                 */
12294
                "sType": null,
12295
 
12296
 
12297
                /**
12298
                 * Defining the width of the column, this parameter may take any CSS value
12299
                 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not
12300
                 * been given a specific width through this interface ensuring that the table
12301
                 * remains readable.
12302
                 *  @type string
12303
                 *  @default null <i>Automatic</i>
12304
                 *
12305
                 *  @name DataTable.defaults.column.width
12306
                 *  @dtopt Columns
12307
                 *
12308
                 *  @example
12309
                 *    // Using `columnDefs`
12310
                 *    $(document).ready( function() {
12311
                 *      $('#example').dataTable( {
12312
                 *        "columnDefs": [
12313
                 *          { "width": "20%", "targets": [ 0 ] }
12314
                 *        ]
12315
                 *      } );
12316
                 *    } );
12317
                 *
12318
                 *  @example
12319
                 *    // Using `columns`
12320
                 *    $(document).ready( function() {
12321
                 *      $('#example').dataTable( {
12322
                 *        "columns": [
12323
                 *          { "width": "20%" },
12324
                 *          null,
12325
                 *          null,
12326
                 *          null,
12327
                 *          null
12328
                 *        ]
12329
                 *      } );
12330
                 *    } );
12331
                 */
12332
                "sWidth": null
12333
        };
12334
 
12335
        _fnHungarianMap( DataTable.defaults.column );
12336
 
12337
 
12338
 
12339
        /**
12340
         * DataTables settings object - this holds all the information needed for a
12341
         * given table, including configuration, data and current application of the
12342
         * table options. DataTables does not have a single instance for each DataTable
12343
         * with the settings attached to that instance, but rather instances of the
12344
         * DataTable "class" are created on-the-fly as needed (typically by a
12345
         * $().dataTable() call) and the settings object is then applied to that
12346
         * instance.
12347
         *
12348
         * Note that this object is related to {@link DataTable.defaults} but this
12349
         * one is the internal data store for DataTables's cache of columns. It should
12350
         * NOT be manipulated outside of DataTables. Any configuration should be done
12351
         * through the initialisation options.
12352
         *  @namespace
12353
         *  @todo Really should attach the settings object to individual instances so we
12354
         *    don't need to create new instances on each $().dataTable() call (if the
12355
         *    table already exists). It would also save passing oSettings around and
12356
         *    into every single function. However, this is a very significant
12357
         *    architecture change for DataTables and will almost certainly break
12358
         *    backwards compatibility with older installations. This is something that
12359
         *    will be done in 2.0.
12360
         */
12361
        DataTable.models.oSettings = {
12362
                /**
12363
                 * Primary features of DataTables and their enablement state.
12364
                 *  @namespace
12365
                 */
12366
                "oFeatures": {
12367
 
12368
                        /**
12369
                         * Flag to say if DataTables should automatically try to calculate the
12370
                         * optimum table and columns widths (true) or not (false).
12371
                         * Note that this parameter will be set by the initialisation routine. To
12372
                         * set a default use {@link DataTable.defaults}.
12373
                         *  @type boolean
12374
                         */
12375
                        "bAutoWidth": null,
12376
 
12377
                        /**
12378
                         * Delay the creation of TR and TD elements until they are actually
12379
                         * needed by a driven page draw. This can give a significant speed
12380
                         * increase for Ajax source and Javascript source data, but makes no
12381
                         * difference at all fro DOM and server-side processing tables.
12382
                         * Note that this parameter will be set by the initialisation routine. To
12383
                         * set a default use {@link DataTable.defaults}.
12384
                         *  @type boolean
12385
                         */
12386
                        "bDeferRender": null,
12387
 
12388
                        /**
12389
                         * Enable filtering on the table or not. Note that if this is disabled
12390
                         * then there is no filtering at all on the table, including fnFilter.
12391
                         * To just remove the filtering input use sDom and remove the 'f' option.
12392
                         * Note that this parameter will be set by the initialisation routine. To
12393
                         * set a default use {@link DataTable.defaults}.
12394
                         *  @type boolean
12395
                         */
12396
                        "bFilter": null,
12397
 
12398
                        /**
12399
                         * Table information element (the 'Showing x of y records' div) enable
12400
                         * flag.
12401
                         * Note that this parameter will be set by the initialisation routine. To
12402
                         * set a default use {@link DataTable.defaults}.
12403
                         *  @type boolean
12404
                         */
12405
                        "bInfo": null,
12406
 
12407
                        /**
12408
                         * Present a user control allowing the end user to change the page size
12409
                         * when pagination is enabled.
12410
                         * Note that this parameter will be set by the initialisation routine. To
12411
                         * set a default use {@link DataTable.defaults}.
12412
                         *  @type boolean
12413
                         */
12414
                        "bLengthChange": null,
12415
 
12416
                        /**
12417
                         * Pagination enabled or not. Note that if this is disabled then length
12418
                         * changing must also be disabled.
12419
                         * Note that this parameter will be set by the initialisation routine. To
12420
                         * set a default use {@link DataTable.defaults}.
12421
                         *  @type boolean
12422
                         */
12423
                        "bPaginate": null,
12424
 
12425
                        /**
12426
                         * Processing indicator enable flag whenever DataTables is enacting a
12427
                         * user request - typically an Ajax request for server-side processing.
12428
                         * Note that this parameter will be set by the initialisation routine. To
12429
                         * set a default use {@link DataTable.defaults}.
12430
                         *  @type boolean
12431
                         */
12432
                        "bProcessing": null,
12433
 
12434
                        /**
12435
                         * Server-side processing enabled flag - when enabled DataTables will
12436
                         * get all data from the server for every draw - there is no filtering,
12437
                         * sorting or paging done on the client-side.
12438
                         * Note that this parameter will be set by the initialisation routine. To
12439
                         * set a default use {@link DataTable.defaults}.
12440
                         *  @type boolean
12441
                         */
12442
                        "bServerSide": null,
12443
 
12444
                        /**
12445
                         * Sorting enablement flag.
12446
                         * Note that this parameter will be set by the initialisation routine. To
12447
                         * set a default use {@link DataTable.defaults}.
12448
                         *  @type boolean
12449
                         */
12450
                        "bSort": null,
12451
 
12452
                        /**
12453
                         * Multi-column sorting
12454
                         * Note that this parameter will be set by the initialisation routine. To
12455
                         * set a default use {@link DataTable.defaults}.
12456
                         *  @type boolean
12457
                         */
12458
                        "bSortMulti": null,
12459
 
12460
                        /**
12461
                         * Apply a class to the columns which are being sorted to provide a
12462
                         * visual highlight or not. This can slow things down when enabled since
12463
                         * there is a lot of DOM interaction.
12464
                         * Note that this parameter will be set by the initialisation routine. To
12465
                         * set a default use {@link DataTable.defaults}.
12466
                         *  @type boolean
12467
                         */
12468
                        "bSortClasses": null,
12469
 
12470
                        /**
12471
                         * State saving enablement flag.
12472
                         * Note that this parameter will be set by the initialisation routine. To
12473
                         * set a default use {@link DataTable.defaults}.
12474
                         *  @type boolean
12475
                         */
12476
                        "bStateSave": null
12477
                },
12478
 
12479
 
12480
                /**
12481
                 * Scrolling settings for a table.
12482
                 *  @namespace
12483
                 */
12484
                "oScroll": {
12485
                        /**
12486
                         * When the table is shorter in height than sScrollY, collapse the
12487
                         * table container down to the height of the table (when true).
12488
                         * Note that this parameter will be set by the initialisation routine. To
12489
                         * set a default use {@link DataTable.defaults}.
12490
                         *  @type boolean
12491
                         */
12492
                        "bCollapse": null,
12493
 
12494
                        /**
12495
                         * Width of the scrollbar for the web-browser's platform. Calculated
12496
                         * during table initialisation.
12497
                         *  @type int
12498
                         *  @default 0
12499
                         */
12500
                        "iBarWidth": 0,
12501
 
12502
                        /**
12503
                         * Viewport width for horizontal scrolling. Horizontal scrolling is
12504
                         * disabled if an empty string.
12505
                         * Note that this parameter will be set by the initialisation routine. To
12506
                         * set a default use {@link DataTable.defaults}.
12507
                         *  @type string
12508
                         */
12509
                        "sX": null,
12510
 
12511
                        /**
12512
                         * Width to expand the table to when using x-scrolling. Typically you
12513
                         * should not need to use this.
12514
                         * Note that this parameter will be set by the initialisation routine. To
12515
                         * set a default use {@link DataTable.defaults}.
12516
                         *  @type string
12517
                         *  @deprecated
12518
                         */
12519
                        "sXInner": null,
12520
 
12521
                        /**
12522
                         * Viewport height for vertical scrolling. Vertical scrolling is disabled
12523
                         * if an empty string.
12524
                         * Note that this parameter will be set by the initialisation routine. To
12525
                         * set a default use {@link DataTable.defaults}.
12526
                         *  @type string
12527
                         */
12528
                        "sY": null
12529
                },
12530
 
12531
                /**
12532
                 * Language information for the table.
12533
                 *  @namespace
12534
                 *  @extends DataTable.defaults.oLanguage
12535
                 */
12536
                "oLanguage": {
12537
                        /**
12538
                         * Information callback function. See
12539
                         * {@link DataTable.defaults.fnInfoCallback}
12540
                         *  @type function
12541
                         *  @default null
12542
                         */
12543
                        "fnInfoCallback": null
12544
                },
12545
 
12546
                /**
12547
                 * Browser support parameters
12548
                 *  @namespace
12549
                 */
12550
                "oBrowser": {
12551
                        /**
12552
                         * Indicate if the browser incorrectly calculates width:100% inside a
12553
                         * scrolling element (IE6/7)
12554
                         *  @type boolean
12555
                         *  @default false
12556
                         */
12557
                        "bScrollOversize": false,
12558
 
12559
                        /**
12560
                         * Determine if the vertical scrollbar is on the right or left of the
12561
                         * scrolling container - needed for rtl language layout, although not
12562
                         * all browsers move the scrollbar (Safari).
12563
                         *  @type boolean
12564
                         *  @default false
12565
                         */
12566
                        "bScrollbarLeft": false
12567
                },
12568
 
12569
 
12570
                "ajax": null,
12571
 
12572
 
12573
                /**
12574
                 * Array referencing the nodes which are used for the features. The
12575
                 * parameters of this object match what is allowed by sDom - i.e.
12576
                 *   <ul>
12577
                 *     <li>'l' - Length changing</li>
12578
                 *     <li>'f' - Filtering input</li>
12579
                 *     <li>'t' - The table!</li>
12580
                 *     <li>'i' - Information</li>
12581
                 *     <li>'p' - Pagination</li>
12582
                 *     <li>'r' - pRocessing</li>
12583
                 *   </ul>
12584
                 *  @type array
12585
                 *  @default []
12586
                 */
12587
                "aanFeatures": [],
12588
 
12589
                /**
12590
                 * Store data information - see {@link DataTable.models.oRow} for detailed
12591
                 * information.
12592
                 *  @type array
12593
                 *  @default []
12594
                 */
12595
                "aoData": [],
12596
 
12597
                /**
12598
                 * Array of indexes which are in the current display (after filtering etc)
12599
                 *  @type array
12600
                 *  @default []
12601
                 */
12602
                "aiDisplay": [],
12603
 
12604
                /**
12605
                 * Array of indexes for display - no filtering
12606
                 *  @type array
12607
                 *  @default []
12608
                 */
12609
                "aiDisplayMaster": [],
12610
 
12611
                /**
12612
                 * Store information about each column that is in use
12613
                 *  @type array
12614
                 *  @default []
12615
                 */
12616
                "aoColumns": [],
12617
 
12618
                /**
12619
                 * Store information about the table's header
12620
                 *  @type array
12621
                 *  @default []
12622
                 */
12623
                "aoHeader": [],
12624
 
12625
                /**
12626
                 * Store information about the table's footer
12627
                 *  @type array
12628
                 *  @default []
12629
                 */
12630
                "aoFooter": [],
12631
 
12632
                /**
12633
                 * Store the applied global search information in case we want to force a
12634
                 * research or compare the old search to a new one.
12635
                 * Note that this parameter will be set by the initialisation routine. To
12636
                 * set a default use {@link DataTable.defaults}.
12637
                 *  @namespace
12638
                 *  @extends DataTable.models.oSearch
12639
                 */
12640
                "oPreviousSearch": {},
12641
 
12642
                /**
12643
                 * Store the applied search for each column - see
12644
                 * {@link DataTable.models.oSearch} for the format that is used for the
12645
                 * filtering information for each column.
12646
                 *  @type array
12647
                 *  @default []
12648
                 */
12649
                "aoPreSearchCols": [],
12650
 
12651
                /**
12652
                 * Sorting that is applied to the table. Note that the inner arrays are
12653
                 * used in the following manner:
12654
                 * <ul>
12655
                 *   <li>Index 0 - column number</li>
12656
                 *   <li>Index 1 - current sorting direction</li>
12657
                 * </ul>
12658
                 * Note that this parameter will be set by the initialisation routine. To
12659
                 * set a default use {@link DataTable.defaults}.
12660
                 *  @type array
12661
                 *  @todo These inner arrays should really be objects
12662
                 */
12663
                "aaSorting": null,
12664
 
12665
                /**
12666
                 * Sorting that is always applied to the table (i.e. prefixed in front of
12667
                 * aaSorting).
12668
                 * Note that this parameter will be set by the initialisation routine. To
12669
                 * set a default use {@link DataTable.defaults}.
12670
                 *  @type array
12671
                 *  @default []
12672
                 */
12673
                "aaSortingFixed": [],
12674
 
12675
                /**
12676
                 * Classes to use for the striping of a table.
12677
                 * Note that this parameter will be set by the initialisation routine. To
12678
                 * set a default use {@link DataTable.defaults}.
12679
                 *  @type array
12680
                 *  @default []
12681
                 */
12682
                "asStripeClasses": null,
12683
 
12684
                /**
12685
                 * If restoring a table - we should restore its striping classes as well
12686
                 *  @type array
12687
                 *  @default []
12688
                 */
12689
                "asDestroyStripes": [],
12690
 
12691
                /**
12692
                 * If restoring a table - we should restore its width
12693
                 *  @type int
12694
                 *  @default 0
12695
                 */
12696
                "sDestroyWidth": 0,
12697
 
12698
                /**
12699
                 * Callback functions array for every time a row is inserted (i.e. on a draw).
12700
                 *  @type array
12701
                 *  @default []
12702
                 */
12703
                "aoRowCallback": [],
12704
 
12705
                /**
12706
                 * Callback functions for the header on each draw.
12707
                 *  @type array
12708
                 *  @default []
12709
                 */
12710
                "aoHeaderCallback": [],
12711
 
12712
                /**
12713
                 * Callback function for the footer on each draw.
12714
                 *  @type array
12715
                 *  @default []
12716
                 */
12717
                "aoFooterCallback": [],
12718
 
12719
                /**
12720
                 * Array of callback functions for draw callback functions
12721
                 *  @type array
12722
                 *  @default []
12723
                 */
12724
                "aoDrawCallback": [],
12725
 
12726
                /**
12727
                 * Array of callback functions for row created function
12728
                 *  @type array
12729
                 *  @default []
12730
                 */
12731
                "aoRowCreatedCallback": [],
12732
 
12733
                /**
12734
                 * Callback functions for just before the table is redrawn. A return of
12735
                 * false will be used to cancel the draw.
12736
                 *  @type array
12737
                 *  @default []
12738
                 */
12739
                "aoPreDrawCallback": [],
12740
 
12741
                /**
12742
                 * Callback functions for when the table has been initialised.
12743
                 *  @type array
12744
                 *  @default []
12745
                 */
12746
                "aoInitComplete": [],
12747
 
12748
 
12749
                /**
12750
                 * Callbacks for modifying the settings to be stored for state saving, prior to
12751
                 * saving state.
12752
                 *  @type array
12753
                 *  @default []
12754
                 */
12755
                "aoStateSaveParams": [],
12756
 
12757
                /**
12758
                 * Callbacks for modifying the settings that have been stored for state saving
12759
                 * prior to using the stored values to restore the state.
12760
                 *  @type array
12761
                 *  @default []
12762
                 */
12763
                "aoStateLoadParams": [],
12764
 
12765
                /**
12766
                 * Callbacks for operating on the settings object once the saved state has been
12767
                 * loaded
12768
                 *  @type array
12769
                 *  @default []
12770
                 */
12771
                "aoStateLoaded": [],
12772
 
12773
                /**
12774
                 * Cache the table ID for quick access
12775
                 *  @type string
12776
                 *  @default <i>Empty string</i>
12777
                 */
12778
                "sTableId": "",
12779
 
12780
                /**
12781
                 * The TABLE node for the main table
12782
                 *  @type node
12783
                 *  @default null
12784
                 */
12785
                "nTable": null,
12786
 
12787
                /**
12788
                 * Permanent ref to the thead element
12789
                 *  @type node
12790
                 *  @default null
12791
                 */
12792
                "nTHead": null,
12793
 
12794
                /**
12795
                 * Permanent ref to the tfoot element - if it exists
12796
                 *  @type node
12797
                 *  @default null
12798
                 */
12799
                "nTFoot": null,
12800
 
12801
                /**
12802
                 * Permanent ref to the tbody element
12803
                 *  @type node
12804
                 *  @default null
12805
                 */
12806
                "nTBody": null,
12807
 
12808
                /**
12809
                 * Cache the wrapper node (contains all DataTables controlled elements)
12810
                 *  @type node
12811
                 *  @default null
12812
                 */
12813
                "nTableWrapper": null,
12814
 
12815
                /**
12816
                 * Indicate if when using server-side processing the loading of data
12817
                 * should be deferred until the second draw.
12818
                 * Note that this parameter will be set by the initialisation routine. To
12819
                 * set a default use {@link DataTable.defaults}.
12820
                 *  @type boolean
12821
                 *  @default false
12822
                 */
12823
                "bDeferLoading": false,
12824
 
12825
                /**
12826
                 * Indicate if all required information has been read in
12827
                 *  @type boolean
12828
                 *  @default false
12829
                 */
12830
                "bInitialised": false,
12831
 
12832
                /**
12833
                 * Information about open rows. Each object in the array has the parameters
12834
                 * 'nTr' and 'nParent'
12835
                 *  @type array
12836
                 *  @default []
12837
                 */
12838
                "aoOpenRows": [],
12839
 
12840
                /**
12841
                 * Dictate the positioning of DataTables' control elements - see
12842
                 * {@link DataTable.model.oInit.sDom}.
12843
                 * Note that this parameter will be set by the initialisation routine. To
12844
                 * set a default use {@link DataTable.defaults}.
12845
                 *  @type string
12846
                 *  @default null
12847
                 */
12848
                "sDom": null,
12849
 
12850
                /**
12851
                 * Which type of pagination should be used.
12852
                 * Note that this parameter will be set by the initialisation routine. To
12853
                 * set a default use {@link DataTable.defaults}.
12854
                 *  @type string
12855
                 *  @default two_button
12856
                 */
12857
                "sPaginationType": "two_button",
12858
 
12859
                /**
12860
                 * The state duration (for `stateSave`) in seconds.
12861
                 * Note that this parameter will be set by the initialisation routine. To
12862
                 * set a default use {@link DataTable.defaults}.
12863
                 *  @type int
12864
                 *  @default 0
12865
                 */
12866
                "iStateDuration": 0,
12867
 
12868
                /**
12869
                 * Array of callback functions for state saving. Each array element is an
12870
                 * object with the following parameters:
12871
                 *   <ul>
12872
                 *     <li>function:fn - function to call. Takes two parameters, oSettings
12873
                 *       and the JSON string to save that has been thus far created. Returns
12874
                 *       a JSON string to be inserted into a json object
12875
                 *       (i.e. '"param": [ 0, 1, 2]')</li>
12876
                 *     <li>string:sName - name of callback</li>
12877
                 *   </ul>
12878
                 *  @type array
12879
                 *  @default []
12880
                 */
12881
                "aoStateSave": [],
12882
 
12883
                /**
12884
                 * Array of callback functions for state loading. Each array element is an
12885
                 * object with the following parameters:
12886
                 *   <ul>
12887
                 *     <li>function:fn - function to call. Takes two parameters, oSettings
12888
                 *       and the object stored. May return false to cancel state loading</li>
12889
                 *     <li>string:sName - name of callback</li>
12890
                 *   </ul>
12891
                 *  @type array
12892
                 *  @default []
12893
                 */
12894
                "aoStateLoad": [],
12895
 
12896
                /**
12897
                 * State that was saved. Useful for back reference
12898
                 *  @type object
12899
                 *  @default null
12900
                 */
12901
                "oSavedState": null,
12902
 
12903
                /**
12904
                 * State that was loaded. Useful for back reference
12905
                 *  @type object
12906
                 *  @default null
12907
                 */
12908
                "oLoadedState": null,
12909
 
12910
                /**
12911
                 * Source url for AJAX data for the table.
12912
                 * Note that this parameter will be set by the initialisation routine. To
12913
                 * set a default use {@link DataTable.defaults}.
12914
                 *  @type string
12915
                 *  @default null
12916
                 */
12917
                "sAjaxSource": null,
12918
 
12919
                /**
12920
                 * Property from a given object from which to read the table data from. This
12921
                 * can be an empty string (when not server-side processing), in which case
12922
                 * it is  assumed an an array is given directly.
12923
                 * Note that this parameter will be set by the initialisation routine. To
12924
                 * set a default use {@link DataTable.defaults}.
12925
                 *  @type string
12926
                 */
12927
                "sAjaxDataProp": null,
12928
 
12929
                /**
12930
                 * Note if draw should be blocked while getting data
12931
                 *  @type boolean
12932
                 *  @default true
12933
                 */
12934
                "bAjaxDataGet": true,
12935
 
12936
                /**
12937
                 * The last jQuery XHR object that was used for server-side data gathering.
12938
                 * This can be used for working with the XHR information in one of the
12939
                 * callbacks
12940
                 *  @type object
12941
                 *  @default null
12942
                 */
12943
                "jqXHR": null,
12944
 
12945
                /**
12946
                 * JSON returned from the server in the last Ajax request
12947
                 *  @type object
12948
                 *  @default undefined
12949
                 */
12950
                "json": undefined,
12951
 
12952
                /**
12953
                 * Data submitted as part of the last Ajax request
12954
                 *  @type object
12955
                 *  @default undefined
12956
                 */
12957
                "oAjaxData": undefined,
12958
 
12959
                /**
12960
                 * Function to get the server-side data.
12961
                 * Note that this parameter will be set by the initialisation routine. To
12962
                 * set a default use {@link DataTable.defaults}.
12963
                 *  @type function
12964
                 */
12965
                "fnServerData": null,
12966
 
12967
                /**
12968
                 * Functions which are called prior to sending an Ajax request so extra
12969
                 * parameters can easily be sent to the server
12970
                 *  @type array
12971
                 *  @default []
12972
                 */
12973
                "aoServerParams": [],
12974
 
12975
                /**
12976
                 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if
12977
                 * required).
12978
                 * Note that this parameter will be set by the initialisation routine. To
12979
                 * set a default use {@link DataTable.defaults}.
12980
                 *  @type string
12981
                 */
12982
                "sServerMethod": null,
12983
 
12984
                /**
12985
                 * Format numbers for display.
12986
                 * Note that this parameter will be set by the initialisation routine. To
12987
                 * set a default use {@link DataTable.defaults}.
12988
                 *  @type function
12989
                 */
12990
                "fnFormatNumber": null,
12991
 
12992
                /**
12993
                 * List of options that can be used for the user selectable length menu.
12994
                 * Note that this parameter will be set by the initialisation routine. To
12995
                 * set a default use {@link DataTable.defaults}.
12996
                 *  @type array
12997
                 *  @default []
12998
                 */
12999
                "aLengthMenu": null,
13000
 
13001
                /**
13002
                 * Counter for the draws that the table does. Also used as a tracker for
13003
                 * server-side processing
13004
                 *  @type int
13005
                 *  @default 0
13006
                 */
13007
                "iDraw": 0,
13008
 
13009
                /**
13010
                 * Indicate if a redraw is being done - useful for Ajax
13011
                 *  @type boolean
13012
                 *  @default false
13013
                 */
13014
                "bDrawing": false,
13015
 
13016
                /**
13017
                 * Draw index (iDraw) of the last error when parsing the returned data
13018
                 *  @type int
13019
                 *  @default -1
13020
                 */
13021
                "iDrawError": -1,
13022
 
13023
                /**
13024
                 * Paging display length
13025
                 *  @type int
13026
                 *  @default 10
13027
                 */
13028
                "_iDisplayLength": 10,
13029
 
13030
                /**
13031
                 * Paging start point - aiDisplay index
13032
                 *  @type int
13033
                 *  @default 0
13034
                 */
13035
                "_iDisplayStart": 0,
13036
 
13037
                /**
13038
                 * Server-side processing - number of records in the result set
13039
                 * (i.e. before filtering), Use fnRecordsTotal rather than
13040
                 * this property to get the value of the number of records, regardless of
13041
                 * the server-side processing setting.
13042
                 *  @type int
13043
                 *  @default 0
13044
                 *  @private
13045
                 */
13046
                "_iRecordsTotal": 0,
13047
 
13048
                /**
13049
                 * Server-side processing - number of records in the current display set
13050
                 * (i.e. after filtering). Use fnRecordsDisplay rather than
13051
                 * this property to get the value of the number of records, regardless of
13052
                 * the server-side processing setting.
13053
                 *  @type boolean
13054
                 *  @default 0
13055
                 *  @private
13056
                 */
13057
                "_iRecordsDisplay": 0,
13058
 
13059
                /**
13060
                 * Flag to indicate if jQuery UI marking and classes should be used.
13061
                 * Note that this parameter will be set by the initialisation routine. To
13062
                 * set a default use {@link DataTable.defaults}.
13063
                 *  @type boolean
13064
                 */
13065
                "bJUI": null,
13066
 
13067
                /**
13068
                 * The classes to use for the table
13069
                 *  @type object
13070
                 *  @default {}
13071
                 */
13072
                "oClasses": {},
13073
 
13074
                /**
13075
                 * Flag attached to the settings object so you can check in the draw
13076
                 * callback if filtering has been done in the draw. Deprecated in favour of
13077
                 * events.
13078
                 *  @type boolean
13079
                 *  @default false
13080
                 *  @deprecated
13081
                 */
13082
                "bFiltered": false,
13083
 
13084
                /**
13085
                 * Flag attached to the settings object so you can check in the draw
13086
                 * callback if sorting has been done in the draw. Deprecated in favour of
13087
                 * events.
13088
                 *  @type boolean
13089
                 *  @default false
13090
                 *  @deprecated
13091
                 */
13092
                "bSorted": false,
13093
 
13094
                /**
13095
                 * Indicate that if multiple rows are in the header and there is more than
13096
                 * one unique cell per column, if the top one (true) or bottom one (false)
13097
                 * should be used for sorting / title by DataTables.
13098
                 * Note that this parameter will be set by the initialisation routine. To
13099
                 * set a default use {@link DataTable.defaults}.
13100
                 *  @type boolean
13101
                 */
13102
                "bSortCellsTop": null,
13103
 
13104
                /**
13105
                 * Initialisation object that is used for the table
13106
                 *  @type object
13107
                 *  @default null
13108
                 */
13109
                "oInit": null,
13110
 
13111
                /**
13112
                 * Destroy callback functions - for plug-ins to attach themselves to the
13113
                 * destroy so they can clean up markup and events.
13114
                 *  @type array
13115
                 *  @default []
13116
                 */
13117
                "aoDestroyCallback": [],
13118
 
13119
 
13120
                /**
13121
                 * Get the number of records in the current record set, before filtering
13122
                 *  @type function
13123
                 */
13124
                "fnRecordsTotal": function ()
13125
                {
13126
                        return _fnDataSource( this ) == 'ssp' ?
13127
                                this._iRecordsTotal * 1 :
13128
                                this.aiDisplayMaster.length;
13129
                },
13130
 
13131
                /**
13132
                 * Get the number of records in the current record set, after filtering
13133
                 *  @type function
13134
                 */
13135
                "fnRecordsDisplay": function ()
13136
                {
13137
                        return _fnDataSource( this ) == 'ssp' ?
13138
                                this._iRecordsDisplay * 1 :
13139
                                this.aiDisplay.length;
13140
                },
13141
 
13142
                /**
13143
                 * Get the display end point - aiDisplay index
13144
                 *  @type function
13145
                 */
13146
                "fnDisplayEnd": function ()
13147
                {
13148
                        var
13149
                                len      = this._iDisplayLength,
13150
                                start    = this._iDisplayStart,
13151
                                calc     = start + len,
13152
                                records  = this.aiDisplay.length,
13153
                                features = this.oFeatures,
13154
                                paginate = features.bPaginate;
13155
 
13156
                        if ( features.bServerSide ) {
13157
                                return paginate === false || len === -1 ?
13158
                                        start + records :
13159
                                        Math.min( start+len, this._iRecordsDisplay );
13160
                        }
13161
                        else {
13162
                                return ! paginate || calc>records || len===-1 ?
13163
                                        records :
13164
                                        calc;
13165
                        }
13166
                },
13167
 
13168
                /**
13169
                 * The DataTables object for this table
13170
                 *  @type object
13171
                 *  @default null
13172
                 */
13173
                "oInstance": null,
13174
 
13175
                /**
13176
                 * Unique identifier for each instance of the DataTables object. If there
13177
                 * is an ID on the table node, then it takes that value, otherwise an
13178
                 * incrementing internal counter is used.
13179
                 *  @type string
13180
                 *  @default null
13181
                 */
13182
                "sInstance": null,
13183
 
13184
                /**
13185
                 * tabindex attribute value that is added to DataTables control elements, allowing
13186
                 * keyboard navigation of the table and its controls.
13187
                 */
13188
                "iTabIndex": 0,
13189
 
13190
                /**
13191
                 * DIV container for the footer scrolling table if scrolling
13192
                 */
13193
                "nScrollHead": null,
13194
 
13195
                /**
13196
                 * DIV container for the footer scrolling table if scrolling
13197
                 */
13198
                "nScrollFoot": null,
13199
 
13200
                /**
13201
                 * Last applied sort
13202
                 *  @type array
13203
                 *  @default []
13204
                 */
13205
                "aLastSort": [],
13206
 
13207
                /**
13208
                 * Stored plug-in instances
13209
                 *  @type object
13210
                 *  @default {}
13211
                 */
13212
                "oPlugins": {}
13213
        };
13214
 
13215
        /**
13216
         * Extension object for DataTables that is used to provide all extension
13217
         * options.
13218
         *
13219
         * Note that the `DataTable.ext` object is available through
13220
         * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is
13221
         * also aliased to `jQuery.fn.dataTableExt` for historic reasons.
13222
         *  @namespace
13223
         *  @extends DataTable.models.ext
13224
         */
13225
 
13226
 
13227
        /**
13228
         * DataTables extensions
13229
         *
13230
         * This namespace acts as a collection area for plug-ins that can be used to
13231
         * extend DataTables capabilities. Indeed many of the build in methods
13232
         * use this method to provide their own capabilities (sorting methods for
13233
         * example).
13234
         *
13235
         * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy
13236
         * reasons
13237
         *
13238
         *  @namespace
13239
         */
13240
        DataTable.ext = _ext = {
13241
                /**
13242
                 * Element class names
13243
                 *
13244
                 *  @type object
13245
                 *  @default {}
13246
                 */
13247
                classes: {},
13248
 
13249
 
13250
                /**
13251
                 * Error reporting.
13252
                 *
13253
                 * How should DataTables report an error. Can take the value 'alert' or
13254
                 * 'throw'
13255
                 *
13256
                 *  @type string
13257
                 *  @default alert
13258
                 */
13259
                errMode: "alert",
13260
 
13261
 
13262
                /**
13263
                 * Feature plug-ins.
13264
                 *
13265
                 * This is an array of objects which describe the feature plug-ins that are
13266
                 * available to DataTables. These feature plug-ins are then available for
13267
                 * use through the `dom` initialisation option.
13268
                 *
13269
                 * Each feature plug-in is described by an object which must have the
13270
                 * following properties:
13271
                 *
13272
                 * * `fnInit` - function that is used to initialise the plug-in,
13273
                 * * `cFeature` - a character so the feature can be enabled by the `dom`
13274
                 *   instillation option. This is case sensitive.
13275
                 *
13276
                 * The `fnInit` function has the following input parameters:
13277
                 *
13278
                 * 1. `{object}` DataTables settings object: see
13279
                 *    {@link DataTable.models.oSettings}
13280
                 *
13281
                 * And the following return is expected:
13282
                 *
13283
                 * * {node|null} The element which contains your feature. Note that the
13284
                 *   return may also be void if your plug-in does not require to inject any
13285
                 *   DOM elements into DataTables control (`dom`) - for example this might
13286
                 *   be useful when developing a plug-in which allows table control via
13287
                 *   keyboard entry
13288
                 *
13289
                 *  @type array
13290
                 *
13291
                 *  @example
13292
                 *    $.fn.dataTable.ext.features.push( {
13293
                 *      "fnInit": function( oSettings ) {
13294
                 *        return new TableTools( { "oDTSettings": oSettings } );
13295
                 *      },
13296
                 *      "cFeature": "T"
13297
                 *    } );
13298
                 */
13299
                feature: [],
13300
 
13301
 
13302
                /**
13303
                 * Row searching.
13304
                 *
13305
                 * This method of searching is complimentary to the default type based
13306
                 * searching, and a lot more comprehensive as it allows you complete control
13307
                 * over the searching logic. Each element in this array is a function
13308
                 * (parameters described below) that is called for every row in the table,
13309
                 * and your logic decides if it should be included in the searching data set
13310
                 * or not.
13311
                 *
13312
                 * Searching functions have the following input parameters:
13313
                 *
13314
                 * 1. `{object}` DataTables settings object: see
13315
                 *    {@link DataTable.models.oSettings}
13316
                 * 2. `{array|object}` Data for the row to be processed (same as the
13317
                 *    original format that was passed in as the data source, or an array
13318
                 *    from a DOM data source
13319
                 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which
13320
                 *    can be useful to retrieve the `TR` element if you need DOM interaction.
13321
                 *
13322
                 * And the following return is expected:
13323
                 *
13324
                 * * {boolean} Include the row in the searched result set (true) or not
13325
                 *   (false)
13326
                 *
13327
                 * Note that as with the main search ability in DataTables, technically this
13328
                 * is "filtering", since it is subtractive. However, for consistency in
13329
                 * naming we call it searching here.
13330
                 *
13331
                 *  @type array
13332
                 *  @default []
13333
                 *
13334
                 *  @example
13335
                 *    // The following example shows custom search being applied to the
13336
                 *    // fourth column (i.e. the data[3] index) based on two input values
13337
                 *    // from the end-user, matching the data in a certain range.
13338
                 *    $.fn.dataTable.ext.search.push(
13339
                 *      function( settings, data, dataIndex ) {
13340
                 *        var min = document.getElementById('min').value * 1;
13341
                 *        var max = document.getElementById('max').value * 1;
13342
                 *        var version = data[3] == "-" ? 0 : data[3]*1;
13343
                 *
13344
                 *        if ( min == "" && max == "" ) {
13345
                 *          return true;
13346
                 *        }
13347
                 *        else if ( min == "" && version < max ) {
13348
                 *          return true;
13349
                 *        }
13350
                 *        else if ( min < version && "" == max ) {
13351
                 *          return true;
13352
                 *        }
13353
                 *        else if ( min < version && version < max ) {
13354
                 *          return true;
13355
                 *        }
13356
                 *        return false;
13357
                 *      }
13358
                 *    );
13359
                 */
13360
                search: [],
13361
 
13362
 
13363
                /**
13364
                 * Internal functions, exposed for used in plug-ins.
13365
                 *
13366
                 * Please note that you should not need to use the internal methods for
13367
                 * anything other than a plug-in (and even then, try to avoid if possible).
13368
                 * The internal function may change between releases.
13369
                 *
13370
                 *  @type object
13371
                 *  @default {}
13372
                 */
13373
                internal: {},
13374
 
13375
 
13376
                /**
13377
                 * Legacy configuration options. Enable and disable legacy options that
13378
                 * are available in DataTables.
13379
                 *
13380
                 *  @type object
13381
                 */
13382
                legacy: {
13383
                        /**
13384
                         * Enable / disable DataTables 1.9 compatible server-side processing
13385
                         * requests
13386
                         *
13387
                         *  @type boolean
13388
                         *  @default null
13389
                         */
13390
                        ajax: null
13391
                },
13392
 
13393
 
13394
                /**
13395
                 * Pagination plug-in methods.
13396
                 *
13397
                 * Each entry in this object is a function and defines which buttons should
13398
                 * be shown by the pagination rendering method that is used for the table:
13399
                 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the
13400
                 * buttons are displayed in the document, while the functions here tell it
13401
                 * what buttons to display. This is done by returning an array of button
13402
                 * descriptions (what each button will do).
13403
                 *
13404
                 * Pagination types (the four built in options and any additional plug-in
13405
                 * options defined here) can be used through the `paginationType`
13406
                 * initialisation parameter.
13407
                 *
13408
                 * The functions defined take two parameters:
13409
                 *
13410
                 * 1. `{int} page` The current page index
13411
                 * 2. `{int} pages` The number of pages in the table
13412
                 *
13413
                 * Each function is expected to return an array where each element of the
13414
                 * array can be one of:
13415
                 *
13416
                 * * `first` - Jump to first page when activated
13417
                 * * `last` - Jump to last page when activated
13418
                 * * `previous` - Show previous page when activated
13419
                 * * `next` - Show next page when activated
13420
                 * * `{int}` - Show page of the index given
13421
                 * * `{array}` - A nested array containing the above elements to add a
13422
                 *   containing 'DIV' element (might be useful for styling).
13423
                 *
13424
                 * Note that DataTables v1.9- used this object slightly differently whereby
13425
                 * an object with two functions would be defined for each plug-in. That
13426
                 * ability is still supported by DataTables 1.10+ to provide backwards
13427
                 * compatibility, but this option of use is now decremented and no longer
13428
                 * documented in DataTables 1.10+.
13429
                 *
13430
                 *  @type object
13431
                 *  @default {}
13432
                 *
13433
                 *  @example
13434
                 *    // Show previous, next and current page buttons only
13435
                 *    $.fn.dataTableExt.oPagination.current = function ( page, pages ) {
13436
                 *      return [ 'previous', page, 'next' ];
13437
                 *    };
13438
                 */
13439
                pager: {},
13440
 
13441
 
13442
                renderer: {
13443
                        pageButton: {},
13444
                        header: {}
13445
                },
13446
 
13447
 
13448
                /**
13449
                 * Ordering plug-ins - custom data source
13450
                 *
13451
                 * The extension options for ordering of data available here is complimentary
13452
                 * to the default type based ordering that DataTables typically uses. It
13453
                 * allows much greater control over the the data that is being used to
13454
                 * order a column, but is necessarily therefore more complex.
13455
                 *
13456
                 * This type of ordering is useful if you want to do ordering based on data
13457
                 * live from the DOM (for example the contents of an 'input' element) rather
13458
                 * than just the static string that DataTables knows of.
13459
                 *
13460
                 * The way these plug-ins work is that you create an array of the values you
13461
                 * wish to be ordering for the column in question and then return that
13462
                 * array. The data in the array much be in the index order of the rows in
13463
                 * the table (not the currently ordering order!). Which order data gathering
13464
                 * function is run here depends on the `dt-init columns.orderDataType`
13465
                 * parameter that is used for the column (if any).
13466
                 *
13467
                 * The functions defined take two parameters:
13468
                 *
13469
                 * 1. `{object}` DataTables settings object: see
13470
                 *    {@link DataTable.models.oSettings}
13471
                 * 2. `{int}` Target column index
13472
                 *
13473
                 * Each function is expected to return an array:
13474
                 *
13475
                 * * `{array}` Data for the column to be ordering upon
13476
                 *
13477
                 *  @type array
13478
                 *
13479
                 *  @example
13480
                 *    // Ordering using `input` node values
13481
                 *    $.fn.dataTable.ext.order['dom-text'] = function  ( settings, col )
13482
                 *    {
13483
                 *      return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) {
13484
                 *        return $('input', td).val();
13485
                 *      } );
13486
                 *    }
13487
                 */
13488
                order: {},
13489
 
13490
 
13491
                /**
13492
                 * Type based plug-ins.
13493
                 *
13494
                 * Each column in DataTables has a type assigned to it, either by automatic
13495
                 * detection or by direct assignment using the `type` option for the column.
13496
                 * The type of a column will effect how it is ordering and search (plug-ins
13497
                 * can also make use of the column type if required).
13498
                 *
13499
                 * @namespace
13500
                 */
13501
                type: {
13502
                        /**
13503
                         * Type detection functions.
13504
                         *
13505
                         * The functions defined in this object are used to automatically detect
13506
                         * a column's type, making initialisation of DataTables super easy, even
13507
                         * when complex data is in the table.
13508
                         *
13509
                         * The functions defined take two parameters:
13510
                         *
13511
                     *  1. `{*}` Data from the column cell to be analysed
13512
                     *  2. `{settings}` DataTables settings object. This can be used to
13513
                     *     perform context specific type detection - for example detection
13514
                     *     based on language settings such as using a comma for a decimal
13515
                     *     place. Generally speaking the options from the settings will not
13516
                     *     be required
13517
                         *
13518
                         * Each function is expected to return:
13519
                         *
13520
                         * * `{string|null}` Data type detected, or null if unknown (and thus
13521
                         *   pass it on to the other type detection functions.
13522
                         *
13523
                         *  @type array
13524
                         *
13525
                         *  @example
13526
                         *    // Currency type detection plug-in:
13527
                         *    $.fn.dataTable.ext.type.detect.push(
13528
                         *      function ( data, settings ) {
13529
                         *        // Check the numeric part
13530
                         *        if ( ! $.isNumeric( data.substring(1) ) ) {
13531
                         *          return null;
13532
                         *        }
13533
                         *
13534
                         *        // Check prefixed by currency
13535
                         *        if ( data.charAt(0) == '$' || data.charAt(0) == '&pound;' ) {
13536
                         *          return 'currency';
13537
                         *        }
13538
                         *        return null;
13539
                         *      }
13540
                         *    );
13541
                         */
13542
                        detect: [],
13543
 
13544
 
13545
                        /**
13546
                         * Type based search formatting.
13547
                         *
13548
                         * The type based searching functions can be used to pre-format the
13549
                         * data to be search on. For example, it can be used to strip HTML
13550
                         * tags or to de-format telephone numbers for numeric only searching.
13551
                         *
13552
                         * Note that is a search is not defined for a column of a given type,
13553
                         * no search formatting will be performed.
13554
                         *
13555
                         * Pre-processing of searching data plug-ins - When you assign the sType
13556
                         * for a column (or have it automatically detected for you by DataTables
13557
                         * or a type detection plug-in), you will typically be using this for
13558
                         * custom sorting, but it can also be used to provide custom searching
13559
                         * by allowing you to pre-processing the data and returning the data in
13560
                         * the format that should be searched upon. This is done by adding
13561
                         * functions this object with a parameter name which matches the sType
13562
                         * for that target column. This is the corollary of <i>afnSortData</i>
13563
                         * for searching data.
13564
                         *
13565
                         * The functions defined take a single parameter:
13566
                         *
13567
                     *  1. `{*}` Data from the column cell to be prepared for searching
13568
                         *
13569
                         * Each function is expected to return:
13570
                         *
13571
                         * * `{string|null}` Formatted string that will be used for the searching.
13572
                         *
13573
                         *  @type object
13574
                         *  @default {}
13575
                         *
13576
                         *  @example
13577
                         *    $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) {
13578
                         *      return d.replace(/\n/g," ").replace( /<.*?>/g, "" );
13579
                         *    }
13580
                         */
13581
                        search: {},
13582
 
13583
 
13584
                        /**
13585
                         * Type based ordering.
13586
                         *
13587
                         * The column type tells DataTables what ordering to apply to the table
13588
                         * when a column is sorted upon. The order for each type that is defined,
13589
                         * is defined by the functions available in this object.
13590
                         *
13591
                         * Each ordering option can be described by three properties added to
13592
                         * this object:
13593
                         *
13594
                         * * `{type}-pre` - Pre-formatting function
13595
                         * * `{type}-asc` - Ascending order function
13596
                         * * `{type}-desc` - Descending order function
13597
                         *
13598
                         * All three can be used together, only `{type}-pre` or only
13599
                         * `{type}-asc` and `{type}-desc` together. It is generally recommended
13600
                         * that only `{type}-pre` is used, as this provides the optimal
13601
                         * implementation in terms of speed, although the others are provided
13602
                         * for compatibility with existing Javascript sort functions.
13603
                         *
13604
                         * `{type}-pre`: Functions defined take a single parameter:
13605
                         *
13606
                     *  1. `{*}` Data from the column cell to be prepared for ordering
13607
                         *
13608
                         * And return:
13609
                         *
13610
                         * * `{*}` Data to be sorted upon
13611
                         *
13612
                         * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort
13613
                         * functions, taking two parameters:
13614
                         *
13615
                     *  1. `{*}` Data to compare to the second parameter
13616
                     *  2. `{*}` Data to compare to the first parameter
13617
                         *
13618
                         * And returning:
13619
                         *
13620
                         * * `{*}` Ordering match: <0 if first parameter should be sorted lower
13621
                         *   than the second parameter, ===0 if the two parameters are equal and
13622
                         *   >0 if the first parameter should be sorted height than the second
13623
                         *   parameter.
13624
                         *
13625
                         *  @type object
13626
                         *  @default {}
13627
                         *
13628
                         *  @example
13629
                         *    // Numeric ordering of formatted numbers with a pre-formatter
13630
                         *    $.extend( $.fn.dataTable.ext.type.order, {
13631
                         *      "string-pre": function(x) {
13632
                         *        a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" );
13633
                         *        return parseFloat( a );
13634
                         *      }
13635
                         *    } );
13636
                         *
13637
                         *  @example
13638
                         *    // Case-sensitive string ordering, with no pre-formatting method
13639
                         *    $.extend( $.fn.dataTable.ext.order, {
13640
                         *      "string-case-asc": function(x,y) {
13641
                         *        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
13642
                         *      },
13643
                         *      "string-case-desc": function(x,y) {
13644
                         *        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
13645
                         *      }
13646
                         *    } );
13647
                         */
13648
                        order: {}
13649
                },
13650
 
13651
                /**
13652
                 * Unique DataTables instance counter
13653
                 *
13654
                 * @type int
13655
                 * @private
13656
                 */
13657
                _unique: 0,
13658
 
13659
 
13660
                //
13661
                // Depreciated
13662
                // The following properties are retained for backwards compatiblity only.
13663
                // The should not be used in new projects and will be removed in a future
13664
                // version
13665
                //
13666
 
13667
                /**
13668
                 * Version check function.
13669
                 *  @type function
13670
                 *  @depreciated Since 1.10
13671
                 */
13672
                fnVersionCheck: DataTable.fnVersionCheck,
13673
 
13674
 
13675
                /**
13676
                 * Index for what 'this' index API functions should use
13677
                 *  @type int
13678
                 *  @deprecated Since v1.10
13679
                 */
13680
                iApiIndex: 0,
13681
 
13682
 
13683
                /**
13684
                 * jQuery UI class container
13685
                 *  @type object
13686
                 *  @deprecated Since v1.10
13687
                 */
13688
                oJUIClasses: {},
13689
 
13690
 
13691
                /**
13692
                 * Software version
13693
                 *  @type string
13694
                 *  @deprecated Since v1.10
13695
                 */
13696
                sVersion: DataTable.version
13697
        };
13698
 
13699
 
13700
        //
13701
        // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts
13702
        //
13703
        $.extend( _ext, {
13704
                afnFiltering: _ext.search,
13705
                aTypes:       _ext.type.detect,
13706
                ofnSearch:    _ext.type.search,
13707
                oSort:        _ext.type.order,
13708
                afnSortData:  _ext.order,
13709
                aoFeatures:   _ext.feature,
13710
                oApi:         _ext.internal,
13711
                oStdClasses:  _ext.classes,
13712
                oPagination:  _ext.pager
13713
        } );
13714
 
13715
 
13716
        $.extend( DataTable.ext.classes, {
13717
                "sTable": "dataTable",
13718
                "sNoFooter": "no-footer",
13719
 
13720
                /* Paging buttons */
13721
                "sPageButton": "paginate_button",
13722
                "sPageButtonActive": "current",
13723
                "sPageButtonDisabled": "disabled",
13724
 
13725
                /* Striping classes */
13726
                "sStripeOdd": "odd",
13727
                "sStripeEven": "even",
13728
 
13729
                /* Empty row */
13730
                "sRowEmpty": "dataTables_empty",
13731
 
13732
                /* Features */
13733
                "sWrapper": "dataTables_wrapper",
13734
                "sFilter": "dataTables_filter",
13735
                "sInfo": "dataTables_info",
13736
                "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */
13737
                "sLength": "dataTables_length",
13738
                "sProcessing": "dataTables_processing",
13739
 
13740
                /* Sorting */
13741
                "sSortAsc": "sorting_asc",
13742
                "sSortDesc": "sorting_desc",
13743
                "sSortable": "sorting", /* Sortable in both directions */
13744
                "sSortableAsc": "sorting_asc_disabled",
13745
                "sSortableDesc": "sorting_desc_disabled",
13746
                "sSortableNone": "sorting_disabled",
13747
                "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */
13748
 
13749
                /* Filtering */
13750
                "sFilterInput": "",
13751
 
13752
                /* Page length */
13753
                "sLengthSelect": "",
13754
 
13755
                /* Scrolling */
13756
                "sScrollWrapper": "dataTables_scroll",
13757
                "sScrollHead": "dataTables_scrollHead",
13758
                "sScrollHeadInner": "dataTables_scrollHeadInner",
13759
                "sScrollBody": "dataTables_scrollBody",
13760
                "sScrollFoot": "dataTables_scrollFoot",
13761
                "sScrollFootInner": "dataTables_scrollFootInner",
13762
 
13763
                /* Misc */
13764
                "sHeaderTH": "",
13765
                "sFooterTH": "",
13766
 
13767
                // Deprecated
13768
                "sSortJUIAsc": "",
13769
                "sSortJUIDesc": "",
13770
                "sSortJUI": "",
13771
                "sSortJUIAscAllowed": "",
13772
                "sSortJUIDescAllowed": "",
13773
                "sSortJUIWrapper": "",
13774
                "sSortIcon": "",
13775
                "sJUIHeader": "",
13776
                "sJUIFooter": ""
13777
        } );
13778
 
13779
 
13780
        (function() {
13781
 
13782
        // Reused strings for better compression. Closure compiler appears to have a
13783
        // weird edge case where it is trying to expand strings rather than use the
13784
        // variable version. This results in about 200 bytes being added, for very
13785
        // little preference benefit since it this run on script load only.
13786
        var _empty = '';
13787
        _empty = '';
13788
 
13789
        var _stateDefault = _empty + 'ui-state-default';
13790
        var _sortIcon     = _empty + 'css_right ui-icon ui-icon-';
13791
        var _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix';
13792
 
13793
        $.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, {
13794
                /* Full numbers paging buttons */
13795
                "sPageButton":         "fg-button ui-button "+_stateDefault,
13796
                "sPageButtonActive":   "ui-state-disabled",
13797
                "sPageButtonDisabled": "ui-state-disabled",
13798
 
13799
                /* Features */
13800
                "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+
13801
                        "ui-buttonset-multi paging_", /* Note that the type is postfixed */
13802
 
13803
                /* Sorting */
13804
                "sSortAsc":            _stateDefault+" sorting_asc",
13805
                "sSortDesc":           _stateDefault+" sorting_desc",
13806
                "sSortable":           _stateDefault+" sorting",
13807
                "sSortableAsc":        _stateDefault+" sorting_asc_disabled",
13808
                "sSortableDesc":       _stateDefault+" sorting_desc_disabled",
13809
                "sSortableNone":       _stateDefault+" sorting_disabled",
13810
                "sSortJUIAsc":         _sortIcon+"triangle-1-n",
13811
                "sSortJUIDesc":        _sortIcon+"triangle-1-s",
13812
                "sSortJUI":            _sortIcon+"carat-2-n-s",
13813
                "sSortJUIAscAllowed":  _sortIcon+"carat-1-n",
13814
                "sSortJUIDescAllowed": _sortIcon+"carat-1-s",
13815
                "sSortJUIWrapper":     "DataTables_sort_wrapper",
13816
                "sSortIcon":           "DataTables_sort_icon",
13817
 
13818
                /* Scrolling */
13819
                "sScrollHead": "dataTables_scrollHead "+_stateDefault,
13820
                "sScrollFoot": "dataTables_scrollFoot "+_stateDefault,
13821
 
13822
                /* Misc */
13823
                "sHeaderTH":  _stateDefault,
13824
                "sFooterTH":  _stateDefault,
13825
                "sJUIHeader": _headerFooter+" ui-corner-tl ui-corner-tr",
13826
                "sJUIFooter": _headerFooter+" ui-corner-bl ui-corner-br"
13827
        } );
13828
 
13829
        }());
13830
 
13831
 
13832
 
13833
        var extPagination = DataTable.ext.pager;
13834
 
13835
        function _numbers ( page, pages ) {
13836
                var
13837
                        numbers = [],
13838
                        buttons = extPagination.numbers_length,
13839
                        half = Math.floor( buttons / 2 ),
13840
                        i = 1;
13841
 
13842
                if ( pages <= buttons ) {
13843
                        numbers = _range( 0, pages );
13844
                }
13845
                else if ( page <= half ) {
13846
                        numbers = _range( 0, buttons-2 );
13847
                        numbers.push( 'ellipsis' );
13848
                        numbers.push( pages-1 );
13849
                }
13850
                else if ( page >= pages - 1 - half ) {
13851
                        numbers = _range( pages-(buttons-2), pages );
13852
                        numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6
13853
                        numbers.splice( 0, 0, 0 );
13854
                }
13855
                else {
13856
                        numbers = _range( page-1, page+2 );
13857
                        numbers.push( 'ellipsis' );
13858
                        numbers.push( pages-1 );
13859
                        numbers.splice( 0, 0, 'ellipsis' );
13860
                        numbers.splice( 0, 0, 0 );
13861
                }
13862
 
13863
                numbers.DT_el = 'span';
13864
                return numbers;
13865
        }
13866
 
13867
 
13868
        $.extend( extPagination, {
13869
                simple: function ( page, pages ) {
13870
                        return [ 'previous', 'next' ];
13871
                },
13872
 
13873
                full: function ( page, pages ) {
13874
                        return [  'first', 'previous', 'next', 'last' ];
13875
                },
13876
 
13877
                simple_numbers: function ( page, pages ) {
13878
                        return [ 'previous', _numbers(page, pages), 'next' ];
13879
                },
13880
 
13881
                full_numbers: function ( page, pages ) {
13882
                        return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ];
13883
                },
13884
 
13885
                // For testing and plug-ins to use
13886
                _numbers: _numbers,
13887
                numbers_length: 7
13888
        } );
13889
 
13890
 
13891
        $.extend( true, DataTable.ext.renderer, {
13892
                pageButton: {
13893
                        _: function ( settings, host, idx, buttons, page, pages ) {
13894
                                var classes = settings.oClasses;
13895
                                var lang = settings.oLanguage.oPaginate;
13896
                                var btnDisplay, btnClass, counter=0;
13897
 
13898
                                var attach = function( container, buttons ) {
13899
                                        var i, ien, node, button;
13900
                                        var clickHandler = function ( e ) {
13901
                                                _fnPageChange( settings, e.data.action, true );
13902
                                        };
13903
 
13904
                                        for ( i=0, ien=buttons.length ; i<ien ; i++ ) {
13905
                                                button = buttons[i];
13906
 
13907
                                                if ( $.isArray( button ) ) {
13908
                                                        var inner = $( '<'+(button.DT_el || 'div')+'/>' )
13909
                                                                .appendTo( container );
13910
                                                        attach( inner, button );
13911
                                                }
13912
                                                else {
13913
                                                        btnDisplay = '';
13914
                                                        btnClass = '';
13915
 
13916
                                                        switch ( button ) {
13917
                                                                case 'ellipsis':
13918
                                                                        container.append('<span>&hellip;</span>');
13919
                                                                        break;
13920
 
13921
                                                                case 'first':
13922
                                                                        btnDisplay = lang.sFirst;
13923
                                                                        btnClass = button + (page > 0 ?
13924
                                                                                '' : ' '+classes.sPageButtonDisabled);
13925
                                                                        break;
13926
 
13927
                                                                case 'previous':
13928
                                                                        btnDisplay = lang.sPrevious;
13929
                                                                        btnClass = button + (page > 0 ?
13930
                                                                                '' : ' '+classes.sPageButtonDisabled);
13931
                                                                        break;
13932
 
13933
                                                                case 'next':
13934
                                                                        btnDisplay = lang.sNext;
13935
                                                                        btnClass = button + (page < pages-1 ?
13936
                                                                                '' : ' '+classes.sPageButtonDisabled);
13937
                                                                        break;
13938
 
13939
                                                                case 'last':
13940
                                                                        btnDisplay = lang.sLast;
13941
                                                                        btnClass = button + (page < pages-1 ?
13942
                                                                                '' : ' '+classes.sPageButtonDisabled);
13943
                                                                        break;
13944
 
13945
                                                                default:
13946
                                                                        btnDisplay = button + 1;
13947
                                                                        btnClass = page === button ?
13948
                                                                                classes.sPageButtonActive : '';
13949
                                                                        break;
13950
                                                        }
13951
 
13952
                                                        if ( btnDisplay ) {
13953
                                                                node = $('<a>', {
13954
                                                                                'class': classes.sPageButton+' '+btnClass,
13955
                                                                                'aria-controls': settings.sTableId,
13956
                                                                                'data-dt-idx': counter,
13957
                                                                                'tabindex': settings.iTabIndex,
13958
                                                                                'id': idx === 0 && typeof button === 'string' ?
13959
                                                                                        settings.sTableId +'_'+ button :
13960
                                                                                        null
13961
                                                                        } )
13962
                                                                        .html( btnDisplay )
13963
                                                                        .appendTo( container );
13964
 
13965
                                                                _fnBindAction(
13966
                                                                        node, {action: button}, clickHandler
13967
                                                                );
13968
 
13969
                                                                counter++;
13970
                                                        }
13971
                                                }
13972
                                        }
13973
                                };
13974
 
13975
                                // IE9 throws an 'unknown error' if document.activeElement is used
13976
                                // inside an iframe or frame. Try / catch the error. Not good for
13977
                                // accessibility, but neither are frames.
13978
                                try {
13979
                                        // Because this approach is destroying and recreating the paging
13980
                                        // elements, focus is lost on the select button which is bad for
13981
                                        // accessibility. So we want to restore focus once the draw has
13982
                                        // completed
13983
                                        var activeEl = $(document.activeElement).data('dt-idx');
13984
 
13985
                                        attach( $(host).empty(), buttons );
13986
 
13987
                                        if ( activeEl !== null ) {
13988
                                                $(host).find( '[data-dt-idx='+activeEl+']' ).focus();
13989
                                        }
13990
                                }
13991
                                catch (e) {}
13992
                        }
13993
                }
13994
        } );
13995
 
13996
 
13997
 
13998
        var __numericReplace = function ( d, decimalPlace, re1, re2 ) {
13999
                if ( !d || d === '-' ) {
14000
                        return -Infinity;
14001
                }
14002
 
14003
                // If a decimal place other than `.` is used, it needs to be given to the
14004
                // function so we can detect it and replace with a `.` which is the only
14005
                // decimal place Javascript recognises - it is not locale aware.
14006
                if ( decimalPlace ) {
14007
                        d = _numToDecimal( d, decimalPlace );
14008
                }
14009
 
14010
                if ( d.replace ) {
14011
                        if ( re1 ) {
14012
                                d = d.replace( re1, '' );
14013
                        }
14014
 
14015
                        if ( re2 ) {
14016
                                d = d.replace( re2, '' );
14017
                        }
14018
                }
14019
 
14020
                return d * 1;
14021
        };
14022
 
14023
 
14024
        // Add the numeric 'deformatting' functions for sorting. This is done in a
14025
        // function to provide an easy ability for the language options to add
14026
        // additional methods if a non-period decimal place is used.
14027
        function _addNumericSort ( decimalPlace ) {
14028
                $.each(
14029
                        {
14030
                                // Plain numbers
14031
                                "num": function ( d ) {
14032
                                        return __numericReplace( d, decimalPlace );
14033
                                },
14034
 
14035
                                // Formatted numbers
14036
                                "num-fmt": function ( d ) {
14037
                                        return __numericReplace( d, decimalPlace, _re_formatted_numeric );
14038
                                },
14039
 
14040
                                // HTML numeric
14041
                                "html-num": function ( d ) {
14042
                                        return __numericReplace( d, decimalPlace, _re_html );
14043
                                },
14044
 
14045
                                // HTML numeric, formatted
14046
                                "html-num-fmt": function ( d ) {
14047
                                        return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric );
14048
                                }
14049
                        },
14050
                        function ( key, fn ) {
14051
                                _ext.type.order[ key+decimalPlace+'-pre' ] = fn;
14052
                        }
14053
                );
14054
        }
14055
 
14056
 
14057
        // Default sort methods
14058
        $.extend( _ext.type.order, {
14059
                // Dates
14060
                "date-pre": function ( d ) {
14061
                        return Date.parse( d ) || 0;
14062
                },
14063
 
14064
                // html
14065
                "html-pre": function ( a ) {
14066
                        return _empty(a) ?
14067
                                '' :
14068
                                a.replace ?
14069
                                        a.replace( /<.*?>/g, "" ).toLowerCase() :
14070
                                        a+'';
14071
                },
14072
 
14073
                // string
14074
                "string-pre": function ( a ) {
14075
                        // This is a little complex, but faster than always calling toString,
14076
                        // http://jsperf.com/tostring-v-check
14077
                        return _empty(a) ?
14078
                                '' :
14079
                                typeof a === 'string' ?
14080
                                        a.toLowerCase() :
14081
                                        ! a.toString ?
14082
                                                '' :
14083
                                                a.toString();
14084
                },
14085
 
14086
                // string-asc and -desc are retained only for compatibility with the old
14087
                // sort methods
14088
                "string-asc": function ( x, y ) {
14089
                        return ((x < y) ? -1 : ((x > y) ? 1 : 0));
14090
                },
14091
 
14092
                "string-desc": function ( x, y ) {
14093
                        return ((x < y) ? 1 : ((x > y) ? -1 : 0));
14094
                }
14095
        } );
14096
 
14097
 
14098
        // Numeric sorting types - order doesn't matter here
14099
        _addNumericSort( '' );
14100
 
14101
 
14102
        // Built in type detection. See model.ext.aTypes for information about
14103
        // what is required from this methods.
14104
        $.extend( DataTable.ext.type.detect, [
14105
                // Plain numbers - first since V8 detects some plain numbers as dates
14106
                // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...).
14107
                function ( d, settings )
14108
                {
14109
                        var decimal = settings.oLanguage.sDecimal;
14110
                        return _isNumber( d, decimal ) ? 'num'+decimal : null;
14111
                },
14112
 
14113
                // Dates (only those recognised by the browser's Date.parse)
14114
                function ( d, settings )
14115
                {
14116
                        // V8 will remove any unknown characters at the start and end of the
14117
                        // expression, leading to false matches such as `$245.12` or `10%` being
14118
                        // a valid date. See forum thread 18941 for detail.
14119
                        if ( d && ( ! _re_date_start.test(d) || ! _re_date_end.test(d) ) ) {
14120
                                return null;
14121
                        }
14122
                        var parsed = Date.parse(d);
14123
                        return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null;
14124
                },
14125
 
14126
                // Formatted numbers
14127
                function ( d, settings )
14128
                {
14129
                        var decimal = settings.oLanguage.sDecimal;
14130
                        return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null;
14131
                },
14132
 
14133
                // HTML numeric
14134
                function ( d, settings )
14135
                {
14136
                        var decimal = settings.oLanguage.sDecimal;
14137
                        return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null;
14138
                },
14139
 
14140
                // HTML numeric, formatted
14141
                function ( d, settings )
14142
                {
14143
                        var decimal = settings.oLanguage.sDecimal;
14144
                        return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null;
14145
                },
14146
 
14147
                // HTML (this is strict checking - there must be html)
14148
                function ( d, settings )
14149
                {
14150
                        return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ?
14151
                                'html' : null;
14152
                }
14153
        ] );
14154
 
14155
 
14156
 
14157
        // Filter formatting functions. See model.ext.ofnSearch for information about
14158
        // what is required from these methods.
14159
 
14160
 
14161
        $.extend( DataTable.ext.type.search, {
14162
                html: function ( data ) {
14163
                        return _empty(data) ?
14164
                                data :
14165
                                typeof data === 'string' ?
14166
                                        data
14167
                                                .replace( _re_new_lines, " " )
14168
                                                .replace( _re_html, "" ) :
14169
                                        '';
14170
                },
14171
 
14172
                string: function ( data ) {
14173
                        return _empty(data) ?
14174
                                data :
14175
                                typeof data === 'string' ?
14176
                                        data.replace( _re_new_lines, " " ) :
14177
                                        data;
14178
                }
14179
        } );
14180
 
14181
 
14182
 
14183
        $.extend( true, DataTable.ext.renderer, {
14184
                header: {
14185
                        _: function ( settings, cell, column, classes ) {
14186
                                // No additional mark-up required
14187
                                // Attach a sort listener to update on sort - note that using the
14188
                                // `DT` namespace will allow the event to be removed automatically
14189
                                // on destroy, while the `dt` namespaced event is the one we are
14190
                                // listening for
14191
                                $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14192
                                        if ( settings !== ctx ) { // need to check this this is the host
14193
                                                return;               // table, not a nested one
14194
                                        }
14195
 
14196
                                        var colIdx = column.idx;
14197
 
14198
                                        cell
14199
                                                .removeClass(
14200
                                                        column.sSortingClass +' '+
14201
                                                        classes.sSortAsc +' '+
14202
                                                        classes.sSortDesc
14203
                                                )
14204
                                                .addClass( columns[ colIdx ] == 'asc' ?
14205
                                                        classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14206
                                                                classes.sSortDesc :
14207
                                                                column.sSortingClass
14208
                                                );
14209
                                } );
14210
                        },
14211
 
14212
                        jqueryui: function ( settings, cell, column, classes ) {
14213
                                var colIdx = column.idx;
14214
 
14215
                                $('<div/>')
14216
                                        .addClass( classes.sSortJUIWrapper )
14217
                                        .append( cell.contents() )
14218
                                        .append( $('<span/>')
14219
                                                .addClass( classes.sSortIcon+' '+column.sSortingClassJUI )
14220
                                        )
14221
                                        .appendTo( cell );
14222
 
14223
                                // Attach a sort listener to update on sort
14224
                                $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) {
14225
                                        if ( settings !== ctx ) {
14226
                                                return;
14227
                                        }
14228
 
14229
                                        cell
14230
                                                .removeClass( classes.sSortAsc +" "+classes.sSortDesc )
14231
                                                .addClass( columns[ colIdx ] == 'asc' ?
14232
                                                        classes.sSortAsc : columns[ colIdx ] == 'desc' ?
14233
                                                                classes.sSortDesc :
14234
                                                                column.sSortingClass
14235
                                                );
14236
 
14237
                                        cell
14238
                                                .find( 'span.'+classes.sSortIcon )
14239
                                                .removeClass(
14240
                                                        classes.sSortJUIAsc +" "+
14241
                                                        classes.sSortJUIDesc +" "+
14242
                                                        classes.sSortJUI +" "+
14243
                                                        classes.sSortJUIAscAllowed +" "+
14244
                                                        classes.sSortJUIDescAllowed
14245
                                                )
14246
                                                .addClass( columns[ colIdx ] == 'asc' ?
14247
                                                        classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ?
14248
                                                                classes.sSortJUIDesc :
14249
                                                                column.sSortingClassJUI
14250
                                                );
14251
                                } );
14252
                        }
14253
                }
14254
        } );
14255
 
14256
        /*
14257
         * Public helper functions. These aren't used internally by DataTables, or
14258
         * called by any of the options passed into DataTables, but they can be used
14259
         * externally by developers working with DataTables. They are helper functions
14260
         * to make working with DataTables a little bit easier.
14261
         */
14262
 
14263
        /**
14264
         * Helpers for `columns.render`.
14265
         *
14266
         * The options defined here can be used with the `columns.render` initialisation
14267
         * option to provide a display renderer. The following functions are defined:
14268
         *
14269
         * * `number` - Will format numeric data (defined by `columns.data`) for
14270
         *   display, retaining the original unformatted data for sorting and filtering.
14271
         *   It takes 4 parameters:
14272
         *   * `string` - Thousands grouping separator
14273
         *   * `string` - Decimal point indicator
14274
         *   * `integer` - Number of decimal points to show
14275
         *   * `string` (optional) - Prefix.
14276
         *
14277
         * @example
14278
         *   // Column definition using the number renderer
14279
         *   {
14280
         *     data: "salary",
14281
         *     render: $.fn.dataTable.render.number( '\'', '.', 0, '$' )
14282
         *   }
14283
         *
14284
         * @namespace
14285
         */
14286
        DataTable.render = {
14287
                number: function ( thousands, decimal, precision, prefix ) {
14288
                        return {
14289
                                display: function ( d ) {
14290
                                        var negative = d < 0 ? '-' : '';
14291
                                        d = Math.abs( parseFloat( d ) );
14292
 
14293
                                        var intPart = parseInt( d, 10 );
14294
                                        var floatPart = precision ?
14295
                                                decimal+(d - intPart).toFixed( precision ).substring( 2 ):
14296
                                                '';
14297
 
14298
                                        return negative + (prefix||'') +
14299
                                                intPart.toString().replace(
14300
                                                        /\B(?=(\d{3})+(?!\d))/g, thousands
14301
                                                ) +
14302
                                                floatPart;
14303
                                }
14304
                        };
14305
                }
14306
        };
14307
 
14308
 
14309
        /*
14310
         * This is really a good bit rubbish this method of exposing the internal methods
14311
         * publicly... - To be fixed in 2.0 using methods on the prototype
14312
         */
14313
 
14314
 
14315
        /**
14316
         * Create a wrapper function for exporting an internal functions to an external API.
14317
         *  @param {string} fn API function name
14318
         *  @returns {function} wrapped function
14319
         *  @memberof DataTable#internal
14320
         */
14321
        function _fnExternApiFunc (fn)
14322
        {
14323
                return function() {
14324
                        var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat(
14325
                                Array.prototype.slice.call(arguments)
14326
                        );
14327
                        return DataTable.ext.internal[fn].apply( this, args );
14328
                };
14329
        }
14330
 
14331
 
14332
        /**
14333
         * Reference to internal functions for use by plug-in developers. Note that
14334
         * these methods are references to internal functions and are considered to be
14335
         * private. If you use these methods, be aware that they are liable to change
14336
         * between versions.
14337
         *  @namespace
14338
         */
14339
        $.extend( DataTable.ext.internal, {
14340
                _fnExternApiFunc: _fnExternApiFunc,
14341
                _fnBuildAjax: _fnBuildAjax,
14342
                _fnAjaxUpdate: _fnAjaxUpdate,
14343
                _fnAjaxParameters: _fnAjaxParameters,
14344
                _fnAjaxUpdateDraw: _fnAjaxUpdateDraw,
14345
                _fnAjaxDataSrc: _fnAjaxDataSrc,
14346
                _fnAddColumn: _fnAddColumn,
14347
                _fnColumnOptions: _fnColumnOptions,
14348
                _fnAdjustColumnSizing: _fnAdjustColumnSizing,
14349
                _fnVisibleToColumnIndex: _fnVisibleToColumnIndex,
14350
                _fnColumnIndexToVisible: _fnColumnIndexToVisible,
14351
                _fnVisbleColumns: _fnVisbleColumns,
14352
                _fnGetColumns: _fnGetColumns,
14353
                _fnColumnTypes: _fnColumnTypes,
14354
                _fnApplyColumnDefs: _fnApplyColumnDefs,
14355
                _fnHungarianMap: _fnHungarianMap,
14356
                _fnCamelToHungarian: _fnCamelToHungarian,
14357
                _fnLanguageCompat: _fnLanguageCompat,
14358
                _fnBrowserDetect: _fnBrowserDetect,
14359
                _fnAddData: _fnAddData,
14360
                _fnAddTr: _fnAddTr,
14361
                _fnNodeToDataIndex: _fnNodeToDataIndex,
14362
                _fnNodeToColumnIndex: _fnNodeToColumnIndex,
14363
                _fnGetCellData: _fnGetCellData,
14364
                _fnSetCellData: _fnSetCellData,
14365
                _fnSplitObjNotation: _fnSplitObjNotation,
14366
                _fnGetObjectDataFn: _fnGetObjectDataFn,
14367
                _fnSetObjectDataFn: _fnSetObjectDataFn,
14368
                _fnGetDataMaster: _fnGetDataMaster,
14369
                _fnClearTable: _fnClearTable,
14370
                _fnDeleteIndex: _fnDeleteIndex,
14371
                _fnInvalidateRow: _fnInvalidateRow,
14372
                _fnGetRowElements: _fnGetRowElements,
14373
                _fnCreateTr: _fnCreateTr,
14374
                _fnBuildHead: _fnBuildHead,
14375
                _fnDrawHead: _fnDrawHead,
14376
                _fnDraw: _fnDraw,
14377
                _fnReDraw: _fnReDraw,
14378
                _fnAddOptionsHtml: _fnAddOptionsHtml,
14379
                _fnDetectHeader: _fnDetectHeader,
14380
                _fnGetUniqueThs: _fnGetUniqueThs,
14381
                _fnFeatureHtmlFilter: _fnFeatureHtmlFilter,
14382
                _fnFilterComplete: _fnFilterComplete,
14383
                _fnFilterCustom: _fnFilterCustom,
14384
                _fnFilterColumn: _fnFilterColumn,
14385
                _fnFilter: _fnFilter,
14386
                _fnFilterCreateSearch: _fnFilterCreateSearch,
14387
                _fnEscapeRegex: _fnEscapeRegex,
14388
                _fnFilterData: _fnFilterData,
14389
                _fnFeatureHtmlInfo: _fnFeatureHtmlInfo,
14390
                _fnUpdateInfo: _fnUpdateInfo,
14391
                _fnInfoMacros: _fnInfoMacros,
14392
                _fnInitialise: _fnInitialise,
14393
                _fnInitComplete: _fnInitComplete,
14394
                _fnLengthChange: _fnLengthChange,
14395
                _fnFeatureHtmlLength: _fnFeatureHtmlLength,
14396
                _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate,
14397
                _fnPageChange: _fnPageChange,
14398
                _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing,
14399
                _fnProcessingDisplay: _fnProcessingDisplay,
14400
                _fnFeatureHtmlTable: _fnFeatureHtmlTable,
14401
                _fnScrollDraw: _fnScrollDraw,
14402
                _fnApplyToChildren: _fnApplyToChildren,
14403
                _fnCalculateColumnWidths: _fnCalculateColumnWidths,
14404
                _fnThrottle: _fnThrottle,
14405
                _fnConvertToWidth: _fnConvertToWidth,
14406
                _fnScrollingWidthAdjust: _fnScrollingWidthAdjust,
14407
                _fnGetWidestNode: _fnGetWidestNode,
14408
                _fnGetMaxLenString: _fnGetMaxLenString,
14409
                _fnStringToCss: _fnStringToCss,
14410
                _fnScrollBarWidth: _fnScrollBarWidth,
14411
                _fnSortFlatten: _fnSortFlatten,
14412
                _fnSort: _fnSort,
14413
                _fnSortAria: _fnSortAria,
14414
                _fnSortListener: _fnSortListener,
14415
                _fnSortAttachListener: _fnSortAttachListener,
14416
                _fnSortingClasses: _fnSortingClasses,
14417
                _fnSortData: _fnSortData,
14418
                _fnSaveState: _fnSaveState,
14419
                _fnLoadState: _fnLoadState,
14420
                _fnSettingsFromNode: _fnSettingsFromNode,
14421
                _fnLog: _fnLog,
14422
                _fnMap: _fnMap,
14423
                _fnBindAction: _fnBindAction,
14424
                _fnCallbackReg: _fnCallbackReg,
14425
                _fnCallbackFire: _fnCallbackFire,
14426
                _fnLengthOverflow: _fnLengthOverflow,
14427
                _fnRenderer: _fnRenderer,
14428
                _fnDataSource: _fnDataSource,
14429
                _fnRowAttributes: _fnRowAttributes,
14430
                _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant
14431
                                                // in 1.10, so this dead-end function is
14432
                                                // added to prevent errors
14433
        } );
14434
 
14435
 
14436
        // jQuery access
14437
        $.fn.dataTable = DataTable;
14438
 
14439
        // Legacy aliases
14440
        $.fn.dataTableSettings = DataTable.settings;
14441
        $.fn.dataTableExt = DataTable.ext;
14442
 
14443
        // With a capital `D` we return a DataTables API instance rather than a
14444
        // jQuery object
14445
        $.fn.DataTable = function ( opts ) {
14446
                return $(this).dataTable( opts ).api();
14447
        };
14448
 
14449
        // All properties that are available to $.fn.dataTable should also be
14450
        // available on $.fn.DataTable
14451
        $.each( DataTable, function ( prop, val ) {
14452
                $.fn.DataTable[ prop ] = val;
14453
        } );
14454
 
14455
 
14456
        // Information about events fired by DataTables - for documentation.
14457
        /**
14458
         * Draw event, fired whenever the table is redrawn on the page, at the same
14459
         * point as fnDrawCallback. This may be useful for binding events or
14460
         * performing calculations when the table is altered at all.
14461
         *  @name DataTable#draw.dt
14462
         *  @event
14463
         *  @param {event} e jQuery event object
14464
         *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14465
         */
14466
 
14467
        /**
14468
         * Search event, fired when the searching applied to the table (using the
14469
         * built-in global search, or column filters) is altered.
14470
         *  @name DataTable#search.dt
14471
         *  @event
14472
         *  @param {event} e jQuery event object
14473
         *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14474
         */
14475
 
14476
        /**
14477
         * Page change event, fired when the paging of the table is altered.
14478
         *  @name DataTable#page.dt
14479
         *  @event
14480
         *  @param {event} e jQuery event object
14481
         *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14482
         */
14483
 
14484
        /**
14485
         * Order event, fired when the ordering applied to the table is altered.
14486
         *  @name DataTable#order.dt
14487
         *  @event
14488
         *  @param {event} e jQuery event object
14489
         *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14490
         */
14491
 
14492
        /**
14493
         * DataTables initialisation complete event, fired when the table is fully
14494
         * drawn, including Ajax data loaded, if Ajax data is required.
14495
         *  @name DataTable#init.dt
14496
         *  @event
14497
         *  @param {event} e jQuery event object
14498
         *  @param {object} oSettings DataTables settings object
14499
         *  @param {object} json The JSON object request from the server - only
14500
         *    present if client-side Ajax sourced data is used</li></ol>
14501
         */
14502
 
14503
        /**
14504
         * State save event, fired when the table has changed state a new state save
14505
         * is required. This event allows modification of the state saving object
14506
         * prior to actually doing the save, including addition or other state
14507
         * properties (for plug-ins) or modification of a DataTables core property.
14508
         *  @name DataTable#stateSaveParams.dt
14509
         *  @event
14510
         *  @param {event} e jQuery event object
14511
         *  @param {object} oSettings DataTables settings object
14512
         *  @param {object} json The state information to be saved
14513
         */
14514
 
14515
        /**
14516
         * State load event, fired when the table is loading state from the stored
14517
         * data, but prior to the settings object being modified by the saved state
14518
         * - allowing modification of the saved state is required or loading of
14519
         * state for a plug-in.
14520
         *  @name DataTable#stateLoadParams.dt
14521
         *  @event
14522
         *  @param {event} e jQuery event object
14523
         *  @param {object} oSettings DataTables settings object
14524
         *  @param {object} json The saved state information
14525
         */
14526
 
14527
        /**
14528
         * State loaded event, fired when state has been loaded from stored data and
14529
         * the settings object has been modified by the loaded data.
14530
         *  @name DataTable#stateLoaded.dt
14531
         *  @event
14532
         *  @param {event} e jQuery event object
14533
         *  @param {object} oSettings DataTables settings object
14534
         *  @param {object} json The saved state information
14535
         */
14536
 
14537
        /**
14538
         * Processing event, fired when DataTables is doing some kind of processing
14539
         * (be it, order, searcg or anything else). It can be used to indicate to
14540
         * the end user that there is something happening, or that something has
14541
         * finished.
14542
         *  @name DataTable#processing.dt
14543
         *  @event
14544
         *  @param {event} e jQuery event object
14545
         *  @param {object} oSettings DataTables settings object
14546
         *  @param {boolean} bShow Flag for if DataTables is doing processing or not
14547
         */
14548
 
14549
        /**
14550
         * Ajax (XHR) event, fired whenever an Ajax request is completed from a
14551
         * request to made to the server for new data. This event is called before
14552
         * DataTables processed the returned data, so it can also be used to pre-
14553
         * process the data returned from the server, if needed.
14554
         *
14555
         * Note that this trigger is called in `fnServerData`, if you override
14556
         * `fnServerData` and which to use this event, you need to trigger it in you
14557
         * success function.
14558
         *  @name DataTable#xhr.dt
14559
         *  @event
14560
         *  @param {event} e jQuery event object
14561
         *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14562
         *  @param {object} json JSON returned from the server
14563
         *
14564
         *  @example
14565
         *     // Use a custom property returned from the server in another DOM element
14566
         *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
14567
         *       $('#status').html( json.status );
14568
         *     } );
14569
         *
14570
         *  @example
14571
         *     // Pre-process the data returned from the server
14572
         *     $('#table').dataTable().on('xhr.dt', function (e, settings, json) {
14573
         *       for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) {
14574
         *         json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two;
14575
         *       }
14576
         *       // Note no return - manipulate the data directly in the JSON object.
14577
         *     } );
14578
         */
14579
 
14580
        /**
14581
         * Destroy event, fired when the DataTable is destroyed by calling fnDestroy
14582
         * or passing the bDestroy:true parameter in the initialisation object. This
14583
         * can be used to remove bound events, added DOM nodes, etc.
14584
         *  @name DataTable#destroy.dt
14585
         *  @event
14586
         *  @param {event} e jQuery event object
14587
         *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14588
         */
14589
 
14590
        /**
14591
         * Page length change event, fired when number of records to show on each
14592
         * page (the length) is changed.
14593
         *  @name DataTable#length.dt
14594
         *  @event
14595
         *  @param {event} e jQuery event object
14596
         *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14597
         *  @param {integer} len New length
14598
         */
14599
 
14600
        /**
14601
         * Column sizing has changed.
14602
         *  @name DataTable#column-sizing.dt
14603
         *  @event
14604
         *  @param {event} e jQuery event object
14605
         *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14606
         */
14607
 
14608
        /**
14609
         * Column visibility has changed.
14610
         *  @name DataTable#column-visibility.dt
14611
         *  @event
14612
         *  @param {event} e jQuery event object
14613
         *  @param {object} o DataTables settings object {@link DataTable.models.oSettings}
14614
         *  @param {int} column Column index
14615
         *  @param {bool} vis `false` if column now hidden, or `true` if visible
14616
         */
14617
 
14618
        return $.fn.dataTable;
14619
}));
14620
 
14621
}(window, document));
14622