1/*! DataTables 1.10.7 2 * ©2008-2014 SpryMedia Ltd - datatables.net/license 3 */ 4 5/** 6 * @summary DataTables 7 * @description Paginate, search and order HTML tables 8 * @version 1.10.7 9 * @file jquery.dataTables.js 10 * @author SpryMedia Ltd (www.sprymedia.co.uk) 11 * @contact www.sprymedia.co.uk/contact 12 * @copyright Copyright 2008-2014 SpryMedia Ltd. 13 * 14 * This source file is free software, available under the following license: 15 * MIT license - http://datatables.net/license 16 * 17 * This source file is distributed in the hope that it will be useful, but 18 * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY 19 * or FITNESS FOR A PARTICULAR PURPOSE. See the license files for details. 20 * 21 * For details please refer to: http://www.datatables.net 22 */ 23 24/*jslint evil: true, undef: true, browser: true */ 25/*globals $,require,jQuery,define,_selector_run,_selector_opts,_selector_first,_selector_row_indexes,_ext,_Api,_api_register,_api_registerPlural,_re_new_lines,_re_html,_re_formatted_numeric,_re_escape_regex,_empty,_intVal,_numToDecimal,_isNumber,_isHtml,_htmlNumeric,_pluck,_pluck_order,_range,_stripHtml,_unique,_fnBuildAjax,_fnAjaxUpdate,_fnAjaxParameters,_fnAjaxUpdateDraw,_fnAjaxDataSrc,_fnAddColumn,_fnColumnOptions,_fnAdjustColumnSizing,_fnVisibleToColumnIndex,_fnColumnIndexToVisible,_fnVisbleColumns,_fnGetColumns,_fnColumnTypes,_fnApplyColumnDefs,_fnHungarianMap,_fnCamelToHungarian,_fnLanguageCompat,_fnBrowserDetect,_fnAddData,_fnAddTr,_fnNodeToDataIndex,_fnNodeToColumnIndex,_fnGetCellData,_fnSetCellData,_fnSplitObjNotation,_fnGetObjectDataFn,_fnSetObjectDataFn,_fnGetDataMaster,_fnClearTable,_fnDeleteIndex,_fnInvalidate,_fnGetRowElements,_fnCreateTr,_fnBuildHead,_fnDrawHead,_fnDraw,_fnReDraw,_fnAddOptionsHtml,_fnDetectHeader,_fnGetUniqueThs,_fnFeatureHtmlFilter,_fnFilterComplete,_fnFilterCustom,_fnFilterColumn,_fnFilter,_fnFilterCreateSearch,_fnEscapeRegex,_fnFilterData,_fnFeatureHtmlInfo,_fnUpdateInfo,_fnInfoMacros,_fnInitialise,_fnInitComplete,_fnLengthChange,_fnFeatureHtmlLength,_fnFeatureHtmlPaginate,_fnPageChange,_fnFeatureHtmlProcessing,_fnProcessingDisplay,_fnFeatureHtmlTable,_fnScrollDraw,_fnApplyToChildren,_fnCalculateColumnWidths,_fnThrottle,_fnConvertToWidth,_fnScrollingWidthAdjust,_fnGetWidestNode,_fnGetMaxLenString,_fnStringToCss,_fnScrollBarWidth,_fnSortFlatten,_fnSort,_fnSortAria,_fnSortListener,_fnSortAttachListener,_fnSortingClasses,_fnSortData,_fnSaveState,_fnLoadState,_fnSettingsFromNode,_fnLog,_fnMap,_fnBindAction,_fnCallbackReg,_fnCallbackFire,_fnLengthOverflow,_fnRenderer,_fnDataSource,_fnRowAttributes*/ 26 27(/** @lends <global> */function( window, document, undefined ) { 28 29(function( factory ) { 30 "use strict"; 31 32 if ( typeof define === 'function' && define.amd ) { 33 // Define as an AMD module if possible 34 define( 'datatables', ['jquery'], factory ); 35 } 36 else if ( typeof exports === 'object' ) { 37 // Node/CommonJS 38 module.exports = factory( require( 'jquery' ) ); 39 } 40 else if ( jQuery && !jQuery.fn.dataTable ) { 41 // Define using browser globals otherwise 42 // Prevent multiple instantiations if the script is loaded twice 43 factory( jQuery ); 44 } 45} 46(/** @lends <global> */function( $ ) { 47 "use strict"; 48 49 /** 50 * DataTables is a plug-in for the jQuery Javascript library. It is a highly 51 * flexible tool, based upon the foundations of progressive enhancement, 52 * which will add advanced interaction controls to any HTML table. For a 53 * full list of features please refer to 54 * [DataTables.net](href="http://datatables.net). 55 * 56 * Note that the `DataTable` object is not a global variable but is aliased 57 * to `jQuery.fn.DataTable` and `jQuery.fn.dataTable` through which it may 58 * be accessed. 59 * 60 * @class 61 * @param {object} [init={}] Configuration object for DataTables. Options 62 * are defined by {@link DataTable.defaults} 63 * @requires jQuery 1.7+ 64 * 65 * @example 66 * // Basic initialisation 67 * $(document).ready( function { 68 * $('#example').dataTable(); 69 * } ); 70 * 71 * @example 72 * // Initialisation with configuration options - in this case, disable 73 * // pagination and sorting. 74 * $(document).ready( function { 75 * $('#example').dataTable( { 76 * "paginate": false, 77 * "sort": false 78 * } ); 79 * } ); 80 */ 81 var DataTable; 82 83 84 /*
vendor: 38,531 bytes, lines 85-1471
85 * It is useful to have variables which are scoped locally so only the 86 * DataTables functions can access them and they don't leak into global space. 87 * At the same time these functions are often useful over multiple files in the 88 * core and API, so we list, or at least document, all variables which are used 89 * by DataTables as private variables here. This also ensures that there is no 90 * clashing of variable names and that they can easily referenced for reuse. 91 */ 92 93 94 // Defined else where 95 // _selector_run 96 // _selector_opts 97 // _selector_first 98 // _selector_row_indexes 99 100 var _ext; // DataTable.ext 101 var _Api; // DataTable.Api 102 var _api_register; // DataTable.Api.register 103 var _api_registerPlural; // DataTable.Api.registerPlural 104 105 var _re_dic = {}; 106 var _re_new_lines = /[\r\n]/g; 107 var _re_html = /<.*?>/g; 108 var _re_date_start = /^[\w\+\-]/; 109 var _re_date_end = /[\w\+\-]$/; 110 111 // Escape regular expression special characters 112 var _re_escape_regex = new RegExp( '(\\' + [ '/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\', '$', '^', '-' ].join('|\\') + ')', 'g' ); 113 114 // http://en.wikipedia.org/wiki/Foreign_exchange_market 115 // - \u20BD - Russian ruble. 116 // - \u20a9 - South Korean Won 117 // - \u20BA - Turkish Lira 118 // - \u20B9 - Indian Rupee 119 // - R - Brazil (R$) and South Africa 120 // - fr - Swiss Franc 121 // - kr - Swedish krona, Norwegian krone and Danish krone 122 // - \u2009 is thin space and \u202F is narrow no-break space, both used in many 123 // standards as thousands separators. 124 var _re_formatted_numeric = /[',$£â¬Â¥%\u2009\u202F\u20BD\u20a9\u20BArfk]/gi; 125 126 127 var _empty = function ( d ) { 128 return !d || d === true || d === '-' ? true : false; 129 }; 130 131 132 var _intVal = function ( s ) { 133 var integer = parseInt( s, 10 ); 134 return !isNaN(integer) && isFinite(s) ? integer : null; 135 }; 136 137 // Convert from a formatted number with characters other than `.` as the 138 // decimal place, to a Javascript number 139 var _numToDecimal = function ( num, decimalPoint ) { 140 // Cache created regular expressions for speed as this function is called often 141 if ( ! _re_dic[ decimalPoint ] ) { 142 _re_dic[ decimalPoint ] = new RegExp( _fnEscapeRegex( decimalPoint ), 'g' ); 143 } 144 return typeof num === 'string' && decimalPoint !== '.' ? 145 num.replace( /\./g, '' ).replace( _re_dic[ decimalPoint ], '.' ) : 146 num; 147 }; 148 149 150 var _isNumber = function ( d, decimalPoint, formatted ) { 151 var strType = typeof d === 'string'; 152 153 // If empty return immediately so there must be a number if it is a 154 // formatted string (this stops the string "k", or "kr", etc being detected 155 // as a formatted number for currency 156 if ( _empty( d ) ) { 157 return true; 158 } 159 160 if ( decimalPoint && strType ) { 161 d = _numToDecimal( d, decimalPoint ); 162 } 163 164 if ( formatted && strType ) { 165 d = d.replace( _re_formatted_numeric, '' ); 166 } 167 168 return !isNaN( parseFloat(d) ) && isFinite( d ); 169 }; 170 171 172 // A string without HTML in it can be considered to be HTML still 173 var _isHtml = function ( d ) { 174 return _empty( d ) || typeof d === 'string'; 175 }; 176 177 178 var _htmlNumeric = function ( d, decimalPoint, formatted ) { 179 if ( _empty( d ) ) { 180 return true; 181 } 182 183 var html = _isHtml( d ); 184 return ! html ? 185 null : 186 _isNumber( _stripHtml( d ), decimalPoint, formatted ) ? 187 true : 188 null; 189 }; 190 191 192 var _pluck = function ( a, prop, prop2 ) { 193 var out = []; 194 var i=0, ien=a.length; 195 196 // Could have the test in the loop for slightly smaller code, but speed 197 // is essential here 198 if ( prop2 !== undefined ) { 199 for ( ; i<ien ; i++ ) { 200 if ( a[i] && a[i][ prop ] ) { 201 out.push( a[i][ prop ][ prop2 ] ); 202 } 203 } 204 } 205 else { 206 for ( ; i<ien ; i++ ) { 207 if ( a[i] ) { 208 out.push( a[i][ prop ] ); 209 } 210 } 211 } 212 213 return out; 214 }; 215 216 217 // Basically the same as _pluck, but rather than looping over `a` we use `order` 218 // as the indexes to pick from `a` 219 var _pluck_order = function ( a, order, prop, prop2 ) 220 { 221 var out = []; 222 var i=0, ien=order.length; 223 224 // Could have the test in the loop for slightly smaller code, but speed 225 // is essential here 226 if ( prop2 !== undefined ) { 227 for ( ; i<ien ; i++ ) { 228 if ( a[ order[i] ][ prop ] ) { 229 out.push( a[ order[i] ][ prop ][ prop2 ] ); 230 } 231 } 232 } 233 else { 234 for ( ; i<ien ; i++ ) { 235 out.push( a[ order[i] ][ prop ] ); 236 } 237 } 238 239 return out; 240 }; 241 242 243 var _range = function ( len, start ) 244 { 245 var out = []; 246 var end; 247 248 if ( start === undefined ) { 249 start = 0; 250 end = len; 251 } 252 else { 253 end = start; 254 start = len; 255 } 256 257 for ( var i=start ; i<end ; i++ ) { 258 out.push( i ); 259 } 260 261 return out; 262 }; 263 264 265 var _removeEmpty = function ( a ) 266 { 267 var out = []; 268 269 for ( var i=0, ien=a.length ; i<ien ; i++ ) { 270 if ( a[i] ) { // careful - will remove all falsy values! 271 out.push( a[i] ); 272 } 273 } 274 275 return out; 276 }; 277 278 279 var _stripHtml = function ( d ) { 280 return d.replace( _re_html, '' ); 281 }; 282 283 284 /** 285 * Find the unique elements in a source array. 286 * 287 * @param {array} src Source array 288 * @return {array} Array of unique items 289 * @ignore 290 */ 291 var _unique = function ( src ) 292 { 293 // A faster unique method is to use object keys to identify used values, 294 // but this doesn't work with arrays or objects, which we must also 295 // consider. See jsperf.com/compare-array-unique-versions/4 for more 296 // information. 297 var 298 out = [], 299 val, 300 i, ien=src.length, 301 j, k=0; 302 303 again: for ( i=0 ; i<ien ; i++ ) { 304 val = src[i]; 305 306 for ( j=0 ; j<k ; j++ ) { 307 if ( out[j] === val ) { 308 continue again; 309 } 310 } 311 312 out.push( val ); 313 k++; 314 } 315 316 return out; 317 }; 318 319 320 321 /** 322 * Create a mapping object that allows camel case parameters to be looked up 323 * for their Hungarian counterparts. The mapping is stored in a private 324 * parameter called `_hungarianMap` which can be accessed on the source object. 325 * @param {object} o 326 * @memberof DataTable#oApi 327 */ 328 function _fnHungarianMap ( o ) 329 { 330 var 331 hungarian = 'a aa ai ao as b fn i m o s ', 332 match, 333 newKey, 334 map = {}; 335 336 $.each( o, function (key, val) { 337 match = key.match(/^([^A-Z]+?)([A-Z])/); 338 339 if ( match && hungarian.indexOf(match[1]+' ') !== -1 ) 340 { 341 newKey = key.replace( match[0], match[2].toLowerCase() ); 342 map[ newKey ] = key; 343 344 if ( match[1] === 'o' ) 345 { 346 _fnHungarianMap( o[key] ); 347 } 348 } 349 } ); 350 351 o._hungarianMap = map; 352 } 353 354 355 /** 356 * Convert from camel case parameters to Hungarian, based on a Hungarian map 357 * created by _fnHungarianMap. 358 * @param {object} src The model object which holds all parameters that can be 359 * mapped. 360 * @param {object} user The object to convert from camel case to Hungarian. 361 * @param {boolean} force When set to `true`, properties which already have a 362 * Hungarian value in the `user` object will be overwritten. Otherwise they 363 * won't be. 364 * @memberof DataTable#oApi 365 */ 366 function _fnCamelToHungarian ( src, user, force ) 367 { 368 if ( ! src._hungarianMap ) { 369 _fnHungarianMap( src ); 370 } 371 372 var hungarianKey; 373 374 $.each( user, function (key, val) { 375 hungarianKey = src._hungarianMap[ key ]; 376 377 if ( hungarianKey !== undefined && (force || user[hungarianKey] === undefined) ) 378 { 379 // For objects, we need to buzz down into the object to copy parameters 380 if ( hungarianKey.charAt(0) === 'o' ) 381 { 382 // Copy the camelCase options over to the hungarian 383 if ( ! user[ hungarianKey ] ) { 384 user[ hungarianKey ] = {}; 385 } 386 $.extend( true, user[hungarianKey], user[key] ); 387 388 _fnCamelToHungarian( src[hungarianKey], user[hungarianKey], force ); 389 } 390 else { 391 user[hungarianKey] = user[ key ]; 392 } 393 } 394 } ); 395 } 396 397 398 /** 399 * Language compatibility - when certain options are given, and others aren't, we 400 * need to duplicate the values over, in order to provide backwards compatibility 401 * with older language files. 402 * @param {object} oSettings dataTables settings object 403 * @memberof DataTable#oApi 404 */ 405 function _fnLanguageCompat( lang ) 406 { 407 var defaults = DataTable.defaults.oLanguage; 408 var zeroRecords = lang.sZeroRecords; 409 410 /* Backwards compatibility - if there is no sEmptyTable given, then use the same as 411 * sZeroRecords - assuming that is given. 412 */ 413 if ( ! lang.sEmptyTable && zeroRecords && 414 defaults.sEmptyTable === "No data available in table" ) 415 { 416 _fnMap( lang, lang, 'sZeroRecords', 'sEmptyTable' ); 417 } 418 419 /* Likewise with loading records */ 420 if ( ! lang.sLoadingRecords && zeroRecords && 421 defaults.sLoadingRecords === "Loading..." ) 422 { 423 _fnMap( lang, lang, 'sZeroRecords', 'sLoadingRecords' ); 424 } 425 426 // Old parameter name of the thousands separator mapped onto the new 427 if ( lang.sInfoThousands ) { 428 lang.sThousands = lang.sInfoThousands; 429 } 430 431 var decimal = lang.sDecimal; 432 if ( decimal ) { 433 _addNumericSort( decimal ); 434 } 435 } 436 437 438 /** 439 * Map one parameter onto another 440 * @param {object} o Object to map 441 * @param {*} knew The new parameter name 442 * @param {*} old The old parameter name 443 */ 444 var _fnCompatMap = function ( o, knew, old ) { 445 if ( o[ knew ] !== undefined ) { 446 o[ old ] = o[ knew ]; 447 } 448 }; 449 450 451 /** 452 * Provide backwards compatibility for the main DT options. Note that the new 453 * options are mapped onto the old parameters, so this is an external interface 454 * change only. 455 * @param {object} init Object to map 456 */ 457 function _fnCompatOpts ( init ) 458 { 459 _fnCompatMap( init, 'ordering', 'bSort' ); 460 _fnCompatMap( init, 'orderMulti', 'bSortMulti' ); 461 _fnCompatMap( init, 'orderClasses', 'bSortClasses' ); 462 _fnCompatMap( init, 'orderCellsTop', 'bSortCellsTop' ); 463 _fnCompatMap( init, 'order', 'aaSorting' ); 464 _fnCompatMap( init, 'orderFixed', 'aaSortingFixed' ); 465 _fnCompatMap( init, 'paging', 'bPaginate' ); 466 _fnCompatMap( init, 'pagingType', 'sPaginationType' ); 467 _fnCompatMap( init, 'pageLength', 'iDisplayLength' ); 468 _fnCompatMap( init, 'searching', 'bFilter' ); 469 470 // Column search objects are in an array, so it needs to be converted 471 // element by element 472 var searchCols = init.aoSearchCols; 473 474 if ( searchCols ) { 475 for ( var i=0, ien=searchCols.length ; i<ien ; i++ ) { 476 if ( searchCols[i] ) { 477 _fnCamelToHungarian( DataTable.models.oSearch, searchCols[i] ); 478 } 479 } 480 } 481 } 482 483 484 /** 485 * Provide backwards compatibility for column options. Note that the new options 486 * are mapped onto the old parameters, so this is an external interface change 487 * only. 488 * @param {object} init Object to map 489 */ 490 function _fnCompatCols ( init ) 491 { 492 _fnCompatMap( init, 'orderable', 'bSortable' ); 493 _fnCompatMap( init, 'orderData', 'aDataSort' ); 494 _fnCompatMap( init, 'orderSequence', 'asSorting' ); 495 _fnCompatMap( init, 'orderDataType', 'sortDataType' ); 496 497 // orderData can be given as an integer 498 var dataSort = init.aDataSort; 499 if ( dataSort && ! $.isArray( dataSort ) ) { 500 init.aDataSort = [ dataSort ]; 501 } 502 } 503 504 505 /** 506 * Browser feature detection for capabilities, quirks 507 * @param {object} settings dataTables settings object 508 * @memberof DataTable#oApi 509 */ 510 function _fnBrowserDetect( settings ) 511 { 512 var browser = settings.oBrowser; 513 514 // Scrolling feature / quirks detection 515 var n = $('<div/>') 516 .css( { 517 position: 'absolute', 518 top: 0, 519 left: 0, 520 height: 1, 521 width: 1, 522 overflow: 'hidden' 523 } ) 524 .append( 525 $('<div/>') 526 .css( { 527 position: 'absolute', 528 top: 1, 529 left: 1, 530 width: 100, 531 overflow: 'scroll' 532 } ) 533 .append( 534 $('<div class="test"/>') 535 .css( { 536 width: '100%', 537 height: 10 538 } ) 539 ) 540 ) 541 .appendTo( 'body' ); 542 543 var test = n.find('.test'); 544 545 // IE6/7 will oversize a width 100% element inside a scrolling element, to 546 // include the width of the scrollbar, while other browsers ensure the inner 547 // element is contained without forcing scrolling 548 browser.bScrollOversize = test[0].offsetWidth === 100; 549 550 // In rtl text layout, some browsers (most, but not all) will place the 551 // scrollbar on the left, rather than the right. 552 browser.bScrollbarLeft = Math.round( test.offset().left ) !== 1; 553 554 n.remove(); 555 } 556 557 558 /** 559 * Array.prototype reduce[Right] method, used for browsers which don't support 560 * JS 1.6. Done this way to reduce code size, since we iterate either way 561 * @param {object} settings dataTables settings object 562 * @memberof DataTable#oApi 563 */ 564 function _fnReduce ( that, fn, init, start, end, inc ) 565 { 566 var 567 i = start, 568 value, 569 isSet = false; 570 571 if ( init !== undefined ) { 572 value = init; 573 isSet = true; 574 } 575 576 while ( i !== end ) { 577 if ( ! that.hasOwnProperty(i) ) { 578 continue; 579 } 580 581 value = isSet ? 582 fn( value, that[i], i, that ) : 583 that[i]; 584 585 isSet = true; 586 i += inc; 587 } 588 589 return value; 590 } 591 592 /** 593 * Add a column to the list used for the table with default values 594 * @param {object} oSettings dataTables settings object 595 * @param {node} nTh The th element for this column 596 * @memberof DataTable#oApi 597 */ 598 function _fnAddColumn( oSettings, nTh ) 599 { 600 // Add column to aoColumns array 601 var oDefaults = DataTable.defaults.column; 602 var iCol = oSettings.aoColumns.length; 603 var oCol = $.extend( {}, DataTable.models.oColumn, oDefaults, { 604 "nTh": nTh ? nTh : document.createElement('th'), 605 "sTitle": oDefaults.sTitle ? oDefaults.sTitle : nTh ? nTh.innerHTML : '', 606 "aDataSort": oDefaults.aDataSort ? oDefaults.aDataSort : [iCol], 607 "mData": oDefaults.mData ? oDefaults.mData : iCol, 608 idx: iCol 609 } ); 610 oSettings.aoColumns.push( oCol ); 611 612 // Add search object for column specific search. Note that the `searchCols[ iCol ]` 613 // passed into extend can be undefined. This allows the user to give a default 614 // with only some of the parameters defined, and also not give a default 615 var searchCols = oSettings.aoPreSearchCols; 616 searchCols[ iCol ] = $.extend( {}, DataTable.models.oSearch, searchCols[ iCol ] ); 617 618 // Use the default column options function to initialise classes etc 619 _fnColumnOptions( oSettings, iCol, $(nTh).data() ); 620 } 621 622 623 /** 624 * Apply options for a column 625 * @param {object} oSettings dataTables settings object 626 * @param {int} iCol column index to consider 627 * @param {object} oOptions object with sType, bVisible and bSearchable etc 628 * @memberof DataTable#oApi 629 */ 630 function _fnColumnOptions( oSettings, iCol, oOptions ) 631 { 632 var oCol = oSettings.aoColumns[ iCol ]; 633 var oClasses = oSettings.oClasses; 634 var th = $(oCol.nTh); 635 636 // Try to get width information from the DOM. We can't get it from CSS 637 // as we'd need to parse the CSS stylesheet. `width` option can override 638 if ( ! oCol.sWidthOrig ) { 639 // Width attribute 640 oCol.sWidthOrig = th.attr('width') || null; 641 642 // Style attribute 643 var t = (th.attr('style') || '').match(/width:\s*(\d+[pxem%]+)/); 644 if ( t ) { 645 oCol.sWidthOrig = t[1]; 646 } 647 } 648 649 /* User specified column options */ 650 if ( oOptions !== undefined && oOptions !== null ) 651 { 652 // Backwards compatibility 653 _fnCompatCols( oOptions ); 654 655 // Map camel case parameters to their Hungarian counterparts 656 _fnCamelToHungarian( DataTable.defaults.column, oOptions ); 657 658 /* Backwards compatibility for mDataProp */ 659 if ( oOptions.mDataProp !== undefined && !oOptions.mData ) 660 { 661 oOptions.mData = oOptions.mDataProp; 662 } 663 664 if ( oOptions.sType ) 665 { 666 oCol._sManualType = oOptions.sType; 667 } 668 669 // `class` is a reserved word in Javascript, so we need to provide 670 // the ability to use a valid name for the camel case input 671 if ( oOptions.className && ! oOptions.sClass ) 672 { 673 oOptions.sClass = oOptions.className; 674 } 675 676 $.extend( oCol, oOptions ); 677 _fnMap( oCol, oOptions, "sWidth", "sWidthOrig" ); 678 679 /* iDataSort to be applied (backwards compatibility), but aDataSort will take 680 * priority if defined 681 */ 682 if ( oOptions.iDataSort !== undefined ) 683 { 684 oCol.aDataSort = [ oOptions.iDataSort ]; 685 } 686 _fnMap( oCol, oOptions, "aDataSort" ); 687 } 688 689 /* Cache the data get and set functions for speed */ 690 var mDataSrc = oCol.mData; 691 var mData = _fnGetObjectDataFn( mDataSrc ); 692 var mRender = oCol.mRender ? _fnGetObjectDataFn( oCol.mRender ) : null; 693 694 var attrTest = function( src ) { 695 return typeof src === 'string' && src.indexOf('@') !== -1; 696 }; 697 oCol._bAttrSrc = $.isPlainObject( mDataSrc ) && ( 698 attrTest(mDataSrc.sort) || attrTest(mDataSrc.type) || attrTest(mDataSrc.filter) 699 ); 700 701 oCol.fnGetData = function (rowData, type, meta) { 702 var innerData = mData( rowData, type, undefined, meta ); 703 704 return mRender && type ? 705 mRender( innerData, type, rowData, meta ) : 706 innerData; 707 }; 708 oCol.fnSetData = function ( rowData, val, meta ) { 709 return _fnSetObjectDataFn( mDataSrc )( rowData, val, meta ); 710 }; 711 712 // Indicate if DataTables should read DOM data as an object or array 713 // Used in _fnGetRowElements 714 if ( typeof mDataSrc !== 'number' ) { 715 oSettings._rowReadObject = true; 716 } 717 718 /* Feature sorting overrides column specific when off */ 719 if ( !oSettings.oFeatures.bSort ) 720 { 721 oCol.bSortable = false; 722 th.addClass( oClasses.sSortableNone ); // Have to add class here as order event isn't called 723 } 724 725 /* Check that the class assignment is correct for sorting */ 726 var bAsc = $.inArray('asc', oCol.asSorting) !== -1; 727 var bDesc = $.inArray('desc', oCol.asSorting) !== -1; 728 if ( !oCol.bSortable || (!bAsc && !bDesc) ) 729 { 730 oCol.sSortingClass = oClasses.sSortableNone; 731 oCol.sSortingClassJUI = ""; 732 } 733 else if ( bAsc && !bDesc ) 734 { 735 oCol.sSortingClass = oClasses.sSortableAsc; 736 oCol.sSortingClassJUI = oClasses.sSortJUIAscAllowed; 737 } 738 else if ( !bAsc && bDesc ) 739 { 740 oCol.sSortingClass = oClasses.sSortableDesc; 741 oCol.sSortingClassJUI = oClasses.sSortJUIDescAllowed; 742 } 743 else 744 { 745 oCol.sSortingClass = oClasses.sSortable; 746 oCol.sSortingClassJUI = oClasses.sSortJUI; 747 } 748 } 749 750 751 /** 752 * Adjust the table column widths for new data. Note: you would probably want to 753 * do a redraw after calling this function! 754 * @param {object} settings dataTables settings object 755 * @memberof DataTable#oApi 756 */ 757 function _fnAdjustColumnSizing ( settings ) 758 { 759 /* Not interested in doing column width calculation if auto-width is disabled */ 760 if ( settings.oFeatures.bAutoWidth !== false ) 761 { 762 var columns = settings.aoColumns; 763 764 _fnCalculateColumnWidths( settings ); 765 for ( var i=0 , iLen=columns.length ; i<iLen ; i++ ) 766 { 767 columns[i].nTh.style.width = columns[i].sWidth; 768 } 769 } 770 771 var scroll = settings.oScroll; 772 if ( scroll.sY !== '' || scroll.sX !== '') 773 { 774 _fnScrollDraw( settings ); 775 } 776 777 _fnCallbackFire( settings, null, 'column-sizing', [settings] ); 778 } 779 780 781 /** 782 * Covert the index of a visible column to the index in the data array (take account 783 * of hidden columns) 784 * @param {object} oSettings dataTables settings object 785 * @param {int} iMatch Visible column index to lookup 786 * @returns {int} i the data index 787 * @memberof DataTable#oApi 788 */ 789 function _fnVisibleToColumnIndex( oSettings, iMatch ) 790 { 791 var aiVis = _fnGetColumns( oSettings, 'bVisible' ); 792 793 return typeof aiVis[iMatch] === 'number' ? 794 aiVis[iMatch] : 795 null; 796 } 797 798 799 /** 800 * Covert the index of an index in the data array and convert it to the visible 801 * column index (take account of hidden columns) 802 * @param {int} iMatch Column index to lookup 803 * @param {object} oSettings dataTables settings object 804 * @returns {int} i the data index 805 * @memberof DataTable#oApi 806 */ 807 function _fnColumnIndexToVisible( oSettings, iMatch ) 808 { 809 var aiVis = _fnGetColumns( oSettings, 'bVisible' ); 810 var iPos = $.inArray( iMatch, aiVis ); 811 812 return iPos !== -1 ? iPos : null; 813 } 814 815 816 /** 817 * Get the number of visible columns 818 * @param {object} oSettings dataTables settings object 819 * @returns {int} i the number of visible columns 820 * @memberof DataTable#oApi 821 */ 822 function _fnVisbleColumns( oSettings ) 823 { 824 return _fnGetColumns( oSettings, 'bVisible' ).length; 825 } 826 827 828 /** 829 * Get an array of column indexes that match a given property 830 * @param {object} oSettings dataTables settings object 831 * @param {string} sParam Parameter in aoColumns to look for - typically 832 * bVisible or bSearchable 833 * @returns {array} Array of indexes with matched properties 834 * @memberof DataTable#oApi 835 */ 836 function _fnGetColumns( oSettings, sParam ) 837 { 838 var a = []; 839 840 $.map( oSettings.aoColumns, function(val, i) { 841 if ( val[sParam] ) { 842 a.push( i ); 843 } 844 } ); 845 846 return a; 847 } 848 849 850 /** 851 * Calculate the 'type' of a column 852 * @param {object} settings dataTables settings object 853 * @memberof DataTable#oApi 854 */ 855 function _fnColumnTypes ( settings ) 856 { 857 var columns = settings.aoColumns; 858 var data = settings.aoData; 859 var types = DataTable.ext.type.detect; 860 var i, ien, j, jen, k, ken; 861 var col, cell, detectedType, cache; 862 863 // For each column, spin over the 864 for ( i=0, ien=columns.length ; i<ien ; i++ ) { 865 col = columns[i]; 866 cache = []; 867 868 if ( ! col.sType && col._sManualType ) { 869 col.sType = col._sManualType; 870 } 871 else if ( ! col.sType ) { 872 for ( j=0, jen=types.length ; j<jen ; j++ ) { 873 for ( k=0, ken=data.length ; k<ken ; k++ ) { 874 // Use a cache array so we only need to get the type data 875 // from the formatter once (when using multiple detectors) 876 if ( cache[k] === undefined ) { 877 cache[k] = _fnGetCellData( settings, k, i, 'type' ); 878 } 879 880 detectedType = types[j]( cache[k], settings ); 881 882 // If null, then this type can't apply to this column, so 883 // rather than testing all cells, break out. There is an 884 // exception for the last type which is `html`. We need to 885 // scan all rows since it is possible to mix string and HTML 886 // types 887 if ( ! detectedType && j !== types.length-1 ) { 888 break; 889 } 890 891 // Only a single match is needed for html type since it is 892 // bottom of the pile and very similar to string 893 if ( detectedType === 'html' ) { 894 break; 895 } 896 } 897 898 // Type is valid for all data points in the column - use this 899 // type 900 if ( detectedType ) { 901 col.sType = detectedType; 902 break; 903 } 904 } 905 906 // Fall back - if no type was detected, always use string 907 if ( ! col.sType ) { 908 col.sType = 'string'; 909 } 910 } 911 } 912 } 913 914 915 /** 916 * Take the column definitions and static columns arrays and calculate how 917 * they relate to column indexes. The callback function will then apply the 918 * definition found for a column to a suitable configuration object. 919 * @param {object} oSettings dataTables settings object 920 * @param {array} aoColDefs The aoColumnDefs array that is to be applied 921 * @param {array} aoCols The aoColumns array that defines columns individually 922 * @param {function} fn Callback function - takes two parameters, the calculated 923 * column index and the definition for that column. 924 * @memberof DataTable#oApi 925 */ 926 function _fnApplyColumnDefs( oSettings, aoColDefs, aoCols, fn ) 927 { 928 var i, iLen, j, jLen, k, kLen, def; 929 var columns = oSettings.aoColumns; 930 931 // Column definitions with aTargets 932 if ( aoColDefs ) 933 { 934 /* Loop over the definitions array - loop in reverse so first instance has priority */ 935 for ( i=aoColDefs.length-1 ; i>=0 ; i-- ) 936 { 937 def = aoColDefs[i]; 938 939 /* Each definition can target multiple columns, as it is an array */ 940 var aTargets = def.targets !== undefined ? 941 def.targets : 942 def.aTargets; 943 944 if ( ! $.isArray( aTargets ) ) 945 { 946 aTargets = [ aTargets ]; 947 } 948 949 for ( j=0, jLen=aTargets.length ; j<jLen ; j++ ) 950 { 951 if ( typeof aTargets[j] === 'number' && aTargets[j] >= 0 ) 952 { 953 /* Add columns that we don't yet know about */ 954 while( columns.length <= aTargets[j] ) 955 { 956 _fnAddColumn( oSettings ); 957 } 958 959 /* Integer, basic index */ 960 fn( aTargets[j], def ); 961 } 962 else if ( typeof aTargets[j] === 'number' && aTargets[j] < 0 ) 963 { 964 /* Negative integer, right to left column counting */ 965 fn( columns.length+aTargets[j], def ); 966 } 967 else if ( typeof aTargets[j] === 'string' ) 968 { 969 /* Class name matching on TH element */ 970 for ( k=0, kLen=columns.length ; k<kLen ; k++ ) 971 { 972 if ( aTargets[j] == "_all" || 973 $(columns[k].nTh).hasClass( aTargets[j] ) ) 974 { 975 fn( k, def ); 976 } 977 } 978 } 979 } 980 } 981 } 982 983 // Statically defined columns array 984 if ( aoCols ) 985 { 986 for ( i=0, iLen=aoCols.length ; i<iLen ; i++ ) 987 { 988 fn( i, aoCols[i] ); 989 } 990 } 991 } 992 993 /** 994 * Add a data array to the table, creating DOM node etc. This is the parallel to 995 * _fnGatherData, but for adding rows from a Javascript source, rather than a 996 * DOM source. 997 * @param {object} oSettings dataTables settings object 998 * @param {array} aData data array to be added 999 * @param {node} [nTr] TR element to add to the table - optional. If not given, 1000 * DataTables will create a row automatically 1001 * @param {array} [anTds] Array of TD|TH elements for the row - must be given 1002 * if nTr is. 1003 * @returns {int} >=0 if successful (index of new aoData entry), -1 if failed 1004 * @memberof DataTable#oApi 1005 */ 1006 function _fnAddData ( oSettings, aDataIn, nTr, anTds ) 1007 { 1008 /* Create the object for storing information about this new row */ 1009 var iRow = oSettings.aoData.length; 1010 var oData = $.extend( true, {}, DataTable.models.oRow, { 1011 src: nTr ? 'dom' : 'data' 1012 } ); 1013 1014 oData._aData = aDataIn; 1015 oSettings.aoData.push( oData ); 1016 1017 /* Create the cells */ 1018 var nTd, sThisType; 1019 var columns = oSettings.aoColumns; 1020 for ( var i=0, iLen=columns.length ; i<iLen ; i++ ) 1021 { 1022 // When working with a row, the data source object must be populated. In 1023 // all other cases, the data source object is already populated, so we 1024 // don't overwrite it, which might break bindings etc 1025 if ( nTr ) { 1026 _fnSetCellData( oSettings, iRow, i, _fnGetCellData( oSettings, iRow, i ) ); 1027 } 1028 columns[i].sType = null; 1029 } 1030 1031 /* Add to the display array */ 1032 oSettings.aiDisplayMaster.push( iRow ); 1033 1034 /* Create the DOM information, or register it if already present */ 1035 if ( nTr || ! oSettings.oFeatures.bDeferRender ) 1036 { 1037 _fnCreateTr( oSettings, iRow, nTr, anTds ); 1038 } 1039 1040 return iRow; 1041 } 1042 1043 1044 /** 1045 * Add one or more TR elements to the table. Generally we'd expect to 1046 * use this for reading data from a DOM sourced table, but it could be 1047 * used for an TR element. Note that if a TR is given, it is used (i.e. 1048 * it is not cloned). 1049 * @param {object} settings dataTables settings object 1050 * @param {array|node|jQuery} trs The TR element(s) to add to the table 1051 * @returns {array} Array of indexes for the added rows 1052 * @memberof DataTable#oApi 1053 */ 1054 function _fnAddTr( settings, trs ) 1055 { 1056 var row; 1057 1058 // Allow an individual node to be passed in 1059 if ( ! (trs instanceof $) ) { 1060 trs = $(trs); 1061 } 1062 1063 return trs.map( function (i, el) { 1064 row = _fnGetRowElements( settings, el ); 1065 return _fnAddData( settings, row.data, el, row.cells ); 1066 } ); 1067 } 1068 1069 1070 /** 1071 * Take a TR element and convert it to an index in aoData 1072 * @param {object} oSettings dataTables settings object 1073 * @param {node} n the TR element to find 1074 * @returns {int} index if the node is found, null if not 1075 * @memberof DataTable#oApi 1076 */ 1077 function _fnNodeToDataIndex( oSettings, n ) 1078 { 1079 return (n._DT_RowIndex!==undefined) ? n._DT_RowIndex : null; 1080 } 1081 1082 1083 /** 1084 * Take a TD element and convert it into a column data index (not the visible index) 1085 * @param {object} oSettings dataTables settings object 1086 * @param {int} iRow The row number the TD/TH can be found in 1087 * @param {node} n The TD/TH element to find 1088 * @returns {int} index if the node is found, -1 if not 1089 * @memberof DataTable#oApi 1090 */ 1091 function _fnNodeToColumnIndex( oSettings, iRow, n ) 1092 { 1093 return $.inArray( n, oSettings.aoData[ iRow ].anCells ); 1094 } 1095 1096 1097 /** 1098 * Get the data for a given cell from the internal cache, taking into account data mapping 1099 * @param {object} settings dataTables settings object 1100 * @param {int} rowIdx aoData row id 1101 * @param {int} colIdx Column index 1102 * @param {string} type data get type ('display', 'type' 'filter' 'sort') 1103 * @returns {*} Cell data 1104 * @memberof DataTable#oApi 1105 */ 1106 function _fnGetCellData( settings, rowIdx, colIdx, type ) 1107 { 1108 var draw = settings.iDraw; 1109 var col = settings.aoColumns[colIdx]; 1110 var rowData = settings.aoData[rowIdx]._aData; 1111 var defaultContent = col.sDefaultContent; 1112 var cellData = col.fnGetData( rowData, type, { 1113 settings: settings, 1114 row: rowIdx, 1115 col: colIdx 1116 } ); 1117 1118 if ( cellData === undefined ) { 1119 if ( settings.iDrawError != draw && defaultContent === null ) { 1120 _fnLog( settings, 0, "Requested unknown parameter "+ 1121 (typeof col.mData=='function' ? '{function}' : "'"+col.mData+"'")+ 1122 " for row "+rowIdx, 4 ); 1123 settings.iDrawError = draw; 1124 } 1125 return defaultContent; 1126 } 1127 1128 /* When the data source is null, we can use default column data */ 1129 if ( (cellData === rowData || cellData === null) && defaultContent !== null ) { 1130 cellData = defaultContent; 1131 } 1132 else if ( typeof cellData === 'function' ) { 1133 // If the data source is a function, then we run it and use the return, 1134 // executing in the scope of the data object (for instances) 1135 return cellData.call( rowData ); 1136 } 1137 1138 if ( cellData === null && type == 'display' ) { 1139 return ''; 1140 } 1141 return cellData; 1142 } 1143 1144 1145 /** 1146 * Set the value for a specific cell, into the internal data cache 1147 * @param {object} settings dataTables settings object 1148 * @param {int} rowIdx aoData row id 1149 * @param {int} colIdx Column index 1150 * @param {*} val Value to set 1151 * @memberof DataTable#oApi 1152 */ 1153 function _fnSetCellData( settings, rowIdx, colIdx, val ) 1154 { 1155 var col = settings.aoColumns[colIdx]; 1156 var rowData = settings.aoData[rowIdx]._aData; 1157 1158 col.fnSetData( rowData, val, { 1159 settings: settings, 1160 row: rowIdx, 1161 col: colIdx 1162 } ); 1163 } 1164 1165 1166 // Private variable that is used to match action syntax in the data property object 1167 var __reArray = /\[.*?\]$/; 1168 var __reFn = /\(\)$/; 1169 1170 /** 1171 * Split string on periods, taking into account escaped periods 1172 * @param {string} str String to split 1173 * @return {array} Split string 1174 */ 1175 function _fnSplitObjNotation( str ) 1176 { 1177 return $.map( str.match(/(\\.|[^\.])+/g), function ( s ) { 1178 return s.replace(/\\./g, '.'); 1179 } ); 1180 } 1181 1182 1183 /** 1184 * Return a function that can be used to get data from a source object, taking 1185 * into account the ability to use nested objects as a source 1186 * @param {string|int|function} mSource The data source for the object 1187 * @returns {function} Data get function 1188 * @memberof DataTable#oApi 1189 */ 1190 function _fnGetObjectDataFn( mSource ) 1191 { 1192 if ( $.isPlainObject( mSource ) ) 1193 { 1194 /* Build an object of get functions, and wrap them in a single call */ 1195 var o = {}; 1196 $.each( mSource, function (key, val) { 1197 if ( val ) { 1198 o[key] = _fnGetObjectDataFn( val ); 1199 } 1200 } ); 1201 1202 return function (data, type, row, meta) { 1203 var t = o[type] || o._; 1204 return t !== undefined ? 1205 t(data, type, row, meta) : 1206 data; 1207 }; 1208 } 1209 else if ( mSource === null ) 1210 { 1211 /* Give an empty string for rendering / sorting etc */ 1212 return function (data) { // type, row and meta also passed, but not used 1213 return data; 1214 }; 1215 } 1216 else if ( typeof mSource === 'function' ) 1217 { 1218 return function (data, type, row, meta) { 1219 return mSource( data, type, row, meta ); 1220 }; 1221 } 1222 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || 1223 mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) ) 1224 { 1225 /* If there is a . in the source string then the data source is in a 1226 * nested object so we loop over the data for each level to get the next 1227 * level down. On each loop we test for undefined, and if found immediately 1228 * return. This allows entire objects to be missing and sDefaultContent to 1229 * be used if defined, rather than throwing an error 1230 */ 1231 var fetchData = function (data, type, src) { 1232 var arrayNotation, funcNotation, out, innerSrc; 1233 1234 if ( src !== "" ) 1235 { 1236 var a = _fnSplitObjNotation( src ); 1237 1238 for ( var i=0, iLen=a.length ; i<iLen ; i++ ) 1239 { 1240 // Check if we are dealing with special notation 1241 arrayNotation = a[i].match(__reArray); 1242 funcNotation = a[i].match(__reFn); 1243 1244 if ( arrayNotation ) 1245 { 1246 // Array notation 1247 a[i] = a[i].replace(__reArray, ''); 1248 1249 // Condition allows simply [] to be passed in 1250 if ( a[i] !== "" ) { 1251 data = data[ a[i] ]; 1252 } 1253 out = []; 1254 1255 // Get the remainder of the nested object to get 1256 a.splice( 0, i+1 ); 1257 innerSrc = a.join('.'); 1258 1259 // Traverse each entry in the array getting the properties requested 1260 for ( var j=0, jLen=data.length ; j<jLen ; j++ ) { 1261 out.push( fetchData( data[j], type, innerSrc ) ); 1262 } 1263 1264 // If a string is given in between the array notation indicators, that 1265 // is used to join the strings together, otherwise an array is returned 1266 var join = arrayNotation[0].substring(1, arrayNotation[0].length-1); 1267 data = (join==="") ? out : out.join(join); 1268 1269 // The inner call to fetchData has already traversed through the remainder 1270 // of the source requested, so we exit from the loop 1271 break; 1272 } 1273 else if ( funcNotation ) 1274 { 1275 // Function call 1276 a[i] = a[i].replace(__reFn, ''); 1277 data = data[ a[i] ](); 1278 continue; 1279 } 1280 1281 if ( data === null || data[ a[i] ] === undefined ) 1282 { 1283 return undefined; 1284 } 1285 data = data[ a[i] ]; 1286 } 1287 } 1288 1289 return data; 1290 }; 1291 1292 return function (data, type) { // row and meta also passed, but not used 1293 return fetchData( data, type, mSource ); 1294 }; 1295 } 1296 else 1297 { 1298 /* Array or flat object mapping */ 1299 return function (data, type) { // row and meta also passed, but not used 1300 return data[mSource]; 1301 }; 1302 } 1303 } 1304 1305 1306 /** 1307 * Return a function that can be used to set data from a source object, taking 1308 * into account the ability to use nested objects as a source 1309 * @param {string|int|function} mSource The data source for the object 1310 * @returns {function} Data set function 1311 * @memberof DataTable#oApi 1312 */ 1313 function _fnSetObjectDataFn( mSource ) 1314 { 1315 if ( $.isPlainObject( mSource ) ) 1316 { 1317 /* Unlike get, only the underscore (global) option is used for for 1318 * setting data since we don't know the type here. This is why an object 1319 * option is not documented for `mData` (which is read/write), but it is 1320 * for `mRender` which is read only. 1321 */ 1322 return _fnSetObjectDataFn( mSource._ ); 1323 } 1324 else if ( mSource === null ) 1325 { 1326 /* Nothing to do when the data source is null */ 1327 return function () {}; 1328 } 1329 else if ( typeof mSource === 'function' ) 1330 { 1331 return function (data, val, meta) { 1332 mSource( data, 'set', val, meta ); 1333 }; 1334 } 1335 else if ( typeof mSource === 'string' && (mSource.indexOf('.') !== -1 || 1336 mSource.indexOf('[') !== -1 || mSource.indexOf('(') !== -1) ) 1337 { 1338 /* Like the get, we need to get data from a nested object */ 1339 var setData = function (data, val, src) { 1340 var a = _fnSplitObjNotation( src ), b; 1341 var aLast = a[a.length-1]; 1342 var arrayNotation, funcNotation, o, innerSrc; 1343 1344 for ( var i=0, iLen=a.length-1 ; i<iLen ; i++ ) 1345 { 1346 // Check if we are dealing with an array notation request 1347 arrayNotation = a[i].match(__reArray); 1348 funcNotation = a[i].match(__reFn); 1349 1350 if ( arrayNotation ) 1351 { 1352 a[i] = a[i].replace(__reArray, ''); 1353 data[ a[i] ] = []; 1354 1355 // Get the remainder of the nested object to set so we can recurse 1356 b = a.slice(); 1357 b.splice( 0, i+1 ); 1358 innerSrc = b.join('.'); 1359 1360 // Traverse each entry in the array setting the properties requested 1361 for ( var j=0, jLen=val.length ; j<jLen ; j++ ) 1362 { 1363 o = {}; 1364 setData( o, val[j], innerSrc ); 1365 data[ a[i] ].push( o ); 1366 } 1367 1368 // The inner call to setData has already traversed through the remainder 1369 // of the source and has set the data, thus we can exit here 1370 return; 1371 } 1372 else if ( funcNotation ) 1373 { 1374 // Function call 1375 a[i] = a[i].replace(__reFn, ''); 1376 data = data[ a[i] ]( val ); 1377 } 1378 1379 // If the nested object doesn't currently exist - since we are 1380 // trying to set the value - create it 1381 if ( data[ a[i] ] === null || data[ a[i] ] === undefined ) 1382 { 1383 data[ a[i] ] = {}; 1384 } 1385 data = data[ a[i] ]; 1386 } 1387 1388 // Last item in the input - i.e, the actual set 1389 if ( aLast.match(__reFn ) ) 1390 { 1391 // Function call 1392 data = data[ aLast.replace(__reFn, '') ]( val ); 1393 } 1394 else 1395 { 1396 // If array notation is used, we just want to strip it and use the property name 1397 // and assign the value. If it isn't used, then we get the result we want anyway 1398 data[ aLast.replace(__reArray, '') ] = val; 1399 } 1400 }; 1401 1402 return function (data, val) { // meta is also passed in, but not used 1403 return setData( data, val, mSource ); 1404 }; 1405 } 1406 else 1407 { 1408 /* Array or flat object mapping */ 1409 return function (data, val) { // meta is also passed in, but not used 1410 data[mSource] = val; 1411 }; 1412 } 1413 } 1414 1415 1416 /** 1417 * Return an array with the full table data 1418 * @param {object} oSettings dataTables settings object 1419 * @returns array {array} aData Master data array 1420 * @memberof DataTable#oApi 1421 */ 1422 function _fnGetDataMaster ( settings ) 1423 { 1424 return _pluck( settings.aoData, '_aData' ); 1425 } 1426 1427 1428 /** 1429 * Nuke the table 1430 * @param {object} oSettings dataTables settings object 1431 * @memberof DataTable#oApi 1432 */ 1433 function _fnClearTable( settings ) 1434 { 1435 settings.aoData.length = 0; 1436 settings.aiDisplayMaster.length = 0; 1437 settings.aiDisplay.length = 0; 1438 } 1439 1440 1441 /** 1442 * Take an array of integers (index array) and remove a target integer (value - not 1443 * the key!) 1444 * @param {array} a Index array to target 1445 * @param {int} iTarget value to find 1446 * @memberof DataTable#oApi 1447 */ 1448 function _fnDeleteIndex( a, iTarget, splice ) 1449 { 1450 var iTargetIndex = -1; 1451 1452 for ( var i=0, iLen=a.length ; i<iLen ; i++ ) 1453 { 1454 if ( a[i] == iTarget ) 1455 { 1456 iTargetIndex = i; 1457 } 1458 else if ( a[i] > iTarget ) 1459 { 1460 a[i]--; 1461 } 1462 } 1463 1464 if ( iTargetIndex != -1 && splice === undefined ) 1465 { 1466 a.splice( iTargetIndex, 1 ); 1467 } 1468 } 1469 1470 1471 /**
1472 * Mark cached data as invalid such that a re-read of the data will occur when 1473 * the cached data is next requested. Also update from the data source object. 1474 * 1475 * @param {object} settings DataTables settings object 1476 * @param {int} rowIdx Row index to invalidate 1477 * @param {string} [src] Source to invalidate from: undefined, 'auto', 'dom' 1478 * or 'data' 1479 * @param {int} [colIdx] Column index to invalidate. If undefined the whole 1480 * row will be invalidated 1481 * @memberof DataTable#oApi 1482 * 1483 * @todo For the modularisation of v1.11 this will need to become a callback, so 1484 * the sort and filter methods can subscribe to it. That will required 1485 * initialisation options for sorting, which is why it is not already baked in 1486 */ 1487 function _fnInvalidate( settings, rowIdx, src, colIdx ) 1488 { 1489 var row = settings.aoData[ rowIdx ]; 1490 var i, ien; 1491 var cellWrite = function ( cell, col ) { 1492 // This is very frustrating, but in IE if you just write directly 1493 // to innerHTML, and elements that are overwritten are GC'ed, 1494 // even if there is a reference to them elsewhere 1495 while ( cell.childNodes.length ) { 1496 cell.removeChild( cell.firstChild ); 1497 } 1498 1499 cell.innerHTML = _fnGetCellData( settings, rowIdx, col, 'display' ); 1500 }; 1501 1502 // Are we reading last data from DOM or the data object? 1503 if ( src === 'dom' || ((! src || src === 'auto') && row.src === 'dom') ) { 1504 // Read the data from the DOM 1505 row._aData = _fnGetRowElements( 1506 settings, row, colIdx, colIdx === undefined ? undefined : row._aData 1507 ) 1508 .data; 1509 } 1510 else { 1511 // Reading from data object, update the DOM 1512 var cells = row.anCells; 1513 1514 if ( cells ) { 1515 if ( colIdx !== undefined ) { 1516 cellWrite( cells[colIdx], colIdx ); 1517 } 1518 else { 1519 for ( i=0, ien=cells.length ; i<ien ; i++ ) { 1520 cellWrite( cells[i], i ); 1521 } 1522 } 1523 } 1524 } 1525 1526 // For both row and cell invalidation, the cached data for sorting and 1527 // filtering is nulled out 1528 row._aSortData = null; 1529 row._aFilterData = null; 1530 1531 // Invalidate the type for a specific column (if given) or all columns since 1532 // the data might have changed 1533 var cols = settings.aoColumns; 1534 if ( colIdx !== undefined ) { 1535 cols[ colIdx ].sType = null; 1536 } 1537 else { 1538 for ( i=0, ien=cols.length ; i<ien ; i++ ) { 1539 cols[i].sType = null; 1540 } 1541 1542 // Update DataTables special `DT_*` attributes for the row 1543 _fnRowAttributes( row ); 1544 } 1545 } 1546 1547 1548 /** 1549 * Build a data source object from an HTML row, reading the contents of the 1550 * cells that are in the row. 1551 * 1552 * @param {object} settings DataTables settings object 1553 * @param {node|object} TR element from which to read data or existing row 1554 * object from which to re-read the data from the cells 1555 * @param {int} [colIdx] Optional column index 1556 * @param {array|object} [d] Data source object. If `colIdx` is given then this 1557 * parameter should also be given and will be used to write the data into. 1558 * Only the column in question will be written 1559 * @returns {object} Object with two parameters: `data` the data read, in 1560 * document order, and `cells` and array of nodes (they can be useful to the 1561 * caller, so rather than needing a second traversal to get them, just return 1562 * them from here). 1563 * @memberof DataTable#oApi 1564 */ 1565 function _fnGetRowElements( settings, row, colIdx, d ) 1566 { 1567 var 1568 tds = [], 1569 td = row.firstChild, 1570 name, col, o, i=0, contents, 1571 columns = settings.aoColumns, 1572 objectRead = settings._rowReadObject; 1573 1574 // Allow the data object to be passed in, or construct 1575 d = d || objectRead ? {} : []; 1576 1577 var attr = function ( str, td ) { 1578 if ( typeof str === 'string' ) { 1579 var idx = str.indexOf('@'); 1580 1581 if ( idx !== -1 ) { 1582 var attr = str.substring( idx+1 ); 1583 var setter = _fnSetObjectDataFn( str ); 1584 setter( d, td.getAttribute( attr ) ); 1585 } 1586 } 1587 }; 1588 1589 // Read data from a cell and store into the data object 1590 var cellProcess = function ( cell ) { 1591 if ( colIdx === undefined || colIdx === i ) { 1592 col = columns[i]; 1593 contents = $.trim(cell.innerHTML); 1594 1595 if ( col && col._bAttrSrc ) { 1596 var setter = _fnSetObjectDataFn( col.mData._ ); 1597 setter( d, contents ); 1598 1599 attr( col.mData.sort, cell ); 1600 attr( col.mData.type, cell ); 1601 attr( col.mData.filter, cell ); 1602 } 1603 else { 1604 // Depending on the `data` option for the columns the data can 1605 // be read to either an object or an array.
vendor: 11,503 bytes, lines 1606-2043
1606 if ( objectRead ) { 1607 if ( ! col._setter ) { 1608 // Cache the setter function 1609 col._setter = _fnSetObjectDataFn( col.mData ); 1610 } 1611 col._setter( d, contents ); 1612 } 1613 else { 1614 d[i] = contents; 1615 } 1616 } 1617 } 1618 1619 i++; 1620 }; 1621 1622 if ( td ) { 1623 // `tr` element was passed in 1624 while ( td ) { 1625 name = td.nodeName.toUpperCase(); 1626 1627 if ( name == "TD" || name == "TH" ) { 1628 cellProcess( td ); 1629 tds.push( td ); 1630 } 1631 1632 td = td.nextSibling; 1633 } 1634 } 1635 else { 1636 // Existing row object passed in 1637 tds = row.anCells; 1638 1639 for ( var j=0, jen=tds.length ; j<jen ; j++ ) { 1640 cellProcess( tds[j] ); 1641 } 1642 } 1643 1644 return { 1645 data: d, 1646 cells: tds 1647 }; 1648 } 1649 /** 1650 * Create a new TR element (and it's TD children) for a row 1651 * @param {object} oSettings dataTables settings object 1652 * @param {int} iRow Row to consider 1653 * @param {node} [nTrIn] TR element to add to the table - optional. If not given, 1654 * DataTables will create a row automatically 1655 * @param {array} [anTds] Array of TD|TH elements for the row - must be given 1656 * if nTr is. 1657 * @memberof DataTable#oApi 1658 */ 1659 function _fnCreateTr ( oSettings, iRow, nTrIn, anTds ) 1660 { 1661 var 1662 row = oSettings.aoData[iRow], 1663 rowData = row._aData, 1664 cells = [], 1665 nTr, nTd, oCol, 1666 i, iLen; 1667 1668 if ( row.nTr === null ) 1669 { 1670 nTr = nTrIn || document.createElement('tr'); 1671 1672 row.nTr = nTr; 1673 row.anCells = cells; 1674 1675 /* Use a private property on the node to allow reserve mapping from the node 1676 * to the aoData array for fast look up 1677 */ 1678 nTr._DT_RowIndex = iRow; 1679 1680 /* Special parameters can be given by the data source to be used on the row */ 1681 _fnRowAttributes( row ); 1682 1683 /* Process each column */ 1684 for ( i=0, iLen=oSettings.aoColumns.length ; i<iLen ; i++ ) 1685 { 1686 oCol = oSettings.aoColumns[i]; 1687 1688 nTd = nTrIn ? anTds[i] : document.createElement( oCol.sCellType ); 1689 cells.push( nTd ); 1690 1691 // Need to create the HTML if new, or if a rendering function is defined 1692 if ( !nTrIn || oCol.mRender || oCol.mData !== i ) 1693 { 1694 nTd.innerHTML = _fnGetCellData( oSettings, iRow, i, 'display' ); 1695 } 1696 1697 /* Add user defined class */ 1698 if ( oCol.sClass ) 1699 { 1700 nTd.className += ' '+oCol.sClass; 1701 } 1702 1703 // Visibility - add or remove as required 1704 if ( oCol.bVisible && ! nTrIn ) 1705 { 1706 nTr.appendChild( nTd ); 1707 } 1708 else if ( ! oCol.bVisible && nTrIn ) 1709 { 1710 nTd.parentNode.removeChild( nTd ); 1711 } 1712 1713 if ( oCol.fnCreatedCell ) 1714 { 1715 oCol.fnCreatedCell.call( oSettings.oInstance, 1716 nTd, _fnGetCellData( oSettings, iRow, i ), rowData, iRow, i 1717 ); 1718 } 1719 } 1720 1721 _fnCallbackFire( oSettings, 'aoRowCreatedCallback', null, [nTr, rowData, iRow] ); 1722 } 1723 1724 // Remove once webkit bug 131819 and Chromium bug 365619 have been resolved 1725 // and deployed 1726 row.nTr.setAttribute( 'role', 'row' ); 1727 } 1728 1729 1730 /** 1731 * Add attributes to a row based on the special `DT_*` parameters in a data 1732 * source object. 1733 * @param {object} DataTables row object for the row to be modified 1734 * @memberof DataTable#oApi 1735 */ 1736 function _fnRowAttributes( row ) 1737 { 1738 var tr = row.nTr; 1739 var data = row._aData; 1740 1741 if ( tr ) { 1742 if ( data.DT_RowId ) { 1743 tr.id = data.DT_RowId; 1744 } 1745 1746 if ( data.DT_RowClass ) { 1747 // Remove any classes added by DT_RowClass before 1748 var a = data.DT_RowClass.split(' '); 1749 row.__rowc = row.__rowc ? 1750 _unique( row.__rowc.concat( a ) ) : 1751 a; 1752 1753 $(tr) 1754 .removeClass( row.__rowc.join(' ') ) 1755 .addClass( data.DT_RowClass ); 1756 } 1757 1758 if ( data.DT_RowAttr ) { 1759 $(tr).attr( data.DT_RowAttr ); 1760 } 1761 1762 if ( data.DT_RowData ) { 1763 $(tr).data( data.DT_RowData ); 1764 } 1765 } 1766 } 1767 1768 1769 /** 1770 * Create the HTML header for the table 1771 * @param {object} oSettings dataTables settings object 1772 * @memberof DataTable#oApi 1773 */ 1774 function _fnBuildHead( oSettings ) 1775 { 1776 var i, ien, cell, row, column; 1777 var thead = oSettings.nTHead; 1778 var tfoot = oSettings.nTFoot; 1779 var createHeader = $('th, td', thead).length === 0; 1780 var classes = oSettings.oClasses; 1781 var columns = oSettings.aoColumns; 1782 1783 if ( createHeader ) { 1784 row = $('<tr/>').appendTo( thead ); 1785 } 1786 1787 for ( i=0, ien=columns.length ; i<ien ; i++ ) { 1788 column = columns[i]; 1789 cell = $( column.nTh ).addClass( column.sClass ); 1790 1791 if ( createHeader ) { 1792 cell.appendTo( row ); 1793 } 1794 1795 // 1.11 move into sorting 1796 if ( oSettings.oFeatures.bSort ) { 1797 cell.addClass( column.sSortingClass ); 1798 1799 if ( column.bSortable !== false ) { 1800 cell 1801 .attr( 'tabindex', oSettings.iTabIndex ) 1802 .attr( 'aria-controls', oSettings.sTableId ); 1803 1804 _fnSortAttachListener( oSettings, column.nTh, i ); 1805 } 1806 } 1807 1808 if ( column.sTitle != cell.html() ) { 1809 cell.html( column.sTitle ); 1810 } 1811 1812 _fnRenderer( oSettings, 'header' )( 1813 oSettings, cell, column, classes 1814 ); 1815 } 1816 1817 if ( createHeader ) { 1818 _fnDetectHeader( oSettings.aoHeader, thead ); 1819 } 1820 1821 /* ARIA role for the rows */ 1822 $(thead).find('>tr').attr('role', 'row'); 1823 1824 /* Deal with the footer - add classes if required */ 1825 $(thead).find('>tr>th, >tr>td').addClass( classes.sHeaderTH ); 1826 $(tfoot).find('>tr>th, >tr>td').addClass( classes.sFooterTH ); 1827 1828 // Cache the footer cells. Note that we only take the cells from the first 1829 // row in the footer. If there is more than one row the user wants to 1830 // interact with, they need to use the table().foot() method. Note also this 1831 // allows cells to be used for multiple columns using colspan 1832 if ( tfoot !== null ) { 1833 var cells = oSettings.aoFooter[0]; 1834 1835 for ( i=0, ien=cells.length ; i<ien ; i++ ) { 1836 column = columns[i]; 1837 column.nTf = cells[i].cell; 1838 1839 if ( column.sClass ) { 1840 $(column.nTf).addClass( column.sClass ); 1841 } 1842 } 1843 } 1844 } 1845 1846 1847 /** 1848 * Draw the header (or footer) element based on the column visibility states. The 1849 * methodology here is to use the layout array from _fnDetectHeader, modified for 1850 * the instantaneous column visibility, to construct the new layout. The grid is 1851 * traversed over cell at a time in a rows x columns grid fashion, although each 1852 * cell insert can cover multiple elements in the grid - which is tracks using the 1853 * aApplied array. Cell inserts in the grid will only occur where there isn't 1854 * already a cell in that position. 1855 * @param {object} oSettings dataTables settings object 1856 * @param array {objects} aoSource Layout array from _fnDetectHeader 1857 * @param {boolean} [bIncludeHidden=false] If true then include the hidden columns in the calc, 1858 * @memberof DataTable#oApi 1859 */ 1860 function _fnDrawHead( oSettings, aoSource, bIncludeHidden ) 1861 { 1862 var i, iLen, j, jLen, k, kLen, n, nLocalTr; 1863 var aoLocal = []; 1864 var aApplied = []; 1865 var iColumns = oSettings.aoColumns.length; 1866 var iRowspan, iColspan; 1867 1868 if ( ! aoSource ) 1869 { 1870 return; 1871 } 1872 1873 if ( bIncludeHidden === undefined ) 1874 { 1875 bIncludeHidden = false; 1876 } 1877 1878 /* Make a copy of the master layout array, but without the visible columns in it */ 1879 for ( i=0, iLen=aoSource.length ; i<iLen ; i++ ) 1880 { 1881 aoLocal[i] = aoSource[i].slice(); 1882 aoLocal[i].nTr = aoSource[i].nTr; 1883 1884 /* Remove any columns which are currently hidden */ 1885 for ( j=iColumns-1 ; j>=0 ; j-- ) 1886 { 1887 if ( !oSettings.aoColumns[j].bVisible && !bIncludeHidden ) 1888 { 1889 aoLocal[i].splice( j, 1 ); 1890 } 1891 } 1892 1893 /* Prep the applied array - it needs an element for each row */ 1894 aApplied.push( [] ); 1895 } 1896 1897 for ( i=0, iLen=aoLocal.length ; i<iLen ; i++ ) 1898 { 1899 nLocalTr = aoLocal[i].nTr; 1900 1901 /* All cells are going to be replaced, so empty out the row */ 1902 if ( nLocalTr ) 1903 { 1904 while( (n = nLocalTr.firstChild) ) 1905 { 1906 nLocalTr.removeChild( n ); 1907 } 1908 } 1909 1910 for ( j=0, jLen=aoLocal[i].length ; j<jLen ; j++ ) 1911 { 1912 iRowspan = 1; 1913 iColspan = 1; 1914 1915 /* Check to see if there is already a cell (row/colspan) covering our target 1916 * insert point. If there is, then there is nothing to do. 1917 */ 1918 if ( aApplied[i][j] === undefined ) 1919 { 1920 nLocalTr.appendChild( aoLocal[i][j].cell ); 1921 aApplied[i][j] = 1; 1922 1923 /* Expand the cell to cover as many rows as needed */ 1924 while ( aoLocal[i+iRowspan] !== undefined && 1925 aoLocal[i][j].cell == aoLocal[i+iRowspan][j].cell ) 1926 { 1927 aApplied[i+iRowspan][j] = 1; 1928 iRowspan++; 1929 } 1930 1931 /* Expand the cell to cover as many columns as needed */ 1932 while ( aoLocal[i][j+iColspan] !== undefined && 1933 aoLocal[i][j].cell == aoLocal[i][j+iColspan].cell ) 1934 { 1935 /* Must update the applied array over the rows for the columns */ 1936 for ( k=0 ; k<iRowspan ; k++ ) 1937 { 1938 aApplied[i+k][j+iColspan] = 1; 1939 } 1940 iColspan++; 1941 } 1942 1943 /* Do the actual expansion in the DOM */ 1944 $(aoLocal[i][j].cell) 1945 .attr('rowspan', iRowspan) 1946 .attr('colspan', iColspan); 1947 } 1948 } 1949 } 1950 } 1951 1952 1953 /** 1954 * Insert the required TR nodes into the table for display 1955 * @param {object} oSettings dataTables settings object 1956 * @memberof DataTable#oApi 1957 */ 1958 function _fnDraw( oSettings ) 1959 { 1960 /* Provide a pre-callback function which can be used to cancel the draw is false is returned */ 1961 var aPreDraw = _fnCallbackFire( oSettings, 'aoPreDrawCallback', 'preDraw', [oSettings] ); 1962 if ( $.inArray( false, aPreDraw ) !== -1 ) 1963 { 1964 _fnProcessingDisplay( oSettings, false ); 1965 return; 1966 } 1967 1968 var i, iLen, n; 1969 var anRows = []; 1970 var iRowCount = 0; 1971 var asStripeClasses = oSettings.asStripeClasses; 1972 var iStripes = asStripeClasses.length; 1973 var iOpenRows = oSettings.aoOpenRows.length; 1974 var oLang = oSettings.oLanguage; 1975 var iInitDisplayStart = oSettings.iInitDisplayStart; 1976 var bServerSide = _fnDataSource( oSettings ) == 'ssp'; 1977 var aiDisplay = oSettings.aiDisplay; 1978 1979 oSettings.bDrawing = true; 1980 1981 /* Check and see if we have an initial draw position from state saving */ 1982 if ( iInitDisplayStart !== undefined && iInitDisplayStart !== -1 ) 1983 { 1984 oSettings._iDisplayStart = bServerSide ? 1985 iInitDisplayStart : 1986 iInitDisplayStart >= oSettings.fnRecordsDisplay() ? 1987 0 : 1988 iInitDisplayStart; 1989 1990 oSettings.iInitDisplayStart = -1; 1991 } 1992 1993 var iDisplayStart = oSettings._iDisplayStart; 1994 var iDisplayEnd = oSettings.fnDisplayEnd(); 1995 1996 /* Server-side processing draw intercept */ 1997 if ( oSettings.bDeferLoading ) 1998 { 1999 oSettings.bDeferLoading = false; 2000 oSettings.iDraw++; 2001 _fnProcessingDisplay( oSettings, false ); 2002 } 2003 else if ( !bServerSide ) 2004 { 2005 oSettings.iDraw++; 2006 } 2007 else if ( !oSettings.bDestroying && !_fnAjaxUpdate( oSettings ) ) 2008 { 2009 return; 2010 } 2011 2012 if ( aiDisplay.length !== 0 ) 2013 { 2014 var iStart = bServerSide ? 0 : iDisplayStart; 2015 var iEnd = bServerSide ? oSettings.aoData.length : iDisplayEnd; 2016 2017 for ( var j=iStart ; j<iEnd ; j++ ) 2018 { 2019 var iDataIndex = aiDisplay[j]; 2020 var aoData = oSettings.aoData[ iDataIndex ]; 2021 if ( aoData.nTr === null ) 2022 { 2023 _fnCreateTr( oSettings, iDataIndex ); 2024 } 2025 2026 var nRow = aoData.nTr; 2027 2028 /* Remove the old striping classes and then add the new one */ 2029 if ( iStripes !== 0 ) 2030 { 2031 var sStripe = asStripeClasses[ iRowCount % iStripes ]; 2032 if ( aoData._sRowStripe != sStripe ) 2033 { 2034 $(nRow).removeClass( aoData._sRowStripe ).addClass( sStripe ); 2035 aoData._sRowStripe = sStripe; 2036 } 2037 } 2038 2039 // Row callback functions - might want to manipulate the row 2040 // iRowCount and j are not currently documented. Are they at all 2041 // useful? 2042 _fnCallbackFire( oSettings, 'aoRowCallback', null, 2043 [nRow, aoData._aData, iRowCount, j
vendor: 6,302 bytes, lines 2043-2280
2043] ); 2044 2045 anRows.push( nRow ); 2046 iRowCount++; 2047 } 2048 } 2049 else 2050 { 2051 /* Table is empty - create a row with an empty message in it */ 2052 var sZero = oLang.sZeroRecords; 2053 if ( oSettings.iDraw == 1 && _fnDataSource( oSettings ) == 'ajax' ) 2054 { 2055 sZero = oLang.sLoadingRecords; 2056 } 2057 else if ( oLang.sEmptyTable && oSettings.fnRecordsTotal() === 0 ) 2058 { 2059 sZero = oLang.sEmptyTable; 2060 } 2061 2062 anRows[ 0 ] = $( '<tr/>', { 'class': iStripes ? asStripeClasses[0] : '' } ) 2063 .append( $('<td />', { 2064 'valign': 'top', 2065 'colSpan': _fnVisbleColumns( oSettings ), 2066 'class': oSettings.oClasses.sRowEmpty 2067 } ).html( sZero ) )[0]; 2068 } 2069 2070 /* Header and footer callbacks */ 2071 _fnCallbackFire( oSettings, 'aoHeaderCallback', 'header', [ $(oSettings.nTHead).children('tr')[0], 2072 _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] ); 2073 2074 _fnCallbackFire( oSettings, 'aoFooterCallback', 'footer', [ $(oSettings.nTFoot).children('tr')[0], 2075 _fnGetDataMaster( oSettings ), iDisplayStart, iDisplayEnd, aiDisplay ] ); 2076 2077 var body = $(oSettings.nTBody); 2078 2079 body.children().detach(); 2080 body.append( $(anRows) ); 2081 2082 /* Call all required callback functions for the end of a draw */ 2083 _fnCallbackFire( oSettings, 'aoDrawCallback', 'draw', [oSettings] ); 2084 2085 /* Draw is complete, sorting and filtering must be as well */ 2086 oSettings.bSorted = false; 2087 oSettings.bFiltered = false; 2088 oSettings.bDrawing = false; 2089 } 2090 2091 2092 /** 2093 * Redraw the table - taking account of the various features which are enabled 2094 * @param {object} oSettings dataTables settings object 2095 * @param {boolean} [holdPosition] Keep the current paging position. By default 2096 * the paging is reset to the first page 2097 * @memberof DataTable#oApi 2098 */ 2099 function _fnReDraw( settings, holdPosition ) 2100 { 2101 var 2102 features = settings.oFeatures, 2103 sort = features.bSort, 2104 filter = features.bFilter; 2105 2106 if ( sort ) { 2107 _fnSort( settings ); 2108 } 2109 2110 if ( filter ) { 2111 _fnFilterComplete( settings, settings.oPreviousSearch ); 2112 } 2113 else { 2114 // No filtering, so we want to just use the display master 2115 settings.aiDisplay = settings.aiDisplayMaster.slice(); 2116 } 2117 2118 if ( holdPosition !== true ) { 2119 settings._iDisplayStart = 0; 2120 } 2121 2122 // Let any modules know about the draw hold position state (used by 2123 // scrolling internally) 2124 settings._drawHold = holdPosition; 2125 2126 _fnDraw( settings ); 2127 2128 settings._drawHold = false; 2129 } 2130 2131 2132 /** 2133 * Add the options to the page HTML for the table 2134 * @param {object} oSettings dataTables settings object 2135 * @memberof DataTable#oApi 2136 */ 2137 function _fnAddOptionsHtml ( oSettings ) 2138 { 2139 var classes = oSettings.oClasses; 2140 var table = $(oSettings.nTable); 2141 var holding = $('<div/>').insertBefore( table ); // Holding element for speed 2142 var features = oSettings.oFeatures; 2143 2144 // All DataTables are wrapped in a div 2145 var insert = $('<div/>', { 2146 id: oSettings.sTableId+'_wrapper', 2147 'class': classes.sWrapper + (oSettings.nTFoot ? '' : ' '+classes.sNoFooter) 2148 } ); 2149 2150 oSettings.nHolding = holding[0]; 2151 oSettings.nTableWrapper = insert[0]; 2152 oSettings.nTableReinsertBefore = oSettings.nTable.nextSibling; 2153 2154 /* Loop over the user set positioning and place the elements as needed */ 2155 var aDom = oSettings.sDom.split(''); 2156 var featureNode, cOption, nNewNode, cNext, sAttr, j; 2157 for ( var i=0 ; i<aDom.length ; i++ ) 2158 { 2159 featureNode = null; 2160 cOption = aDom[i]; 2161 2162 if ( cOption == '<' ) 2163 { 2164 /* New container div */ 2165 nNewNode = $('<div/>')[0]; 2166 2167 /* Check to see if we should append an id and/or a class name to the container */ 2168 cNext = aDom[i+1]; 2169 if ( cNext == "'" || cNext == '"' ) 2170 { 2171 sAttr = ""; 2172 j = 2; 2173 while ( aDom[i+j] != cNext ) 2174 { 2175 sAttr += aDom[i+j]; 2176 j++; 2177 } 2178 2179 /* Replace jQuery UI constants @todo depreciated */ 2180 if ( sAttr == "H" ) 2181 { 2182 sAttr = classes.sJUIHeader; 2183 } 2184 else if ( sAttr == "F" ) 2185 { 2186 sAttr = classes.sJUIFooter; 2187 } 2188 2189 /* The attribute can be in the format of "#id.class", "#id" or "class" This logic 2190 * breaks the string into parts and applies them as needed 2191 */ 2192 if ( sAttr.indexOf('.') != -1 ) 2193 { 2194 var aSplit = sAttr.split('.'); 2195 nNewNode.id = aSplit[0].substr(1, aSplit[0].length-1); 2196 nNewNode.className = aSplit[1]; 2197 } 2198 else if ( sAttr.charAt(0) == "#" ) 2199 { 2200 nNewNode.id = sAttr.substr(1, sAttr.length-1); 2201 } 2202 else 2203 { 2204 nNewNode.className = sAttr; 2205 } 2206 2207 i += j; /* Move along the position array */ 2208 } 2209 2210 insert.append( nNewNode ); 2211 insert = $(nNewNode); 2212 } 2213 else if ( cOption == '>' ) 2214 { 2215 /* End container div */ 2216 insert = insert.parent(); 2217 } 2218 // @todo Move options into their own plugins? 2219 else if ( cOption == 'l' && features.bPaginate && features.bLengthChange ) 2220 { 2221 /* Length */ 2222 featureNode = _fnFeatureHtmlLength( oSettings ); 2223 } 2224 else if ( cOption == 'f' && features.bFilter ) 2225 { 2226 /* Filter */ 2227 featureNode = _fnFeatureHtmlFilter( oSettings ); 2228 } 2229 else if ( cOption == 'r' && features.bProcessing ) 2230 { 2231 /* pRocessing */ 2232 featureNode = _fnFeatureHtmlProcessing( oSettings ); 2233 } 2234 else if ( cOption == 't' ) 2235 { 2236 /* Table */ 2237 featureNode = _fnFeatureHtmlTable( oSettings ); 2238 } 2239 else if ( cOption == 'i' && features.bInfo ) 2240 { 2241 /* Info */ 2242 featureNode = _fnFeatureHtmlInfo( oSettings ); 2243 } 2244 else if ( cOption == 'p' && features.bPaginate ) 2245 { 2246 /* Pagination */ 2247 featureNode = _fnFeatureHtmlPaginate( oSettings ); 2248 } 2249 else if ( DataTable.ext.feature.length !== 0 ) 2250 { 2251 /* Plug-in features */ 2252 var aoFeatures = DataTable.ext.feature; 2253 for ( var k=0, kLen=aoFeatures.length ; k<kLen ; k++ ) 2254 { 2255 if ( cOption == aoFeatures[k].cFeature ) 2256 { 2257 featureNode = aoFeatures[k].fnInit( oSettings ); 2258 break; 2259 } 2260 } 2261 } 2262 2263 /* Add to the 2D features array */ 2264 if ( featureNode ) 2265 { 2266 var aanFeatures = oSettings.aanFeatures; 2267 2268 if ( ! aanFeatures[cOption] ) 2269 { 2270 aanFeatures[cOption] = []; 2271 } 2272 2273 aanFeatures[cOption].push( featureNode ); 2274 insert.append( featureNode ); 2275 } 2276 } 2277 2278 /* Built our DOM structure - replace the holding div with what we want */ 2279 holding.replaceWith( insert ); 2280
vendor: 42,271 bytes, lines 2280-3782
2280} 2281 2282 2283 /** 2284 * Use the DOM source to create up an array of header cells. The idea here is to 2285 * create a layout grid (array) of rows x columns, which contains a reference 2286 * to the cell that that point in the grid (regardless of col/rowspan), such that 2287 * any column / row could be removed and the new grid constructed 2288 * @param array {object} aLayout Array to store the calculated layout in 2289 * @param {node} nThead The header/footer element for the table 2290 * @memberof DataTable#oApi 2291 */ 2292 function _fnDetectHeader ( aLayout, nThead ) 2293 { 2294 var nTrs = $(nThead).children('tr'); 2295 var nTr, nCell; 2296 var i, k, l, iLen, jLen, iColShifted, iColumn, iColspan, iRowspan; 2297 var bUnique; 2298 var fnShiftCol = function ( a, i, j ) { 2299 var k = a[i]; 2300 while ( k[j] ) { 2301 j++; 2302 } 2303 return j; 2304 }; 2305 2306 aLayout.splice( 0, aLayout.length ); 2307 2308 /* We know how many rows there are in the layout - so prep it */ 2309 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) 2310 { 2311 aLayout.push( [] ); 2312 } 2313 2314 /* Calculate a layout array */ 2315 for ( i=0, iLen=nTrs.length ; i<iLen ; i++ ) 2316 { 2317 nTr = nTrs[i]; 2318 iColumn = 0; 2319 2320 /* For every cell in the row... */ 2321 nCell = nTr.firstChild; 2322 while ( nCell ) { 2323 if ( nCell.nodeName.toUpperCase() == "TD" || 2324 nCell.nodeName.toUpperCase() == "TH" ) 2325 { 2326 /* Get the col and rowspan attributes from the DOM and sanitise them */ 2327 iColspan = nCell.getAttribute('colspan') * 1; 2328 iRowspan = nCell.getAttribute('rowspan') * 1; 2329 iColspan = (!iColspan || iColspan===0 || iColspan===1) ? 1 : iColspan; 2330 iRowspan = (!iRowspan || iRowspan===0 || iRowspan===1) ? 1 : iRowspan; 2331 2332 /* There might be colspan cells already in this row, so shift our target 2333 * accordingly 2334 */ 2335 iColShifted = fnShiftCol( aLayout, i, iColumn ); 2336 2337 /* Cache calculation for unique columns */ 2338 bUnique = iColspan === 1 ? true : false; 2339 2340 /* If there is col / rowspan, copy the information into the layout grid */ 2341 for ( l=0 ; l<iColspan ; l++ ) 2342 { 2343 for ( k=0 ; k<iRowspan ; k++ ) 2344 { 2345 aLayout[i+k][iColShifted+l] = { 2346 "cell": nCell, 2347 "unique": bUnique 2348 }; 2349 aLayout[i+k].nTr = nTr; 2350 } 2351 } 2352 } 2353 nCell = nCell.nextSibling; 2354 } 2355 } 2356 } 2357 2358 2359 /** 2360 * Get an array of unique th elements, one for each column 2361 * @param {object} oSettings dataTables settings object 2362 * @param {node} nHeader automatically detect the layout from this node - optional 2363 * @param {array} aLayout thead/tfoot layout from _fnDetectHeader - optional 2364 * @returns array {node} aReturn list of unique th's 2365 * @memberof DataTable#oApi 2366 */ 2367 function _fnGetUniqueThs ( oSettings, nHeader, aLayout ) 2368 { 2369 var aReturn = []; 2370 if ( !aLayout ) 2371 { 2372 aLayout = oSettings.aoHeader; 2373 if ( nHeader ) 2374 { 2375 aLayout = []; 2376 _fnDetectHeader( aLayout, nHeader ); 2377 } 2378 } 2379 2380 for ( var i=0, iLen=aLayout.length ; i<iLen ; i++ ) 2381 { 2382 for ( var j=0, jLen=aLayout[i].length ; j<jLen ; j++ ) 2383 { 2384 if ( aLayout[i][j].unique && 2385 (!aReturn[j] || !oSettings.bSortCellsTop) ) 2386 { 2387 aReturn[j] = aLayout[i][j].cell; 2388 } 2389 } 2390 } 2391 2392 return aReturn; 2393 } 2394 2395 /** 2396 * Create an Ajax call based on the table's settings, taking into account that 2397 * parameters can have multiple forms, and backwards compatibility. 2398 * 2399 * @param {object} oSettings dataTables settings object 2400 * @param {array} data Data to send to the server, required by 2401 * DataTables - may be augmented by developer callbacks 2402 * @param {function} fn Callback function to run when data is obtained 2403 */ 2404 function _fnBuildAjax( oSettings, data, fn ) 2405 { 2406 // Compatibility with 1.9-, allow fnServerData and event to manipulate 2407 _fnCallbackFire( oSettings, 'aoServerParams', 'serverParams', [data] ); 2408 2409 // Convert to object based for 1.10+ if using the old array scheme which can 2410 // come from server-side processing or serverParams 2411 if ( data && $.isArray(data) ) { 2412 var tmp = {}; 2413 var rbracket = /(.*?)\[\]$/; 2414 2415 $.each( data, function (key, val) { 2416 var match = val.name.match(rbracket); 2417 2418 if ( match ) { 2419 // Support for arrays 2420 var name = match[0]; 2421 2422 if ( ! tmp[ name ] ) { 2423 tmp[ name ] = []; 2424 } 2425 tmp[ name ].push( val.value ); 2426 } 2427 else { 2428 tmp[val.name] = val.value; 2429 } 2430 } ); 2431 data = tmp; 2432 } 2433 2434 var ajaxData; 2435 var ajax = oSettings.ajax; 2436 var instance = oSettings.oInstance; 2437 var callback = function ( json ) { 2438 _fnCallbackFire( oSettings, null, 'xhr', [oSettings, json, oSettings.jqXHR] ); 2439 fn( json ); 2440 }; 2441 2442 if ( $.isPlainObject( ajax ) && ajax.data ) 2443 { 2444 ajaxData = ajax.data; 2445 2446 var newData = $.isFunction( ajaxData ) ? 2447 ajaxData( data, oSettings ) : // fn can manipulate data or return 2448 ajaxData; // an object object or array to merge 2449 2450 // If the function returned something, use that alone 2451 data = $.isFunction( ajaxData ) && newData ? 2452 newData : 2453 $.extend( true, data, newData ); 2454 2455 // Remove the data property as we've resolved it already and don't want 2456 // jQuery to do it again (it is restored at the end of the function) 2457 delete ajax.data; 2458 } 2459 2460 var baseAjax = { 2461 "data": data, 2462 "success": function (json) { 2463 var error = json.error || json.sError; 2464 if ( error ) { 2465 _fnLog( oSettings, 0, error ); 2466 } 2467 2468 oSettings.json = json; 2469 callback( json ); 2470 }, 2471 "dataType": "json", 2472 "cache": false, 2473 "type": oSettings.sServerMethod, 2474 "error": function (xhr, error, thrown) { 2475 var ret = _fnCallbackFire( oSettings, null, 'xhr', [oSettings, null, oSettings.jqXHR] ); 2476 2477 if ( $.inArray( true, ret ) === -1 ) { 2478 if ( error == "parsererror" ) { 2479 _fnLog( oSettings, 0, 'Invalid JSON response', 1 ); 2480 } 2481 else if ( xhr.readyState === 4 ) { 2482 _fnLog( oSettings, 0, 'Ajax error', 7 ); 2483 } 2484 } 2485 2486 _fnProcessingDisplay( oSettings, false ); 2487 } 2488 }; 2489 2490 // Store the data submitted for the API 2491 oSettings.oAjaxData = data; 2492 2493 // Allow plug-ins and external processes to modify the data 2494 _fnCallbackFire( oSettings, null, 'preXhr', [oSettings, data] ); 2495 2496 if ( oSettings.fnServerData ) 2497 { 2498 // DataTables 1.9- compatibility 2499 oSettings.fnServerData.call( instance, 2500 oSettings.sAjaxSource, 2501 $.map( data, function (val, key) { // Need to convert back to 1.9 trad format 2502 return { name: key, value: val }; 2503 } ), 2504 callback, 2505 oSettings 2506 ); 2507 } 2508 else if ( oSettings.sAjaxSource || typeof ajax === 'string' ) 2509 { 2510 // DataTables 1.9- compatibility 2511 oSettings.jqXHR = $.ajax( $.extend( baseAjax, { 2512 url: ajax || oSettings.sAjaxSource 2513 } ) ); 2514 } 2515 else if ( $.isFunction( ajax ) ) 2516 { 2517 // Is a function - let the caller define what needs to be done 2518 oSettings.jqXHR = ajax.call( instance, data, callback, oSettings ); 2519 } 2520 else 2521 { 2522 // Object to extend the base settings 2523 oSettings.jqXHR = $.ajax( $.extend( baseAjax, ajax ) ); 2524 2525 // Restore for next time around 2526 ajax.data = ajaxData; 2527 } 2528 } 2529 2530 2531 /** 2532 * Update the table using an Ajax call 2533 * @param {object} settings dataTables settings object 2534 * @returns {boolean} Block the table drawing or not 2535 * @memberof DataTable#oApi 2536 */ 2537 function _fnAjaxUpdate( settings ) 2538 { 2539 if ( settings.bAjaxDataGet ) { 2540 settings.iDraw++; 2541 _fnProcessingDisplay( settings, true ); 2542 2543 _fnBuildAjax( 2544 settings, 2545 _fnAjaxParameters( settings ), 2546 function(json) { 2547 _fnAjaxUpdateDraw( settings, json ); 2548 } 2549 ); 2550 2551 return false; 2552 } 2553 return true; 2554 } 2555 2556 2557 /** 2558 * Build up the parameters in an object needed for a server-side processing 2559 * request. Note that this is basically done twice, is different ways - a modern 2560 * method which is used by default in DataTables 1.10 which uses objects and 2561 * arrays, or the 1.9- method with is name / value pairs. 1.9 method is used if 2562 * the sAjaxSource option is used in the initialisation, or the legacyAjax 2563 * option is set. 2564 * @param {object} oSettings dataTables settings object 2565 * @returns {bool} block the table drawing or not 2566 * @memberof DataTable#oApi 2567 */ 2568 function _fnAjaxParameters( settings ) 2569 { 2570 var 2571 columns = settings.aoColumns, 2572 columnCount = columns.length, 2573 features = settings.oFeatures, 2574 preSearch = settings.oPreviousSearch, 2575 preColSearch = settings.aoPreSearchCols, 2576 i, data = [], dataProp, column, columnSearch, 2577 sort = _fnSortFlatten( settings ), 2578 displayStart = settings._iDisplayStart, 2579 displayLength = features.bPaginate !== false ? 2580 settings._iDisplayLength : 2581 -1; 2582 2583 var param = function ( name, value ) { 2584 data.push( { 'name': name, 'value': value } ); 2585 }; 2586 2587 // DataTables 1.9- compatible method 2588 param( 'sEcho', settings.iDraw ); 2589 param( 'iColumns', columnCount ); 2590 param( 'sColumns', _pluck( columns, 'sName' ).join(',') ); 2591 param( 'iDisplayStart', displayStart ); 2592 param( 'iDisplayLength', displayLength ); 2593 2594 // DataTables 1.10+ method 2595 var d = { 2596 draw: settings.iDraw, 2597 columns: [], 2598 order: [], 2599 start: displayStart, 2600 length: displayLength, 2601 search: { 2602 value: preSearch.sSearch, 2603 regex: preSearch.bRegex 2604 } 2605 }; 2606 2607 for ( i=0 ; i<columnCount ; i++ ) { 2608 column = columns[i]; 2609 columnSearch = preColSearch[i]; 2610 dataProp = typeof column.mData=="function" ? 'function' : column.mData ; 2611 2612 d.columns.push( { 2613 data: dataProp, 2614 name: column.sName, 2615 searchable: column.bSearchable, 2616 orderable: column.bSortable, 2617 search: { 2618 value: columnSearch.sSearch, 2619 regex: columnSearch.bRegex 2620 } 2621 } ); 2622 2623 param( "mDataProp_"+i, dataProp ); 2624 2625 if ( features.bFilter ) { 2626 param( 'sSearch_'+i, columnSearch.sSearch ); 2627 param( 'bRegex_'+i, columnSearch.bRegex ); 2628 param( 'bSearchable_'+i, column.bSearchable ); 2629 } 2630 2631 if ( features.bSort ) { 2632 param( 'bSortable_'+i, column.bSortable ); 2633 } 2634 } 2635 2636 if ( features.bFilter ) { 2637 param( 'sSearch', preSearch.sSearch ); 2638 param( 'bRegex', preSearch.bRegex ); 2639 } 2640 2641 if ( features.bSort ) { 2642 $.each( sort, function ( i, val ) { 2643 d.order.push( { column: val.col, dir: val.dir } ); 2644 2645 param( 'iSortCol_'+i, val.col ); 2646 param( 'sSortDir_'+i, val.dir ); 2647 } ); 2648 2649 param( 'iSortingCols', sort.length ); 2650 } 2651 2652 // If the legacy.ajax parameter is null, then we automatically decide which 2653 // form to use, based on sAjaxSource 2654 var legacy = DataTable.ext.legacy.ajax; 2655 if ( legacy === null ) { 2656 return settings.sAjaxSource ? data : d; 2657 } 2658 2659 // Otherwise, if legacy has been specified then we use that to decide on the 2660 // form 2661 return legacy ? data : d; 2662 } 2663 2664 2665 /** 2666 * Data the data from the server (nuking the old) and redraw the table 2667 * @param {object} oSettings dataTables settings object 2668 * @param {object} json json data return from the server. 2669 * @param {string} json.sEcho Tracking flag for DataTables to match requests 2670 * @param {int} json.iTotalRecords Number of records in the data set, not accounting for filtering 2671 * @param {int} json.iTotalDisplayRecords Number of records in the data set, accounting for filtering 2672 * @param {array} json.aaData The data to display on this page 2673 * @param {string} [json.sColumns] Column ordering (sName, comma separated) 2674 * @memberof DataTable#oApi 2675 */ 2676 function _fnAjaxUpdateDraw ( settings, json ) 2677 { 2678 // v1.10 uses camelCase variables, while 1.9 uses Hungarian notation. 2679 // Support both 2680 var compat = function ( old, modern ) { 2681 return json[old] !== undefined ? json[old] : json[modern]; 2682 }; 2683 2684 var data = _fnAjaxDataSrc( settings, json ); 2685 var draw = compat( 'sEcho', 'draw' ); 2686 var recordsTotal = compat( 'iTotalRecords', 'recordsTotal' ); 2687 var recordsFiltered = compat( 'iTotalDisplayRecords', 'recordsFiltered' ); 2688 2689 if ( draw ) { 2690 // Protect against out of sequence returns 2691 if ( draw*1 < settings.iDraw ) { 2692 return; 2693 } 2694 settings.iDraw = draw * 1; 2695 } 2696 2697 _fnClearTable( settings ); 2698 settings._iRecordsTotal = parseInt(recordsTotal, 10); 2699 settings._iRecordsDisplay = parseInt(recordsFiltered, 10); 2700 2701 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 2702 _fnAddData( settings, data[i] ); 2703 } 2704 settings.aiDisplay = settings.aiDisplayMaster.slice(); 2705 2706 settings.bAjaxDataGet = false; 2707 _fnDraw( settings ); 2708 2709 if ( ! settings._bInitComplete ) { 2710 _fnInitComplete( settings, json ); 2711 } 2712 2713 settings.bAjaxDataGet = true; 2714 _fnProcessingDisplay( settings, false ); 2715 } 2716 2717 2718 /** 2719 * Get the data from the JSON data source to use for drawing a table. Using 2720 * `_fnGetObjectDataFn` allows the data to be sourced from a property of the 2721 * source object, or from a processing function. 2722 * @param {object} oSettings dataTables settings object 2723 * @param {object} json Data source object / array from the server 2724 * @return {array} Array of data to use 2725 */ 2726 function _fnAjaxDataSrc ( oSettings, json ) 2727 { 2728 var dataSrc = $.isPlainObject( oSettings.ajax ) && oSettings.ajax.dataSrc !== undefined ? 2729 oSettings.ajax.dataSrc : 2730 oSettings.sAjaxDataProp; // Compatibility with 1.9-. 2731 2732 // Compatibility with 1.9-. In order to read from aaData, check if the 2733 // default has been changed, if not, check for aaData 2734 if ( dataSrc === 'data' ) { 2735 return json.aaData || json[dataSrc]; 2736 } 2737 2738 return dataSrc !== "" ? 2739 _fnGetObjectDataFn( dataSrc )( json ) : 2740 json; 2741 } 2742 2743 /** 2744 * Generate the node required for filtering text 2745 * @returns {node} Filter control element 2746 * @param {object} oSettings dataTables settings object 2747 * @memberof DataTable#oApi 2748 */ 2749 function _fnFeatureHtmlFilter ( settings ) 2750 { 2751 var classes = settings.oClasses; 2752 var tableId = settings.sTableId; 2753 var language = settings.oLanguage; 2754 var previousSearch = settings.oPreviousSearch; 2755 var features = settings.aanFeatures; 2756 var input = '<input type="search" class="'+classes.sFilterInput+'"/>'; 2757 2758 var str = language.sSearch; 2759 str = str.match(/_INPUT_/) ? 2760 str.replace('_INPUT_', input) : 2761 str+input; 2762 2763 var filter = $('<div/>', { 2764 'id': ! features.f ? tableId+'_filter' : null, 2765 'class': classes.sFilter 2766 } ) 2767 .append( $('<label/>' ).append( str ) ); 2768 2769 var searchFn = function() { 2770 /* Update all other filter input elements for the new display */ 2771 var n = features.f; 2772 var val = !this.value ? "" : this.value; // mental IE8 fix :-( 2773 2774 /* Now do the filter */ 2775 if ( val != previousSearch.sSearch ) { 2776 _fnFilterComplete( settings, { 2777 "sSearch": val, 2778 "bRegex": previousSearch.bRegex, 2779 "bSmart": previousSearch.bSmart , 2780 "bCaseInsensitive": previousSearch.bCaseInsensitive 2781 } ); 2782 2783 // Need to redraw, without resorting 2784 settings._iDisplayStart = 0; 2785 _fnDraw( settings ); 2786 } 2787 }; 2788 2789 var searchDelay = settings.searchDelay !== null ? 2790 settings.searchDelay : 2791 _fnDataSource( settings ) === 'ssp' ? 2792 400 : 2793 0; 2794 2795 var jqFilter = $('input', filter) 2796 .val( previousSearch.sSearch ) 2797 .attr( 'placeholder', language.sSearchPlaceholder ) 2798 .bind( 2799 'keyup.DT search.DT input.DT paste.DT cut.DT', 2800 searchDelay ? 2801 _fnThrottle( searchFn, searchDelay ) : 2802 searchFn 2803 ) 2804 .bind( 'keypress.DT', function(e) { 2805 /* Prevent form submission */ 2806 if ( e.keyCode == 13 ) { 2807 return false; 2808 } 2809 } ) 2810 .attr('aria-controls', tableId); 2811 2812 // Update the input elements whenever the table is filtered 2813 $(settings.nTable).on( 'search.dt.DT', function ( ev, s ) { 2814 if ( settings === s ) { 2815 // IE9 throws an 'unknown error' if document.activeElement is used 2816 // inside an iframe or frame... 2817 try { 2818 if ( jqFilter[0] !== document.activeElement ) { 2819 jqFilter.val( previousSearch.sSearch ); 2820 } 2821 } 2822 catch ( e ) {} 2823 } 2824 } ); 2825 2826 return filter[0]; 2827 } 2828 2829 2830 /** 2831 * Filter the table using both the global filter and column based filtering 2832 * @param {object} oSettings dataTables settings object 2833 * @param {object} oSearch search information 2834 * @param {int} [iForce] force a research of the master array (1) or not (undefined or 0) 2835 * @memberof DataTable#oApi 2836 */ 2837 function _fnFilterComplete ( oSettings, oInput, iForce ) 2838 { 2839 var oPrevSearch = oSettings.oPreviousSearch; 2840 var aoPrevSearch = oSettings.aoPreSearchCols; 2841 var fnSaveFilter = function ( oFilter ) { 2842 /* Save the filtering values */ 2843 oPrevSearch.sSearch = oFilter.sSearch; 2844 oPrevSearch.bRegex = oFilter.bRegex; 2845 oPrevSearch.bSmart = oFilter.bSmart; 2846 oPrevSearch.bCaseInsensitive = oFilter.bCaseInsensitive; 2847 }; 2848 var fnRegex = function ( o ) { 2849 // Backwards compatibility with the bEscapeRegex option 2850 return o.bEscapeRegex !== undefined ? !o.bEscapeRegex : o.bRegex; 2851 }; 2852 2853 // Resolve any column types that are unknown due to addition or invalidation 2854 // @todo As per sort - can this be moved into an event handler? 2855 _fnColumnTypes( oSettings ); 2856 2857 /* In server-side processing all filtering is done by the server, so no point hanging around here */ 2858 if ( _fnDataSource( oSettings ) != 'ssp' ) 2859 { 2860 /* Global filter */ 2861 _fnFilter( oSettings, oInput.sSearch, iForce, fnRegex(oInput), oInput.bSmart, oInput.bCaseInsensitive ); 2862 fnSaveFilter( oInput ); 2863 2864 /* Now do the individual column filter */ 2865 for ( var i=0 ; i<aoPrevSearch.length ; i++ ) 2866 { 2867 _fnFilterColumn( oSettings, aoPrevSearch[i].sSearch, i, fnRegex(aoPrevSearch[i]), 2868 aoPrevSearch[i].bSmart, aoPrevSearch[i].bCaseInsensitive ); 2869 } 2870 2871 /* Custom filtering */ 2872 _fnFilterCustom( oSettings ); 2873 } 2874 else 2875 { 2876 fnSaveFilter( oInput ); 2877 } 2878 2879 /* Tell the draw function we have been filtering */ 2880 oSettings.bFiltered = true; 2881 _fnCallbackFire( oSettings, null, 'search', [oSettings] ); 2882 } 2883 2884 2885 /** 2886 * Apply custom filtering functions 2887 * @param {object} oSettings dataTables settings object 2888 * @memberof DataTable#oApi 2889 */ 2890 function _fnFilterCustom( settings ) 2891 { 2892 var filters = DataTable.ext.search; 2893 var displayRows = settings.aiDisplay; 2894 var row, rowIdx; 2895 2896 for ( var i=0, ien=filters.length ; i<ien ; i++ ) { 2897 var rows = []; 2898 2899 // Loop over each row and see if it should be included 2900 for ( var j=0, jen=displayRows.length ; j<jen ; j++ ) { 2901 rowIdx = displayRows[ j ]; 2902 row = settings.aoData[ rowIdx ]; 2903 2904 if ( filters[i]( settings, row._aFilterData, rowIdx, row._aData, j ) ) { 2905 rows.push( rowIdx ); 2906 } 2907 } 2908 2909 // So the array reference doesn't break set the results into the 2910 // existing array 2911 displayRows.length = 0; 2912 displayRows.push.apply( displayRows, rows ); 2913 } 2914 } 2915 2916 2917 /** 2918 * Filter the table on a per-column basis 2919 * @param {object} oSettings dataTables settings object 2920 * @param {string} sInput string to filter on 2921 * @param {int} iColumn column to filter 2922 * @param {bool} bRegex treat search string as a regular expression or not 2923 * @param {bool} bSmart use smart filtering or not 2924 * @param {bool} bCaseInsensitive Do case insenstive matching or not 2925 * @memberof DataTable#oApi 2926 */ 2927 function _fnFilterColumn ( settings, searchStr, colIdx, regex, smart, caseInsensitive ) 2928 { 2929 if ( searchStr === '' ) { 2930 return; 2931 } 2932 2933 var data; 2934 var display = settings.aiDisplay; 2935 var rpSearch = _fnFilterCreateSearch( searchStr, regex, smart, caseInsensitive ); 2936 2937 for ( var i=display.length-1 ; i>=0 ; i-- ) { 2938 data = settings.aoData[ display[i] ]._aFilterData[ colIdx ]; 2939 2940 if ( ! rpSearch.test( data ) ) { 2941 display.splice( i, 1 ); 2942 } 2943 } 2944 } 2945 2946 2947 /** 2948 * Filter the data table based on user input and draw the table 2949 * @param {object} settings dataTables settings object 2950 * @param {string} input string to filter on 2951 * @param {int} force optional - force a research of the master array (1) or not (undefined or 0) 2952 * @param {bool} regex treat as a regular expression or not 2953 * @param {bool} smart perform smart filtering or not 2954 * @param {bool} caseInsensitive Do case insenstive matching or not 2955 * @memberof DataTable#oApi 2956 */ 2957 function _fnFilter( settings, input, force, regex, smart, caseInsensitive ) 2958 { 2959 var rpSearch = _fnFilterCreateSearch( input, regex, smart, caseInsensitive ); 2960 var prevSearch = settings.oPreviousSearch.sSearch; 2961 var displayMaster = settings.aiDisplayMaster; 2962 var display, invalidated, i; 2963 2964 // Need to take account of custom filtering functions - always filter 2965 if ( DataTable.ext.search.length !== 0 ) { 2966 force = true; 2967 } 2968 2969 // Check if any of the rows were invalidated 2970 invalidated = _fnFilterData( settings ); 2971 2972 // If the input is blank - we just want the full data set 2973 if ( input.length <= 0 ) { 2974 settings.aiDisplay = displayMaster.slice(); 2975 } 2976 else { 2977 // New search - start from the master array 2978 if ( invalidated || 2979 force || 2980 prevSearch.length > input.length || 2981 input.indexOf(prevSearch) !== 0 || 2982 settings.bSorted // On resort, the display master needs to be 2983 // re-filtered since indexes will have changed 2984 ) { 2985 settings.aiDisplay = displayMaster.slice(); 2986 } 2987 2988 // Search the display array 2989 display = settings.aiDisplay; 2990 2991 for ( i=display.length-1 ; i>=0 ; i-- ) { 2992 if ( ! rpSearch.test( settings.aoData[ display[i] ]._sFilterRow ) ) { 2993 display.splice( i, 1 ); 2994 } 2995 } 2996 } 2997 } 2998 2999 3000 /** 3001 * Build a regular expression object suitable for searching a table 3002 * @param {string} sSearch string to search for 3003 * @param {bool} bRegex treat as a regular expression or not 3004 * @param {bool} bSmart perform smart filtering or not 3005 * @param {bool} bCaseInsensitive Do case insensitive matching or not 3006 * @returns {RegExp} constructed object 3007 * @memberof DataTable#oApi 3008 */ 3009 function _fnFilterCreateSearch( search, regex, smart, caseInsensitive ) 3010 { 3011 search = regex ? 3012 search : 3013 _fnEscapeRegex( search ); 3014 3015 if ( smart ) { 3016 /* For smart filtering we want to allow the search to work regardless of 3017 * word order. We also want double quoted text to be preserved, so word 3018 * order is important - a la google. So this is what we want to 3019 * generate: 3020 * 3021 * ^(?=.*?\bone\b)(?=.*?\btwo three\b)(?=.*?\bfour\b).*$ 3022 */ 3023 var a = $.map( search.match( /"[^"]+"|[^ ]+/g ) || [''], function ( word ) { 3024 if ( word.charAt(0) === '"' ) { 3025 var m = word.match( /^"(.*)"$/ ); 3026 word = m ? m[1] : word; 3027 } 3028 3029 return word.replace('"', ''); 3030 } ); 3031 3032 search = '^(?=.*?'+a.join( ')(?=.*?' )+').*$'; 3033 } 3034 3035 return new RegExp( search, caseInsensitive ? 'i' : '' ); 3036 } 3037 3038 3039 /** 3040 * Escape a string such that it can be used in a regular expression 3041 * @param {string} sVal string to escape 3042 * @returns {string} escaped string 3043 * @memberof DataTable#oApi 3044 */ 3045 function _fnEscapeRegex ( sVal ) 3046 { 3047 return sVal.replace( _re_escape_regex, '\\$1' ); 3048 } 3049 3050 3051 3052 var __filter_div = $('<div>')[0]; 3053 var __filter_div_textContent = __filter_div.textContent !== undefined; 3054 3055 // Update the filtering data for each row if needed (by invalidation or first run) 3056 function _fnFilterData ( settings ) 3057 { 3058 var columns = settings.aoColumns; 3059 var column; 3060 var i, j, ien, jen, filterData, cellData, row; 3061 var fomatters = DataTable.ext.type.search; 3062 var wasInvalidated = false; 3063 3064 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 3065 row = settings.aoData[i]; 3066 3067 if ( ! row._aFilterData ) { 3068 filterData = []; 3069 3070 for ( j=0, jen=columns.length ; j<jen ; j++ ) { 3071 column = columns[j]; 3072 3073 if ( column.bSearchable ) { 3074 cellData = _fnGetCellData( settings, i, j, 'filter' ); 3075 3076 if ( fomatters[ column.sType ] ) { 3077 cellData = fomatters[ column.sType ]( cellData ); 3078 } 3079 3080 // Search in DataTables 1.10 is string based. In 1.11 this 3081 // should be altered to also allow strict type checking. 3082 if ( cellData === null ) { 3083 cellData = ''; 3084 } 3085 3086 if ( typeof cellData !== 'string' && cellData.toString ) { 3087 cellData = cellData.toString(); 3088 } 3089 } 3090 else { 3091 cellData = ''; 3092 } 3093 3094 // If it looks like there is an HTML entity in the string, 3095 // attempt to decode it so sorting works as expected. Note that 3096 // we could use a single line of jQuery to do this, but the DOM 3097 // method used here is much faster http://jsperf.com/html-decode 3098 if ( cellData.indexOf && cellData.indexOf('&') !== -1 ) { 3099 __filter_div.innerHTML = cellData; 3100 cellData = __filter_div_textContent ? 3101 __filter_div.textContent : 3102 __filter_div.innerText; 3103 } 3104 3105 if ( cellData.replace ) { 3106 cellData = cellData.replace(/[\r\n]/g, ''); 3107 } 3108 3109 filterData.push( cellData ); 3110 } 3111 3112 row._aFilterData = filterData; 3113 row._sFilterRow = filterData.join(' '); 3114 wasInvalidated = true; 3115 } 3116 } 3117 3118 return wasInvalidated; 3119 } 3120 3121 3122 /** 3123 * Convert from the internal Hungarian notation to camelCase for external 3124 * interaction 3125 * @param {object} obj Object to convert 3126 * @returns {object} Inverted object 3127 * @memberof DataTable#oApi 3128 */ 3129 function _fnSearchToCamel ( obj ) 3130 { 3131 return { 3132 search: obj.sSearch, 3133 smart: obj.bSmart, 3134 regex: obj.bRegex, 3135 caseInsensitive: obj.bCaseInsensitive 3136 }; 3137 } 3138 3139 3140 3141 /** 3142 * Convert from camelCase notation to the internal Hungarian. We could use the 3143 * Hungarian convert function here, but this is cleaner 3144 * @param {object} obj Object to convert 3145 * @returns {object} Inverted object 3146 * @memberof DataTable#oApi 3147 */ 3148 function _fnSearchToHung ( obj ) 3149 { 3150 return { 3151 sSearch: obj.search, 3152 bSmart: obj.smart, 3153 bRegex: obj.regex, 3154 bCaseInsensitive: obj.caseInsensitive 3155 }; 3156 } 3157 3158 /** 3159 * Generate the node required for the info display 3160 * @param {object} oSettings dataTables settings object 3161 * @returns {node} Information element 3162 * @memberof DataTable#oApi 3163 */ 3164 function _fnFeatureHtmlInfo ( settings ) 3165 { 3166 var 3167 tid = settings.sTableId, 3168 nodes = settings.aanFeatures.i, 3169 n = $('<div/>', { 3170 'class': settings.oClasses.sInfo, 3171 'id': ! nodes ? tid+'_info' : null 3172 } ); 3173 3174 if ( ! nodes ) { 3175 // Update display on each draw 3176 settings.aoDrawCallback.push( { 3177 "fn": _fnUpdateInfo, 3178 "sName": "information" 3179 } ); 3180 3181 n 3182 .attr( 'role', 'status' ) 3183 .attr( 'aria-live', 'polite' ); 3184 3185 // Table is described by our info div 3186 $(settings.nTable).attr( 'aria-describedby', tid+'_info' ); 3187 } 3188 3189 return n[0]; 3190 } 3191 3192 3193 /** 3194 * Update the information elements in the display 3195 * @param {object} settings dataTables settings object 3196 * @memberof DataTable#oApi 3197 */ 3198 function _fnUpdateInfo ( settings ) 3199 { 3200 /* Show information about the table */ 3201 var nodes = settings.aanFeatures.i; 3202 if ( nodes.length === 0 ) { 3203 return; 3204 } 3205 3206 var 3207 lang = settings.oLanguage, 3208 start = settings._iDisplayStart+1, 3209 end = settings.fnDisplayEnd(), 3210 max = settings.fnRecordsTotal(), 3211 total = settings.fnRecordsDisplay(), 3212 out = total ? 3213 lang.sInfo : 3214 lang.sInfoEmpty; 3215 3216 if ( total !== max ) { 3217 /* Record set after filtering */ 3218 out += ' ' + lang.sInfoFiltered; 3219 } 3220 3221 // Convert the macros 3222 out += lang.sInfoPostFix; 3223 out = _fnInfoMacros( settings, out ); 3224 3225 var callback = lang.fnInfoCallback; 3226 if ( callback !== null ) { 3227 out = callback.call( settings.oInstance, 3228 settings, start, end, max, total, out 3229 ); 3230 } 3231 3232 $(nodes).html( out ); 3233 } 3234 3235 3236 function _fnInfoMacros ( settings, str ) 3237 { 3238 // When infinite scrolling, we are always starting at 1. _iDisplayStart is used only 3239 // internally 3240 var 3241 formatter = settings.fnFormatNumber, 3242 start = settings._iDisplayStart+1, 3243 len = settings._iDisplayLength, 3244 vis = settings.fnRecordsDisplay(), 3245 all = len === -1; 3246 3247 return str. 3248 replace(/_START_/g, formatter.call( settings, start ) ). 3249 replace(/_END_/g, formatter.call( settings, settings.fnDisplayEnd() ) ). 3250 replace(/_MAX_/g, formatter.call( settings, settings.fnRecordsTotal() ) ). 3251 replace(/_TOTAL_/g, formatter.call( settings, vis ) ). 3252 replace(/_PAGE_/g, formatter.call( settings, all ? 1 : Math.ceil( start / len ) ) ). 3253 replace(/_PAGES_/g, formatter.call( settings, all ? 1 : Math.ceil( vis / len ) ) ); 3254 } 3255 3256 3257 3258 /** 3259 * Draw the table for the first time, adding all required features 3260 * @param {object} settings dataTables settings object 3261 * @memberof DataTable#oApi 3262 */ 3263 function _fnInitialise ( settings ) 3264 { 3265 var i, iLen, iAjaxStart=settings.iInitDisplayStart; 3266 var columns = settings.aoColumns, column; 3267 var features = settings.oFeatures; 3268 3269 /* Ensure that the table data is fully initialised */ 3270 if ( ! settings.bInitialised ) { 3271 setTimeout( function(){ _fnInitialise( settings ); }, 200 ); 3272 return; 3273 } 3274 3275 /* Show the display HTML options */ 3276 _fnAddOptionsHtml( settings ); 3277 3278 /* Build and draw the header / footer for the table */ 3279 _fnBuildHead( settings ); 3280 _fnDrawHead( settings, settings.aoHeader ); 3281 _fnDrawHead( settings, settings.aoFooter ); 3282 3283 /* Okay to show that something is going on now */ 3284 _fnProcessingDisplay( settings, true ); 3285 3286 /* Calculate sizes for columns */ 3287 if ( features.bAutoWidth ) { 3288 _fnCalculateColumnWidths( settings ); 3289 } 3290 3291 for ( i=0, iLen=columns.length ; i<iLen ; i++ ) { 3292 column = columns[i]; 3293 3294 if ( column.sWidth ) { 3295 column.nTh.style.width = _fnStringToCss( column.sWidth ); 3296 } 3297 } 3298 3299 // If there is default sorting required - let's do it. The sort function 3300 // will do the drawing for us. Otherwise we draw the table regardless of the 3301 // Ajax source - this allows the table to look initialised for Ajax sourcing 3302 // data (show 'loading' message possibly) 3303 _fnReDraw( settings ); 3304 3305 // Server-side processing init complete is done by _fnAjaxUpdateDraw 3306 var dataSrc = _fnDataSource( settings ); 3307 if ( dataSrc != 'ssp' ) { 3308 // if there is an ajax source load the data 3309 if ( dataSrc == 'ajax' ) { 3310 _fnBuildAjax( settings, [], function(json) { 3311 var aData = _fnAjaxDataSrc( settings, json ); 3312 3313 // Got the data - add it to the table 3314 for ( i=0 ; i<aData.length ; i++ ) { 3315 _fnAddData( settings, aData[i] ); 3316 } 3317 3318 // Reset the init display for cookie saving. We've already done 3319 // a filter, and therefore cleared it before. So we need to make 3320 // it appear 'fresh' 3321 settings.iInitDisplayStart = iAjaxStart; 3322 3323 _fnReDraw( settings ); 3324 3325 _fnProcessingDisplay( settings, false ); 3326 _fnInitComplete( settings, json ); 3327 }, settings ); 3328 } 3329 else { 3330 _fnProcessingDisplay( settings, false ); 3331 _fnInitComplete( settings ); 3332 } 3333 } 3334 } 3335 3336 3337 /** 3338 * Draw the table for the first time, adding all required features 3339 * @param {object} oSettings dataTables settings object 3340 * @param {object} [json] JSON from the server that completed the table, if using Ajax source 3341 * with client-side processing (optional) 3342 * @memberof DataTable#oApi 3343 */ 3344 function _fnInitComplete ( settings, json ) 3345 { 3346 settings._bInitComplete = true; 3347 3348 // On an Ajax load we now have data and therefore want to apply the column 3349 // sizing 3350 if ( json ) { 3351 _fnAdjustColumnSizing( settings ); 3352 } 3353 3354 _fnCallbackFire( settings, 'aoInitComplete', 'init', [settings, json] ); 3355 } 3356 3357 3358 function _fnLengthChange ( settings, val ) 3359 { 3360 var len = parseInt( val, 10 ); 3361 settings._iDisplayLength = len; 3362 3363 _fnLengthOverflow( settings ); 3364 3365 // Fire length change event 3366 _fnCallbackFire( settings, null, 'length', [settings, len] ); 3367 } 3368 3369 3370 /** 3371 * Generate the node required for user display length changing 3372 * @param {object} settings dataTables settings object 3373 * @returns {node} Display length feature node 3374 * @memberof DataTable#oApi 3375 */ 3376 function _fnFeatureHtmlLength ( settings ) 3377 { 3378 var 3379 classes = settings.oClasses, 3380 tableId = settings.sTableId, 3381 menu = settings.aLengthMenu, 3382 d2 = $.isArray( menu[0] ), 3383 lengths = d2 ? menu[0] : menu, 3384 language = d2 ? menu[1] : menu; 3385 3386 var select = $('<select/>', { 3387 'name': tableId+'_length', 3388 'aria-controls': tableId, 3389 'class': classes.sLengthSelect 3390 } ); 3391 3392 for ( var i=0, ien=lengths.length ; i<ien ; i++ ) { 3393 select[0][ i ] = new Option( language[i], lengths[i] ); 3394 } 3395 3396 var div = $('<div><label/></div>').addClass( classes.sLength ); 3397 if ( ! settings.aanFeatures.l ) { 3398 div[0].id = tableId+'_length'; 3399 } 3400 3401 div.children().append( 3402 settings.oLanguage.sLengthMenu.replace( '_MENU_', select[0].outerHTML ) 3403 ); 3404 3405 // Can't use `select` variable as user might provide their own and the 3406 // reference is broken by the use of outerHTML 3407 $('select', div) 3408 .val( settings._iDisplayLength ) 3409 .bind( 'change.DT', function(e) { 3410 _fnLengthChange( settings, $(this).val() ); 3411 _fnDraw( settings ); 3412 } ); 3413 3414 // Update node value whenever anything changes the table's length 3415 $(settings.nTable).bind( 'length.dt.DT', function (e, s, len) { 3416 if ( settings === s ) { 3417 $('select', div).val( len ); 3418 } 3419 } ); 3420 3421 return div[0]; 3422 } 3423 3424 3425 3426 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 3427 * Note that most of the paging logic is done in 3428 * DataTable.ext.pager 3429 */ 3430 3431 /** 3432 * Generate the node required for default pagination 3433 * @param {object} oSettings dataTables settings object 3434 * @returns {node} Pagination feature node 3435 * @memberof DataTable#oApi 3436 */ 3437 function _fnFeatureHtmlPaginate ( settings ) 3438 { 3439 var 3440 type = settings.sPaginationType, 3441 plugin = DataTable.ext.pager[ type ], 3442 modern = typeof plugin === 'function', 3443 redraw = function( settings ) { 3444 _fnDraw( settings ); 3445 }, 3446 node = $('<div/>').addClass( settings.oClasses.sPaging + type )[0], 3447 features = settings.aanFeatures; 3448 3449 if ( ! modern ) { 3450 plugin.fnInit( settings, node, redraw ); 3451 } 3452 3453 /* Add a draw callback for the pagination on first instance, to update the paging display */ 3454 if ( ! features.p ) 3455 { 3456 node.id = settings.sTableId+'_paginate'; 3457 3458 settings.aoDrawCallback.push( { 3459 "fn": function( settings ) { 3460 if ( modern ) { 3461 var 3462 start = settings._iDisplayStart, 3463 len = settings._iDisplayLength, 3464 visRecords = settings.fnRecordsDisplay(), 3465 all = len === -1, 3466 page = all ? 0 : Math.ceil( start / len ), 3467 pages = all ? 1 : Math.ceil( visRecords / len ), 3468 buttons = plugin(page, pages), 3469 i, ien; 3470 3471 for ( i=0, ien=features.p.length ; i<ien ; i++ ) { 3472 _fnRenderer( settings, 'pageButton' )( 3473 settings, features.p[i], i, buttons, page, pages 3474 ); 3475 } 3476 } 3477 else { 3478 plugin.fnUpdate( settings, redraw ); 3479 } 3480 }, 3481 "sName": "pagination" 3482 } ); 3483 } 3484 3485 return node; 3486 } 3487 3488 3489 /** 3490 * Alter the display settings to change the page 3491 * @param {object} settings DataTables settings object 3492 * @param {string|int} action Paging action to take: "first", "previous", 3493 * "next" or "last" or page number to jump to (integer) 3494 * @param [bool] redraw Automatically draw the update or not 3495 * @returns {bool} true page has changed, false - no change 3496 * @memberof DataTable#oApi 3497 */ 3498 function _fnPageChange ( settings, action, redraw ) 3499 { 3500 var 3501 start = settings._iDisplayStart, 3502 len = settings._iDisplayLength, 3503 records = settings.fnRecordsDisplay(); 3504 3505 if ( records === 0 || len === -1 ) 3506 { 3507 start = 0; 3508 } 3509 else if ( typeof action === "number" ) 3510 { 3511 start = action * len; 3512 3513 if ( start > records ) 3514 { 3515 start = 0; 3516 } 3517 } 3518 else if ( action == "first" ) 3519 { 3520 start = 0; 3521 } 3522 else if ( action == "previous" ) 3523 { 3524 start = len >= 0 ? 3525 start - len : 3526 0; 3527 3528 if ( start < 0 ) 3529 { 3530 start = 0; 3531 } 3532 } 3533 else if ( action == "next" ) 3534 { 3535 if ( start + len < records ) 3536 { 3537 start += len; 3538 } 3539 } 3540 else if ( action == "last" ) 3541 { 3542 start = Math.floor( (records-1) / len) * len; 3543 } 3544 else 3545 { 3546 _fnLog( settings, 0, "Unknown paging action: "+action, 5 ); 3547 } 3548 3549 var changed = settings._iDisplayStart !== start; 3550 settings._iDisplayStart = start; 3551 3552 if ( changed ) { 3553 _fnCallbackFire( settings, null, 'page', [settings] ); 3554 3555 if ( redraw ) { 3556 _fnDraw( settings ); 3557 } 3558 } 3559 3560 return changed; 3561 } 3562 3563 3564 3565 /** 3566 * Generate the node required for the processing node 3567 * @param {object} settings dataTables settings object 3568 * @returns {node} Processing element 3569 * @memberof DataTable#oApi 3570 */ 3571 function _fnFeatureHtmlProcessing ( settings ) 3572 { 3573 return $('<div/>', { 3574 'id': ! settings.aanFeatures.r ? settings.sTableId+'_processing' : null, 3575 'class': settings.oClasses.sProcessing 3576 } ) 3577 .html( settings.oLanguage.sProcessing ) 3578 .insertBefore( settings.nTable )[0]; 3579 } 3580 3581 3582 /** 3583 * Display or hide the processing indicator 3584 * @param {object} settings dataTables settings object 3585 * @param {bool} show Show the processing indicator (true) or not (false) 3586 * @memberof DataTable#oApi 3587 */ 3588 function _fnProcessingDisplay ( settings, show ) 3589 { 3590 if ( settings.oFeatures.bProcessing ) { 3591 $(settings.aanFeatures.r).css( 'display', show ? 'block' : 'none' ); 3592 } 3593 3594 _fnCallbackFire( settings, null, 'processing', [settings, show] ); 3595 } 3596 3597 /** 3598 * Add any control elements for the table - specifically scrolling 3599 * @param {object} settings dataTables settings object 3600 * @returns {node} Node to add to the DOM 3601 * @memberof DataTable#oApi 3602 */ 3603 function _fnFeatureHtmlTable ( settings ) 3604 { 3605 var table = $(settings.nTable); 3606 3607 // Add the ARIA grid role to the table 3608 table.attr( 'role', 'grid' ); 3609 3610 // Scrolling from here on in 3611 var scroll = settings.oScroll; 3612 3613 if ( scroll.sX === '' && scroll.sY === '' ) { 3614 return settings.nTable; 3615 } 3616 3617 var scrollX = scroll.sX; 3618 var scrollY = scroll.sY; 3619 var classes = settings.oClasses; 3620 var caption = table.children('caption'); 3621 var captionSide = caption.length ? caption[0]._captionSide : null; 3622 var headerClone = $( table[0].cloneNode(false) ); 3623 var footerClone = $( table[0].cloneNode(false) ); 3624 var footer = table.children('tfoot'); 3625 var _div = '<div/>'; 3626 var size = function ( s ) { 3627 return !s ? null : _fnStringToCss( s ); 3628 }; 3629 3630 // This is fairly messy, but with x scrolling enabled, if the table has a 3631 // width attribute, regardless of any width applied using the column width 3632 // options, the browser will shrink or grow the table as needed to fit into 3633 // that 100%. That would make the width options useless. So we remove it. 3634 // This is okay, under the assumption that width:100% is applied to the 3635 // table in CSS (it is in the default stylesheet) which will set the table 3636 // width as appropriate (the attribute and css behave differently...) 3637 if ( scroll.sX && table.attr('width') === '100%' ) { 3638 table.removeAttr('width'); 3639 } 3640 3641 if ( ! footer.length ) { 3642 footer = null; 3643 } 3644 3645 /* 3646 * The HTML structure that we want to generate in this function is: 3647 * div - scroller 3648 * div - scroll head 3649 * div - scroll head inner 3650 * table - scroll head table 3651 * thead - thead 3652 * div - scroll body 3653 * table - table (master table) 3654 * thead - thead clone for sizing 3655 * tbody - tbody 3656 * div - scroll foot 3657 * div - scroll foot inner 3658 * table - scroll foot table 3659 * tfoot - tfoot 3660 */ 3661 var scroller = $( _div, { 'class': classes.sScrollWrapper } ) 3662 .append( 3663 $(_div, { 'class': classes.sScrollHead } ) 3664 .css( { 3665 overflow: 'hidden', 3666 position: 'relative', 3667 border: 0, 3668 width: scrollX ? size(scrollX) : '100%' 3669 } ) 3670 .append( 3671 $(_div, { 'class': classes.sScrollHeadInner } ) 3672 .css( { 3673 'box-sizing': 'content-box', 3674 width: scroll.sXInner || '100%' 3675 } ) 3676 .append( 3677 headerClone 3678 .removeAttr('id') 3679 .css( 'margin-left', 0 ) 3680 .append( captionSide === 'top' ? caption : null ) 3681 .append( 3682 table.children('thead') 3683 ) 3684 ) 3685 ) 3686 ) 3687 .append( 3688 $(_div, { 'class': classes.sScrollBody } ) 3689 .css( { 3690 overflow: 'auto', 3691 height: size( scrollY ), 3692 width: size( scrollX ) 3693 } ) 3694 .append( table ) 3695 ); 3696 3697 if ( footer ) { 3698 scroller.append( 3699 $(_div, { 'class': classes.sScrollFoot } ) 3700 .css( { 3701 overflow: 'hidden', 3702 border: 0, 3703 width: scrollX ? size(scrollX) : '100%' 3704 } ) 3705 .append( 3706 $(_div, { 'class': classes.sScrollFootInner } ) 3707 .append( 3708 footerClone 3709 .removeAttr('id') 3710 .css( 'margin-left', 0 ) 3711 .append( captionSide === 'bottom' ? caption : null ) 3712 .append( 3713 table.children('tfoot') 3714 ) 3715 ) 3716 ) 3717 ); 3718 } 3719 3720 var children = scroller.children(); 3721 var scrollHead = children[0]; 3722 var scrollBody = children[1]; 3723 var scrollFoot = footer ? children[2] : null; 3724 3725 // When the body is scrolled, then we also want to scroll the headers 3726 if ( scrollX ) { 3727 $(scrollBody).on( 'scroll.DT', function (e) { 3728 var scrollLeft = this.scrollLeft; 3729 3730 scrollHead.scrollLeft = scrollLeft; 3731 3732 if ( footer ) { 3733 scrollFoot.scrollLeft = scrollLeft; 3734 } 3735 } ); 3736 } 3737 3738 settings.nScrollHead = scrollHead; 3739 settings.nScrollBody = scrollBody; 3740 settings.nScrollFoot = scrollFoot; 3741 3742 // On redraw - align columns 3743 settings.aoDrawCallback.push( { 3744 "fn": _fnScrollDraw, 3745 "sName": "scrolling" 3746 } ); 3747 3748 return scroller[0]; 3749 } 3750 3751 3752 3753 /** 3754 * Update the header, footer and body tables for resizing - i.e. column 3755 * alignment. 3756 * 3757 * Welcome to the most horrible function DataTables. The process that this 3758 * function follows is basically: 3759 * 1. Re-create the table inside the scrolling div 3760 * 2. Take live measurements from the DOM 3761 * 3. Apply the measurements to align the columns 3762 * 4. Clean up 3763 * 3764 * @param {object} settings dataTables settings object 3765 * @memberof DataTable#oApi 3766 */ 3767 function _fnScrollDraw ( settings ) 3768 { 3769 // Given that this is such a monster function, a lot of variables are use 3770 // to try and keep the minimised size as small as possible 3771 var 3772 scroll = settings.oScroll, 3773 scrollX = scroll.sX, 3774 scrollXInner = scroll.sXInner, 3775 scrollY = scroll.sY, 3776 barWidth = scroll.iBarWidth, 3777 divHeader = $(settings.nScrollHead), 3778 divHeaderStyle = divHeader[0].style, 3779 divHeaderInner = divHeader.children('div'), 3780 divHeaderInnerStyle = divHeaderInner[0].style, 3781 divHeaderTable = divHeaderInner.children('table'), 3782 divBodyEl = settings.nScrollBody,
3783 divBody = $(divBodyEl), 3784 divBodyStyle = divBodyEl.style, 3785 divFooter = $(settings.nScrollFoot), 3786 divFooterInner = divFooter.children('div'), 3787 divFooterTable = divFooterInner.children('table'), 3788 header = $(settings.nTHead), 3789 table = $(settings.nTable), 3790 tableEl = table[0], 3791 tableStyle = tableEl.style, 3792 footer = settings.nTFoot ? $(settings.nTFoot) : null, 3793 browser = settings.oBrowser, 3794 ie67 = browser.bScrollOversize, 3795 headerTrgEls, footerTrgEls, 3796 headerSrcEls, footerSrcEls, 3797 headerCopy, footerCopy, 3798 headerWidths=[], footerWidths=[], 3799 headerContent=[], 3800 idx, correction, sanityWidth, 3801 zeroOut = function(nSizer) { 3802 var style = nSizer.style; 3803 style.paddingTop = "0"; 3804 style.paddingBottom = "0"; 3805 style.borderTopWidth = "0"; 3806 style.borderBottomWidth = "0"; 3807 style.height = 0; 3808 }; 3809 3810 /* 3811 * 1. Re-create the table inside the scrolling div 3812 */ 3813 3814 // Remove the old minimised thead and tfoot elements in the inner table 3815 table.children('thead, tfoot').remove(); 3816 3817 // Clone the current header and footer elements and then place it into the inner table 3818 headerCopy = header.clone().prependTo( table ); 3819 headerTrgEls = header.find('tr'); // original header is in its own table 3820 headerSrcEls = headerCopy.find('tr'); 3821 headerCopy.find('th, td').removeAttr('tabindex'); 3822 3823 if ( footer ) { 3824 footerCopy = footer.clone().prependTo( table ); 3825 footerTrgEls = footer.find('tr'); // the original tfoot is in its own table and must be sized 3826 footerSrcEls = footerCopy.find('tr'); 3827 } 3828 3829 3830 /* 3831 * 2. Take live measurements from the DOM - do not alter the DOM itself! 3832 */ 3833 3834 // Remove old sizing and apply the calculated column widths 3835 // Get the unique column headers in the newly created (cloned) header. We want to apply the 3836 // calculated sizes to this header 3837 if ( ! scrollX ) 3838 { 3839 divBodyStyle.width = '100%'; 3840 divHeader[0].style.width = '100%'; 3841 } 3842 3843 $.each( _fnGetUniqueThs( settings, headerCopy ), function ( i, el ) { 3844 idx = _fnVisibleToColumnIndex( settings, i ); 3845 el.style.width = settings.aoColumns[idx].sWidth; 3846 } ); 3847 3848 if ( footer ) { 3849 _fnApplyToChildren( function(n) { 3850 n.style.width = ""; 3851 }, footerSrcEls ); 3852 } 3853 3854 // If scroll collapse is enabled, when we put the headers back into the body for sizing, we 3855 // will end up forcing the scrollbar to appear, making our measurements wrong for when we 3856 // then hide it (end of this function), so add the header height to the body scroller. 3857 if ( scroll.bCollapse && scrollY !== "" ) { 3858 divBodyStyle.height = (divBody[0].offsetHeight + header[0].offsetHeight)+"px"; 3859 } 3860 3861 // Size the table as a whole 3862 sanityWidth = table.outerWidth(); 3863 if ( scrollX === "" ) { 3864 // No x scrolling 3865 tableStyle.width = "100%"; 3866 3867 // IE7 will make the width of the table when 100% include the scrollbar 3868 // - which is shouldn't. When there is a scrollbar we need to take this 3869 // into account. 3870 if ( ie67 && (table.find('tbody').height() > divBodyEl.offsetHeight || 3871 divBody.css('overflow-y') == "scroll") 3872 ) { 3873 tableStyle.width = _fnStringToCss( table.outerWidth() - barWidth); 3874 } 3875 } 3876 else 3877 { 3878 // x scrolling 3879 if ( scrollXInner !== "" ) { 3880 // x scroll inner has been given - use it 3881 tableStyle.width = _fnStringToCss(scrollXInner); 3882 } 3883 else if ( sanityWidth == divBody.width() && divBody.height() < table.height() ) { 3884 // There is y-scrolling - try to take account of the y scroll bar 3885 tableStyle.width = _fnStringToCss( sanityWidth-barWidth ); 3886 if ( table.outerWidth() > sanityWidth-barWidth ) { 3887 // Not possible to take account of it 3888 tableStyle.width = _fnStringToCss( sanityWidth ); 3889 } 3890 } 3891 else { 3892 // When all else fails 3893 tableStyle.width = _fnStringToCss( sanityWidth ); 3894 } 3895 } 3896 3897 // Recalculate the sanity width - now that we've applied the required width, 3898 // before it was a temporary variable. This is required because the column 3899 // width calculation is done before this table DOM is created. 3900 sanityWidth = table.outerWidth(); 3901 3902 // Hidden header should have zero height, so remove padding and borders. Then 3903 // set the width based on the real headers 3904 3905 // Apply all styles in one pass 3906 _fnApplyToChildren( zeroOut, headerSrcEls ); 3907 3908 // Read all widths in next pass 3909 _fnApplyToChildren( function(nSizer) { 3910 headerContent.push( nSizer.innerHTML ); 3911 headerWidths.push( _fnStringToCss( $(nSizer).css('width') ) ); 3912 }, headerSrcEls ); 3913 3914 // Apply all widths in final pass 3915 _fnApplyToChildren( function(nToSize, i) { 3916 nToSize.style.width = headerWidths[i]; 3917 }, headerTrgEls ); 3918 3919 $(headerSrcEls).height(0); 3920 3921 /* Same again with the footer if we have one */ 3922 if ( footer ) 3923 { 3924 _fnApplyToChildren( zeroOut, footerSrcEls ); 3925 3926 _fnApplyToChildren( function(nSizer) {
vendor: 6,846 bytes, lines 3927-4145
3927 footerWidths.push( _fnStringToCss( $(nSizer).css('width') ) ); 3928 }, footerSrcEls ); 3929 3930 _fnApplyToChildren( function(nToSize, i) { 3931 nToSize.style.width = footerWidths[i]; 3932 }, footerTrgEls ); 3933 3934 $(footerSrcEls).height(0); 3935 } 3936 3937 3938 /* 3939 * 3. Apply the measurements 3940 */ 3941 3942 // "Hide" the header and footer that we used for the sizing. We need to keep 3943 // the content of the cell so that the width applied to the header and body 3944 // both match, but we want to hide it completely. We want to also fix their 3945 // width to what they currently are 3946 _fnApplyToChildren( function(nSizer, i) { 3947 nSizer.innerHTML = '<div class="dataTables_sizing" style="height:0;overflow:hidden;">'+headerContent[i]+'</div>'; 3948 nSizer.style.width = headerWidths[i]; 3949 }, headerSrcEls ); 3950 3951 if ( footer ) 3952 { 3953 _fnApplyToChildren( function(nSizer, i) { 3954 nSizer.innerHTML = ""; 3955 nSizer.style.width = footerWidths[i]; 3956 }, footerSrcEls ); 3957 } 3958 3959 // Sanity check that the table is of a sensible width. If not then we are going to get 3960 // misalignment - try to prevent this by not allowing the table to shrink below its min width 3961 if ( table.outerWidth() < sanityWidth ) 3962 { 3963 // The min width depends upon if we have a vertical scrollbar visible or not */ 3964 correction = ((divBodyEl.scrollHeight > divBodyEl.offsetHeight || 3965 divBody.css('overflow-y') == "scroll")) ? 3966 sanityWidth+barWidth : 3967 sanityWidth; 3968 3969 // IE6/7 are a law unto themselves... 3970 if ( ie67 && (divBodyEl.scrollHeight > 3971 divBodyEl.offsetHeight || divBody.css('overflow-y') == "scroll") 3972 ) { 3973 tableStyle.width = _fnStringToCss( correction-barWidth ); 3974 } 3975 3976 // And give the user a warning that we've stopped the table getting too small 3977 if ( scrollX === "" || scrollXInner !== "" ) { 3978 _fnLog( settings, 1, 'Possible column misalignment', 6 ); 3979 } 3980 } 3981 else 3982 { 3983 correction = '100%'; 3984 } 3985 3986 // Apply to the container elements 3987 divBodyStyle.width = _fnStringToCss( correction ); 3988 divHeaderStyle.width = _fnStringToCss( correction ); 3989 3990 if ( footer ) { 3991 settings.nScrollFoot.style.width = _fnStringToCss( correction ); 3992 } 3993 3994 3995 /* 3996 * 4. Clean up 3997 */ 3998 if ( ! scrollY ) { 3999 /* IE7< puts a vertical scrollbar in place (when it shouldn't be) due to subtracting 4000 * the scrollbar height from the visible display, rather than adding it on. We need to 4001 * set the height in order to sort this. Don't want to do it in any other browsers. 4002 */ 4003 if ( ie67 ) { 4004 divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+barWidth ); 4005 } 4006 } 4007 4008 if ( scrollY && scroll.bCollapse ) { 4009 divBodyStyle.height = _fnStringToCss( scrollY ); 4010 4011 var iExtra = (scrollX && tableEl.offsetWidth > divBodyEl.offsetWidth) ? 4012 barWidth : 4013 0; 4014 4015 if ( tableEl.offsetHeight < divBodyEl.offsetHeight ) { 4016 divBodyStyle.height = _fnStringToCss( tableEl.offsetHeight+iExtra ); 4017 } 4018 } 4019 4020 /* Finally set the width's of the header and footer tables */ 4021 var iOuterWidth = table.outerWidth(); 4022 divHeaderTable[0].style.width = _fnStringToCss( iOuterWidth ); 4023 divHeaderInnerStyle.width = _fnStringToCss( iOuterWidth ); 4024 4025 // Figure out if there are scrollbar present - if so then we need a the header and footer to 4026 // provide a bit more space to allow "overflow" scrolling (i.e. past the scrollbar) 4027 var bScrolling = table.height() > divBodyEl.clientHeight || divBody.css('overflow-y') == "scroll"; 4028 var padding = 'padding' + (browser.bScrollbarLeft ? 'Left' : 'Right' ); 4029 divHeaderInnerStyle[ padding ] = bScrolling ? barWidth+"px" : "0px"; 4030 4031 if ( footer ) { 4032 divFooterTable[0].style.width = _fnStringToCss( iOuterWidth ); 4033 divFooterInner[0].style.width = _fnStringToCss( iOuterWidth ); 4034 divFooterInner[0].style[padding] = bScrolling ? barWidth+"px" : "0px"; 4035 } 4036 4037 /* Adjust the position of the header in case we loose the y-scrollbar */ 4038 divBody.scroll(); 4039 4040 // If sorting or filtering has occurred, jump the scrolling back to the top 4041 // only if we aren't holding the position 4042 if ( (settings.bSorted || settings.bFiltered) && ! settings._drawHold ) { 4043 divBodyEl.scrollTop = 0; 4044 } 4045 } 4046 4047 4048 4049 /** 4050 * Apply a given function to the display child nodes of an element array (typically 4051 * TD children of TR rows 4052 * @param {function} fn Method to apply to the objects 4053 * @param array {nodes} an1 List of elements to look through for display children 4054 * @param array {nodes} an2 Another list (identical structure to the first) - optional 4055 * @memberof DataTable#oApi 4056 */ 4057 function _fnApplyToChildren( fn, an1, an2 ) 4058 { 4059 var index=0, i=0, iLen=an1.length; 4060 var nNode1, nNode2; 4061 4062 while ( i < iLen ) { 4063 nNode1 = an1[i].firstChild; 4064 nNode2 = an2 ? an2[i].firstChild : null; 4065 4066 while ( nNode1 ) { 4067 if ( nNode1.nodeType === 1 ) { 4068 if ( an2 ) { 4069 fn( nNode1, nNode2, index ); 4070 } 4071 else { 4072 fn( nNode1, index ); 4073 } 4074 4075 index++; 4076 } 4077 4078 nNode1 = nNode1.nextSibling; 4079 nNode2 = an2 ? nNode2.nextSibling : null; 4080 } 4081 4082 i++; 4083 } 4084 } 4085 4086 4087 4088 var __re_html_remove = /<.*?>/g; 4089 4090 4091 /** 4092 * Calculate the width of columns for the table 4093 * @param {object} oSettings dataTables settings object 4094 * @memberof DataTable#oApi 4095 */ 4096 function _fnCalculateColumnWidths ( oSettings ) 4097 { 4098 var 4099 table = oSettings.nTable, 4100 columns = oSettings.aoColumns, 4101 scroll = oSettings.oScroll, 4102 scrollY = scroll.sY, 4103 scrollX = scroll.sX, 4104 scrollXInner = scroll.sXInner, 4105 columnCount = columns.length, 4106 visibleColumns = _fnGetColumns( oSettings, 'bVisible' ), 4107 headerCells = $('th', oSettings.nTHead), 4108 tableWidthAttr = table.getAttribute('width'), // from DOM element 4109 tableContainer = table.parentNode, 4110 userInputs = false, 4111 i, column, columnIdx, width, outerWidth; 4112 4113 var styleWidth = table.style.width; 4114 if ( styleWidth && styleWidth.indexOf('%') !== -1 ) { 4115 tableWidthAttr = styleWidth; 4116 } 4117 4118 /* Convert any user input sizes into pixel sizes */ 4119 for ( i=0 ; i<visibleColumns.length ; i++ ) { 4120 column = columns[ visibleColumns[i] ]; 4121 4122 if ( column.sWidth !== null ) { 4123 column.sWidth = _fnConvertToWidth( column.sWidthOrig, tableContainer ); 4124 4125 userInputs = true; 4126 } 4127 } 4128 4129 /* If the number of columns in the DOM equals the number that we have to 4130 * process in DataTables, then we can use the offsets that are created by 4131 * the web- browser. No custom sizes can be set in order for this to happen, 4132 * nor scrolling used 4133 */ 4134 if ( ! userInputs && ! scrollX && ! scrollY && 4135 columnCount == _fnVisbleColumns( oSettings ) && 4136 columnCount == headerCells.length 4137 ) { 4138 for ( i=0 ; i<columnCount ; i++ ) { 4139 columns[i].sWidth = _fnStringToCss( headerCells.eq(i).width() ); 4140 } 4141 } 4142 else 4143 { 4144 // Otherwise construct a single row, worst case, table with the widest 4145 // node in the data, assign any user defined widths, then insert it into
4146 // the DOM and allow the browser to do all the hard work of calculating 4147 // table widths 4148 var tmpTable = $(table).clone() // don't use cloneNode - IE8 will remove events on the main table 4149 .css( 'visibility', 'hidden' ) 4150 .removeAttr( 'id' ); 4151 4152 // Clean up the table body 4153 tmpTable.find('tbody tr').remove(); 4154 var tr = $('<tr/>').appendTo( tmpTable.find('tbody') ); 4155 4156 // Remove any assigned widths from the footer (from scrolling) 4157 tmpTable.find('tfoot th, tfoot td').css('width', ''); 4158 4159 // Apply custom sizing to the cloned header 4160 headerCells = _fnGetUniqueThs( oSettings, tmpTable.find('thead')[0] ); 4161 4162 for ( i=0 ; i<visibleColumns.length ; i++ ) { 4163 column = columns[ visibleColumns[i] ]; 4164 4165 headerCells[i].style.width = column.sWidthOrig !== null && column.sWidthOrig !== '' ? 4166 _fnStringToCss( column.sWidthOrig ) : 4167 ''; 4168 } 4169 4170 // Find the widest cell for each column and put it into the table 4171 if ( oSettings.aoData.length ) { 4172 for ( i=0 ; i<visibleColumns.length ; i++ ) { 4173 columnIdx = visibleColumns[i]; 4174 column = columns[ columnIdx ]; 4175 4176 $( _fnGetWidestNode( oSettings, columnIdx ) ) 4177 .clone( false ) 4178 .append( column.sContentPadding ) 4179 .appendTo( tr ); 4180 } 4181 } 4182 4183 // Table has been built, attach to the document so we can work with it 4184 tmpTable.appendTo( tableContainer ); 4185 4186 // When scrolling (X or Y) we want to set the width of the table as 4187 // appropriate. However, when not scrolling leave the table width as it 4188 // is. This results in slightly different, but I think correct behaviour 4189 if ( scrollX && scrollXInner ) { 4190 tmpTable.width( scrollXInner ); 4191 } 4192 else if ( scrollX ) { 4193 tmpTable.css( 'width', 'auto' ); 4194 4195 if ( tmpTable.width() < tableContainer.offsetWidth ) { 4196 tmpTable.width( tableContainer.offsetWidth ); 4197 } 4198 } 4199 else if ( scrollY ) { 4200 tmpTable.width( tableContainer.offsetWidth ); 4201 } 4202 else if ( tableWidthAttr ) { 4203 tmpTable.width( tableWidthAttr ); 4204 } 4205 4206 // Take into account the y scrollbar 4207 _fnScrollingWidthAdjust( oSettings, tmpTable[0] ); 4208 4209 // Browsers need a bit of a hand when a width is assigned to any columns 4210 // when x-scrolling as they tend to collapse the table to the min-width, 4211 // even if we sent the column widths. So we need to keep track of what 4212 // the table width should be by summing the user given values, and the 4213 // automatic values 4214 if ( scrollX ) 4215 { 4216 var total = 0; 4217 4218 for ( i=0 ; i<visibleColumns.length ; i++ ) { 4219 column = columns[ visibleColumns[i] ]; 4220 outerWidth = $(headerCells[i]).outerWidth(); 4221 4222 total += column.sWidthOrig === null ? 4223 outerWidth : 4224 parseInt( column.sWidth, 10 ) + outerWidth - $(headerCells[i]).width(); 4225 } 4226 4227 tmpTable.width( _fnStringToCss( total ) ); 4228 table.style.width = _fnStringToCss( total ); 4229 } 4230 4231 // Get the width of each column in the constructed table 4232 for ( i=0 ; i<visibleColumns.length ; i++ ) { 4233 column = columns[ visibleColumns[i] ]; 4234 width = $(headerCells[i]).width(); 4235 4236 if ( width ) { 4237 column.sWidth = _fnStringToCss( width ); 4238 } 4239 } 4240 4241 table.style.width = _fnStringToCss( tmpTable.css('width') ); 4242 4243 // Finished with the table - ditch it 4244 tmpTable.remove(); 4245 } 4246 4247 // If there is a width attr, we want to attach an event listener which 4248 // allows the table sizing to automatically adjust when the window is 4249 // resized. Use the width attr rather than CSS, since we can't know if the 4250 // CSS is a relative value or absolute - DOM read is always px. 4251 if ( tableWidthAttr ) { 4252 table.style.width = _fnStringToCss( tableWidthAttr ); 4253 } 4254 4255 if ( (tableWidthAttr || scrollX) && ! oSettings._reszEvt ) { 4256 var bindResize = function () { 4257 $(window).bind('resize.DT-'+oSettings.sInstance, _fnThrottle( function () { 4258 _fnAdjustColumnSizing( oSettings ); 4259 } ) ); 4260 }; 4261 4262 // IE6/7 will crash if we bind a resize event handler on page load. 4263 // To be removed in 1.11 which drops IE6/7 support 4264 if ( oSettings.oBrowser.bScrollOversize ) { 4265 setTimeout( bindResize, 1000 ); 4266 } 4267 else { 4268 bindResize(); 4269 } 4270 4271 oSettings._reszEvt = true; 4272 } 4273 } 4274 4275 4276 /** 4277 * Throttle the calls to a function. Arguments and context are maintained for 4278 * the throttled function 4279 * @param {function} fn Function to be called 4280 * @param {int} [freq=200] call frequency in mS 4281 * @returns {function} wrapped function 4282 * @memberof DataTable#oApi 4283 */ 4284 function _fnThrottle( fn, freq ) { 4285 var 4286 frequency = freq !== undefined ? freq : 200, 4287 last, 4288 timer; 4289 4290 return function () { 4291 var 4292 that = this, 4293 now = +new Date(), 4294 args = arguments; 4295 4296 if ( last && now < last + frequency ) { 4297 clearTimeout( timer ); 4298 4299 timer = setTimeout( function () { 4300 last = undefined; 4301 fn.apply( that, args ); 4302 }, frequency ); 4303 } 4304 else { 4305 last = now; 4306 fn.apply( that, args ); 4307 } 4308 }; 4309 } 4310 4311 4312 /** 4313 * Convert a CSS unit width to pixels (e.g. 2em) 4314 * @param {string} width width to be converted 4315 * @param {node} parent parent to get the with for (required for relative widths) - optional 4316 * @returns {int} width in pixels 4317 * @memberof DataTable#oApi 4318 */ 4319 function _fnConvertToWidth ( width, parent ) 4320 { 4321 if ( ! width ) { 4322 return 0; 4323 } 4324 4325 var n = $('<div/>') 4326 .css( 'width', _fnStringToCss( width ) ) 4327 .appendTo( parent || document.body ); 4328 4329 var val = n[0].offsetWidth; 4330 n.remove(); 4331 4332 return val; 4333 } 4334 4335 4336 /** 4337 * Adjust a table's width to take account of vertical scroll bar 4338 * @param {object} oSettings dataTables settings object 4339 * @param {node} n table node 4340 * @memberof DataTable#oApi 4341 */ 4342 4343 function _fnScrollingWidthAdjust ( settings, n ) 4344 { 4345 var scroll = settings.oScroll; 4346
vendor: 56,525 bytes, lines 4347-6254
4347 if ( scroll.sX || scroll.sY ) { 4348 // When y-scrolling only, we want to remove the width of the scroll bar 4349 // so the table + scroll bar will fit into the area available, otherwise 4350 // we fix the table at its current size with no adjustment 4351 var correction = ! scroll.sX ? scroll.iBarWidth : 0; 4352 n.style.width = _fnStringToCss( $(n).outerWidth() - correction ); 4353 } 4354 } 4355 4356 4357 /** 4358 * Get the widest node 4359 * @param {object} settings dataTables settings object 4360 * @param {int} colIdx column of interest 4361 * @returns {node} widest table node 4362 * @memberof DataTable#oApi 4363 */ 4364 function _fnGetWidestNode( settings, colIdx ) 4365 { 4366 var idx = _fnGetMaxLenString( settings, colIdx ); 4367 if ( idx < 0 ) { 4368 return null; 4369 } 4370 4371 var data = settings.aoData[ idx ]; 4372 return ! data.nTr ? // Might not have been created when deferred rendering 4373 $('<td/>').html( _fnGetCellData( settings, idx, colIdx, 'display' ) )[0] : 4374 data.anCells[ colIdx ]; 4375 } 4376 4377 4378 /** 4379 * Get the maximum strlen for each data column 4380 * @param {object} settings dataTables settings object 4381 * @param {int} colIdx column of interest 4382 * @returns {string} max string length for each column 4383 * @memberof DataTable#oApi 4384 */ 4385 function _fnGetMaxLenString( settings, colIdx ) 4386 { 4387 var s, max=-1, maxIdx = -1; 4388 4389 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 4390 s = _fnGetCellData( settings, i, colIdx, 'display' )+''; 4391 s = s.replace( __re_html_remove, '' ); 4392 4393 if ( s.length > max ) { 4394 max = s.length; 4395 maxIdx = i; 4396 } 4397 } 4398 4399 return maxIdx; 4400 } 4401 4402 4403 /** 4404 * Append a CSS unit (only if required) to a string 4405 * @param {string} value to css-ify 4406 * @returns {string} value with css unit 4407 * @memberof DataTable#oApi 4408 */ 4409 function _fnStringToCss( s ) 4410 { 4411 if ( s === null ) { 4412 return '0px'; 4413 } 4414 4415 if ( typeof s == 'number' ) { 4416 return s < 0 ? 4417 '0px' : 4418 s+'px'; 4419 } 4420 4421 // Check it has a unit character already 4422 return s.match(/\d$/) ? 4423 s+'px' : 4424 s; 4425 } 4426 4427 4428 /** 4429 * Get the width of a scroll bar in this browser being used 4430 * @returns {int} width in pixels 4431 * @memberof DataTable#oApi 4432 */ 4433 function _fnScrollBarWidth () 4434 { 4435 // On first run a static variable is set, since this is only needed once. 4436 // Subsequent runs will just use the previously calculated value 4437 var width = DataTable.__scrollbarWidth; 4438 4439 if ( width === undefined ) { 4440 var sizer = $('<p/>').css( { 4441 position: 'absolute', 4442 top: 0, 4443 left: 0, 4444 width: '100%', 4445 height: 150, 4446 padding: 0, 4447 overflow: 'scroll', 4448 visibility: 'hidden' 4449 } ) 4450 .appendTo('body'); 4451 4452 width = sizer[0].offsetWidth - sizer[0].clientWidth; 4453 DataTable.__scrollbarWidth = width; 4454 4455 sizer.remove(); 4456 } 4457 4458 return width; 4459 } 4460 4461 4462 4463 function _fnSortFlatten ( settings ) 4464 { 4465 var 4466 i, iLen, k, kLen, 4467 aSort = [], 4468 aiOrig = [], 4469 aoColumns = settings.aoColumns, 4470 aDataSort, iCol, sType, srcCol, 4471 fixed = settings.aaSortingFixed, 4472 fixedObj = $.isPlainObject( fixed ), 4473 nestedSort = [], 4474 add = function ( a ) { 4475 if ( a.length && ! $.isArray( a[0] ) ) { 4476 // 1D array 4477 nestedSort.push( a ); 4478 } 4479 else { 4480 // 2D array 4481 nestedSort.push.apply( nestedSort, a ); 4482 } 4483 }; 4484 4485 // Build the sort array, with pre-fix and post-fix options if they have been 4486 // specified 4487 if ( $.isArray( fixed ) ) { 4488 add( fixed ); 4489 } 4490 4491 if ( fixedObj && fixed.pre ) { 4492 add( fixed.pre ); 4493 } 4494 4495 add( settings.aaSorting ); 4496 4497 if (fixedObj && fixed.post ) { 4498 add( fixed.post ); 4499 } 4500 4501 for ( i=0 ; i<nestedSort.length ; i++ ) 4502 { 4503 srcCol = nestedSort[i][0]; 4504 aDataSort = aoColumns[ srcCol ].aDataSort; 4505 4506 for ( k=0, kLen=aDataSort.length ; k<kLen ; k++ ) 4507 { 4508 iCol = aDataSort[k]; 4509 sType = aoColumns[ iCol ].sType || 'string'; 4510 4511 if ( nestedSort[i]._idx === undefined ) { 4512 nestedSort[i]._idx = $.inArray( nestedSort[i][1], aoColumns[iCol].asSorting ); 4513 } 4514 4515 aSort.push( { 4516 src: srcCol, 4517 col: iCol, 4518 dir: nestedSort[i][1], 4519 index: nestedSort[i]._idx, 4520 type: sType, 4521 formatter: DataTable.ext.type.order[ sType+"-pre" ] 4522 } ); 4523 } 4524 } 4525 4526 return aSort; 4527 } 4528 4529 /** 4530 * Change the order of the table 4531 * @param {object} oSettings dataTables settings object 4532 * @memberof DataTable#oApi 4533 * @todo This really needs split up! 4534 */ 4535 function _fnSort ( oSettings ) 4536 { 4537 var 4538 i, ien, iLen, j, jLen, k, kLen, 4539 sDataType, nTh, 4540 aiOrig = [], 4541 oExtSort = DataTable.ext.type.order, 4542 aoData = oSettings.aoData, 4543 aoColumns = oSettings.aoColumns, 4544 aDataSort, data, iCol, sType, oSort, 4545 formatters = 0, 4546 sortCol, 4547 displayMaster = oSettings.aiDisplayMaster, 4548 aSort; 4549 4550 // Resolve any column types that are unknown due to addition or invalidation 4551 // @todo Can this be moved into a 'data-ready' handler which is called when 4552 // data is going to be used in the table? 4553 _fnColumnTypes( oSettings ); 4554 4555 aSort = _fnSortFlatten( oSettings ); 4556 4557 for ( i=0, ien=aSort.length ; i<ien ; i++ ) { 4558 sortCol = aSort[i]; 4559 4560 // Track if we can use the fast sort algorithm 4561 if ( sortCol.formatter ) { 4562 formatters++; 4563 } 4564 4565 // Load the data needed for the sort, for each cell 4566 _fnSortData( oSettings, sortCol.col ); 4567 } 4568 4569 /* No sorting required if server-side or no sorting array */ 4570 if ( _fnDataSource( oSettings ) != 'ssp' && aSort.length !== 0 ) 4571 { 4572 // Create a value - key array of the current row positions such that we can use their 4573 // current position during the sort, if values match, in order to perform stable sorting 4574 for ( i=0, iLen=displayMaster.length ; i<iLen ; i++ ) { 4575 aiOrig[ displayMaster[i] ] = i; 4576 } 4577 4578 /* Do the sort - here we want multi-column sorting based on a given data source (column) 4579 * and sorting function (from oSort) in a certain direction. It's reasonably complex to 4580 * follow on it's own, but this is what we want (example two column sorting): 4581 * fnLocalSorting = function(a,b){ 4582 * var iTest; 4583 * iTest = oSort['string-asc']('data11', 'data12'); 4584 * if (iTest !== 0) 4585 * return iTest; 4586 * iTest = oSort['numeric-desc']('data21', 'data22'); 4587 * if (iTest !== 0) 4588 * return iTest; 4589 * return oSort['numeric-asc']( aiOrig[a], aiOrig[b] ); 4590 * } 4591 * Basically we have a test for each sorting column, if the data in that column is equal, 4592 * test the next column. If all columns match, then we use a numeric sort on the row 4593 * positions in the original data array to provide a stable sort. 4594 * 4595 * Note - I know it seems excessive to have two sorting methods, but the first is around 4596 * 15% faster, so the second is only maintained for backwards compatibility with sorting 4597 * methods which do not have a pre-sort formatting function. 4598 */ 4599 if ( formatters === aSort.length ) { 4600 // All sort types have formatting functions 4601 displayMaster.sort( function ( a, b ) { 4602 var 4603 x, y, k, test, sort, 4604 len=aSort.length, 4605 dataA = aoData[a]._aSortData, 4606 dataB = aoData[b]._aSortData; 4607 4608 for ( k=0 ; k<len ; k++ ) { 4609 sort = aSort[k]; 4610 4611 x = dataA[ sort.col ]; 4612 y = dataB[ sort.col ]; 4613 4614 test = x<y ? -1 : x>y ? 1 : 0; 4615 if ( test !== 0 ) { 4616 return sort.dir === 'asc' ? test : -test; 4617 } 4618 } 4619 4620 x = aiOrig[a]; 4621 y = aiOrig[b]; 4622 return x<y ? -1 : x>y ? 1 : 0; 4623 } ); 4624 } 4625 else { 4626 // Depreciated - remove in 1.11 (providing a plug-in option) 4627 // Not all sort types have formatting methods, so we have to call their sorting 4628 // methods. 4629 displayMaster.sort( function ( a, b ) { 4630 var 4631 x, y, k, l, test, sort, fn, 4632 len=aSort.length, 4633 dataA = aoData[a]._aSortData, 4634 dataB = aoData[b]._aSortData; 4635 4636 for ( k=0 ; k<len ; k++ ) { 4637 sort = aSort[k]; 4638 4639 x = dataA[ sort.col ]; 4640 y = dataB[ sort.col ]; 4641 4642 fn = oExtSort[ sort.type+"-"+sort.dir ] || oExtSort[ "string-"+sort.dir ]; 4643 test = fn( x, y ); 4644 if ( test !== 0 ) { 4645 return test; 4646 } 4647 } 4648 4649 x = aiOrig[a]; 4650 y = aiOrig[b]; 4651 return x<y ? -1 : x>y ? 1 : 0; 4652 } ); 4653 } 4654 } 4655 4656 /* Tell the draw function that we have sorted the data */ 4657 oSettings.bSorted = true; 4658 } 4659 4660 4661 function _fnSortAria ( settings ) 4662 { 4663 var label; 4664 var nextSort; 4665 var columns = settings.aoColumns; 4666 var aSort = _fnSortFlatten( settings ); 4667 var oAria = settings.oLanguage.oAria; 4668 4669 // ARIA attributes - need to loop all columns, to update all (removing old 4670 // attributes as needed) 4671 for ( var i=0, iLen=columns.length ; i<iLen ; i++ ) 4672 { 4673 var col = columns[i]; 4674 var asSorting = col.asSorting; 4675 var sTitle = col.sTitle.replace( /<.*?>/g, "" ); 4676 var th = col.nTh; 4677 4678 // IE7 is throwing an error when setting these properties with jQuery's 4679 // attr() and removeAttr() methods... 4680 th.removeAttribute('aria-sort'); 4681 4682 /* In ARIA only the first sorting column can be marked as sorting - no multi-sort option */ 4683 if ( col.bSortable ) { 4684 if ( aSort.length > 0 && aSort[0].col == i ) { 4685 th.setAttribute('aria-sort', aSort[0].dir=="asc" ? "ascending" : "descending" ); 4686 nextSort = asSorting[ aSort[0].index+1 ] || asSorting[0]; 4687 } 4688 else { 4689 nextSort = asSorting[0]; 4690 } 4691 4692 label = sTitle + ( nextSort === "asc" ? 4693 oAria.sSortAscending : 4694 oAria.sSortDescending 4695 ); 4696 } 4697 else { 4698 label = sTitle; 4699 } 4700 4701 th.setAttribute('aria-label', label); 4702 } 4703 } 4704 4705 4706 /** 4707 * Function to run on user sort request 4708 * @param {object} settings dataTables settings object 4709 * @param {node} attachTo node to attach the handler to 4710 * @param {int} colIdx column sorting index 4711 * @param {boolean} [append=false] Append the requested sort to the existing 4712 * sort if true (i.e. multi-column sort) 4713 * @param {function} [callback] callback function 4714 * @memberof DataTable#oApi 4715 */ 4716 function _fnSortListener ( settings, colIdx, append, callback ) 4717 { 4718 var col = settings.aoColumns[ colIdx ]; 4719 var sorting = settings.aaSorting; 4720 var asSorting = col.asSorting; 4721 var nextSortIdx; 4722 var next = function ( a, overflow ) { 4723 var idx = a._idx; 4724 if ( idx === undefined ) { 4725 idx = $.inArray( a[1], asSorting ); 4726 } 4727 4728 return idx+1 < asSorting.length ? 4729 idx+1 : 4730 overflow ? 4731 null : 4732 0; 4733 }; 4734 4735 // Convert to 2D array if needed 4736 if ( typeof sorting[0] === 'number' ) { 4737 sorting = settings.aaSorting = [ sorting ]; 4738 } 4739 4740 // If appending the sort then we are multi-column sorting 4741 if ( append && settings.oFeatures.bSortMulti ) { 4742 // Are we already doing some kind of sort on this column? 4743 var sortIdx = $.inArray( colIdx, _pluck(sorting, '0') ); 4744 4745 if ( sortIdx !== -1 ) { 4746 // Yes, modify the sort 4747 nextSortIdx = next( sorting[sortIdx], true ); 4748 4749 if ( nextSortIdx === null && sorting.length === 1 ) { 4750 nextSortIdx = 0; // can't remove sorting completely 4751 } 4752 4753 if ( nextSortIdx === null ) { 4754 sorting.splice( sortIdx, 1 ); 4755 } 4756 else { 4757 sorting[sortIdx][1] = asSorting[ nextSortIdx ]; 4758 sorting[sortIdx]._idx = nextSortIdx; 4759 } 4760 } 4761 else { 4762 // No sort on this column yet 4763 sorting.push( [ colIdx, asSorting[0], 0 ] ); 4764 sorting[sorting.length-1]._idx = 0; 4765 } 4766 } 4767 else if ( sorting.length && sorting[0][0] == colIdx ) { 4768 // Single column - already sorting on this column, modify the sort 4769 nextSortIdx = next( sorting[0] ); 4770 4771 sorting.length = 1; 4772 sorting[0][1] = asSorting[ nextSortIdx ]; 4773 sorting[0]._idx = nextSortIdx; 4774 } 4775 else { 4776 // Single column - sort only on this column 4777 sorting.length = 0; 4778 sorting.push( [ colIdx, asSorting[0] ] ); 4779 sorting[0]._idx = 0; 4780 } 4781 4782 // Run the sort by calling a full redraw 4783 _fnReDraw( settings ); 4784 4785 // callback used for async user interaction 4786 if ( typeof callback == 'function' ) { 4787 callback( settings ); 4788 } 4789 } 4790 4791 4792 /** 4793 * Attach a sort handler (click) to a node 4794 * @param {object} settings dataTables settings object 4795 * @param {node} attachTo node to attach the handler to 4796 * @param {int} colIdx column sorting index 4797 * @param {function} [callback] callback function 4798 * @memberof DataTable#oApi 4799 */ 4800 function _fnSortAttachListener ( settings, attachTo, colIdx, callback ) 4801 { 4802 var col = settings.aoColumns[ colIdx ]; 4803 4804 _fnBindAction( attachTo, {}, function (e) { 4805 /* If the column is not sortable - don't to anything */ 4806 if ( col.bSortable === false ) { 4807 return; 4808 } 4809 4810 // If processing is enabled use a timeout to allow the processing 4811 // display to be shown - otherwise to it synchronously 4812 if ( settings.oFeatures.bProcessing ) { 4813 _fnProcessingDisplay( settings, true ); 4814 4815 setTimeout( function() { 4816 _fnSortListener( settings, colIdx, e.shiftKey, callback ); 4817 4818 // In server-side processing, the draw callback will remove the 4819 // processing display 4820 if ( _fnDataSource( settings ) !== 'ssp' ) { 4821 _fnProcessingDisplay( settings, false ); 4822 } 4823 }, 0 ); 4824 } 4825 else { 4826 _fnSortListener( settings, colIdx, e.shiftKey, callback ); 4827 } 4828 } ); 4829 } 4830 4831 4832 /** 4833 * Set the sorting classes on table's body, Note: it is safe to call this function 4834 * when bSort and bSortClasses are false 4835 * @param {object} oSettings dataTables settings object 4836 * @memberof DataTable#oApi 4837 */ 4838 function _fnSortingClasses( settings ) 4839 { 4840 var oldSort = settings.aLastSort; 4841 var sortClass = settings.oClasses.sSortColumn; 4842 var sort = _fnSortFlatten( settings ); 4843 var features = settings.oFeatures; 4844 var i, ien, colIdx; 4845 4846 if ( features.bSort && features.bSortClasses ) { 4847 // Remove old sorting classes 4848 for ( i=0, ien=oldSort.length ; i<ien ; i++ ) { 4849 colIdx = oldSort[i].src; 4850 4851 // Remove column sorting 4852 $( _pluck( settings.aoData, 'anCells', colIdx ) ) 4853 .removeClass( sortClass + (i<2 ? i+1 : 3) ); 4854 } 4855 4856 // Add new column sorting 4857 for ( i=0, ien=sort.length ; i<ien ; i++ ) { 4858 colIdx = sort[i].src; 4859 4860 $( _pluck( settings.aoData, 'anCells', colIdx ) ) 4861 .addClass( sortClass + (i<2 ? i+1 : 3) ); 4862 } 4863 } 4864 4865 settings.aLastSort = sort; 4866 } 4867 4868 4869 // Get the data to sort a column, be it from cache, fresh (populating the 4870 // cache), or from a sort formatter 4871 function _fnSortData( settings, idx ) 4872 { 4873 // Custom sorting function - provided by the sort data type 4874 var column = settings.aoColumns[ idx ]; 4875 var customSort = DataTable.ext.order[ column.sSortDataType ]; 4876 var customData; 4877 4878 if ( customSort ) { 4879 customData = customSort.call( settings.oInstance, settings, idx, 4880 _fnColumnIndexToVisible( settings, idx ) 4881 ); 4882 } 4883 4884 // Use / populate cache 4885 var row, cellData; 4886 var formatter = DataTable.ext.type.order[ column.sType+"-pre" ]; 4887 4888 for ( var i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 4889 row = settings.aoData[i]; 4890 4891 if ( ! row._aSortData ) { 4892 row._aSortData = []; 4893 } 4894 4895 if ( ! row._aSortData[idx] || customSort ) { 4896 cellData = customSort ? 4897 customData[i] : // If there was a custom sort function, use data from there 4898 _fnGetCellData( settings, i, idx, 'sort' ); 4899 4900 row._aSortData[ idx ] = formatter ? 4901 formatter( cellData ) : 4902 cellData; 4903 } 4904 } 4905 } 4906 4907 4908 4909 /** 4910 * Save the state of a table 4911 * @param {object} oSettings dataTables settings object 4912 * @memberof DataTable#oApi 4913 */ 4914 function _fnSaveState ( settings ) 4915 { 4916 if ( !settings.oFeatures.bStateSave || settings.bDestroying ) 4917 { 4918 return; 4919 } 4920 4921 /* Store the interesting variables */ 4922 var state = { 4923 time: +new Date(), 4924 start: settings._iDisplayStart, 4925 length: settings._iDisplayLength, 4926 order: $.extend( true, [], settings.aaSorting ), 4927 search: _fnSearchToCamel( settings.oPreviousSearch ), 4928 columns: $.map( settings.aoColumns, function ( col, i ) { 4929 return { 4930 visible: col.bVisible, 4931 search: _fnSearchToCamel( settings.aoPreSearchCols[i] ) 4932 }; 4933 } ) 4934 }; 4935 4936 _fnCallbackFire( settings, "aoStateSaveParams", 'stateSaveParams', [settings, state] ); 4937 4938 settings.oSavedState = state; 4939 settings.fnStateSaveCallback.call( settings.oInstance, settings, state ); 4940 } 4941 4942 4943 /** 4944 * Attempt to load a saved table state 4945 * @param {object} oSettings dataTables settings object 4946 * @param {object} oInit DataTables init object so we can override settings 4947 * @memberof DataTable#oApi 4948 */ 4949 function _fnLoadState ( settings, oInit ) 4950 { 4951 var i, ien; 4952 var columns = settings.aoColumns; 4953 4954 if ( ! settings.oFeatures.bStateSave ) { 4955 return; 4956 } 4957 4958 var state = settings.fnStateLoadCallback.call( settings.oInstance, settings ); 4959 if ( ! state || ! state.time ) { 4960 return; 4961 } 4962 4963 /* Allow custom and plug-in manipulation functions to alter the saved data set and 4964 * cancelling of loading by returning false 4965 */ 4966 var abStateLoad = _fnCallbackFire( settings, 'aoStateLoadParams', 'stateLoadParams', [settings, state] ); 4967 if ( $.inArray( false, abStateLoad ) !== -1 ) { 4968 return; 4969 } 4970 4971 /* Reject old data */ 4972 var duration = settings.iStateDuration; 4973 if ( duration > 0 && state.time < +new Date() - (duration*1000) ) { 4974 return; 4975 } 4976 4977 // Number of columns have changed - all bets are off, no restore of settings 4978 if ( columns.length !== state.columns.length ) { 4979 return; 4980 } 4981 4982 // Store the saved state so it might be accessed at any time 4983 settings.oLoadedState = $.extend( true, {}, state ); 4984 4985 // Restore key features - todo - for 1.11 this needs to be done by 4986 // subscribed events 4987 if ( state.start !== undefined ) { 4988 settings._iDisplayStart = state.start; 4989 settings.iInitDisplayStart = state.start; 4990 } 4991 if ( state.length !== undefined ) { 4992 settings._iDisplayLength = state.length; 4993 } 4994 4995 // Order 4996 if ( state.order !== undefined ) { 4997 settings.aaSorting = []; 4998 $.each( state.order, function ( i, col ) { 4999 settings.aaSorting.push( col[0] >= columns.length ? 5000 [ 0, col[1] ] : 5001 col 5002 ); 5003 } ); 5004 } 5005 5006 // Search 5007 if ( state.search !== undefined ) { 5008 $.extend( settings.oPreviousSearch, _fnSearchToHung( state.search ) ); 5009 } 5010 5011 // Columns 5012 for ( i=0, ien=state.columns.length ; i<ien ; i++ ) { 5013 var col = state.columns[i]; 5014 5015 // Visibility 5016 if ( col.visible !== undefined ) { 5017 columns[i].bVisible = col.visible; 5018 } 5019 5020 // Search 5021 if ( col.search !== undefined ) { 5022 $.extend( settings.aoPreSearchCols[i], _fnSearchToHung( col.search ) ); 5023 } 5024 } 5025 5026 _fnCallbackFire( settings, 'aoStateLoaded', 'stateLoaded', [settings, state] ); 5027 } 5028 5029 5030 /** 5031 * Return the settings object for a particular table 5032 * @param {node} table table we are using as a dataTable 5033 * @returns {object} Settings object - or null if not found 5034 * @memberof DataTable#oApi 5035 */ 5036 function _fnSettingsFromNode ( table ) 5037 { 5038 var settings = DataTable.settings; 5039 var idx = $.inArray( table, _pluck( settings, 'nTable' ) ); 5040 5041 return idx !== -1 ? 5042 settings[ idx ] : 5043 null; 5044 } 5045 5046 5047 /** 5048 * Log an error message 5049 * @param {object} settings dataTables settings object 5050 * @param {int} level log error messages, or display them to the user 5051 * @param {string} msg error message 5052 * @param {int} tn Technical note id to get more information about the error. 5053 * @memberof DataTable#oApi 5054 */ 5055 function _fnLog( settings, level, msg, tn ) 5056 { 5057 msg = 'DataTables warning: '+ 5058 (settings!==null ? 'table id='+settings.sTableId+' - ' : '')+msg; 5059 5060 if ( tn ) { 5061 msg += '. For more information about this error, please see '+ 5062 'http://datatables.net/tn/'+tn; 5063 } 5064 5065 if ( ! level ) { 5066 // Backwards compatibility pre 1.10 5067 var ext = DataTable.ext; 5068 var type = ext.sErrMode || ext.errMode; 5069 5070 _fnCallbackFire( settings, null, 'error', [ settings, tn, msg ] ); 5071 5072 if ( type == 'alert' ) { 5073 alert( msg ); 5074 } 5075 else if ( type == 'throw' ) { 5076 throw new Error(msg); 5077 } 5078 else if ( typeof type == 'function' ) { 5079 type( settings, tn, msg ); 5080 } 5081 } 5082 else if ( window.console && console.log ) { 5083 console.log( msg ); 5084 } 5085 } 5086 5087 5088 /** 5089 * See if a property is defined on one object, if so assign it to the other object 5090 * @param {object} ret target object 5091 * @param {object} src source object 5092 * @param {string} name property 5093 * @param {string} [mappedName] name to map too - optional, name used if not given 5094 * @memberof DataTable#oApi 5095 */ 5096 function _fnMap( ret, src, name, mappedName ) 5097 { 5098 if ( $.isArray( name ) ) { 5099 $.each( name, function (i, val) { 5100 if ( $.isArray( val ) ) { 5101 _fnMap( ret, src, val[0], val[1] ); 5102 } 5103 else { 5104 _fnMap( ret, src, val ); 5105 } 5106 } ); 5107 5108 return; 5109 } 5110 5111 if ( mappedName === undefined ) { 5112 mappedName = name; 5113 } 5114 5115 if ( src[name] !== undefined ) { 5116 ret[mappedName] = src[name]; 5117 } 5118 } 5119 5120 5121 /** 5122 * Extend objects - very similar to jQuery.extend, but deep copy objects, and 5123 * shallow copy arrays. The reason we need to do this, is that we don't want to 5124 * deep copy array init values (such as aaSorting) since the dev wouldn't be 5125 * able to override them, but we do want to deep copy arrays. 5126 * @param {object} out Object to extend 5127 * @param {object} extender Object from which the properties will be applied to 5128 * out 5129 * @param {boolean} breakRefs If true, then arrays will be sliced to take an 5130 * independent copy with the exception of the `data` or `aaData` parameters 5131 * if they are present. This is so you can pass in a collection to 5132 * DataTables and have that used as your data source without breaking the 5133 * references 5134 * @returns {object} out Reference, just for convenience - out === the return. 5135 * @memberof DataTable#oApi 5136 * @todo This doesn't take account of arrays inside the deep copied objects. 5137 */ 5138 function _fnExtend( out, extender, breakRefs ) 5139 { 5140 var val; 5141 5142 for ( var prop in extender ) { 5143 if ( extender.hasOwnProperty(prop) ) { 5144 val = extender[prop]; 5145 5146 if ( $.isPlainObject( val ) ) { 5147 if ( ! $.isPlainObject( out[prop] ) ) { 5148 out[prop] = {}; 5149 } 5150 $.extend( true, out[prop], val ); 5151 } 5152 else if ( breakRefs && prop !== 'data' && prop !== 'aaData' && $.isArray(val) ) { 5153 out[prop] = val.slice(); 5154 } 5155 else { 5156 out[prop] = val; 5157 } 5158 } 5159 } 5160 5161 return out; 5162 } 5163 5164 5165 /** 5166 * Bind an event handers to allow a click or return key to activate the callback. 5167 * This is good for accessibility since a return on the keyboard will have the 5168 * same effect as a click, if the element has focus. 5169 * @param {element} n Element to bind the action to 5170 * @param {object} oData Data object to pass to the triggered function 5171 * @param {function} fn Callback function for when the event is triggered 5172 * @memberof DataTable#oApi 5173 */ 5174 function _fnBindAction( n, oData, fn ) 5175 { 5176 $(n) 5177 .bind( 'click.DT', oData, function (e) { 5178 n.blur(); // Remove focus outline for mouse users 5179 fn(e); 5180 } ) 5181 .bind( 'keypress.DT', oData, function (e){ 5182 if ( e.which === 13 ) { 5183 e.preventDefault(); 5184 fn(e); 5185 } 5186 } ) 5187 .bind( 'selectstart.DT', function () { 5188 /* Take the brutal approach to cancelling text selection */ 5189 return false; 5190 } ); 5191 } 5192 5193 5194 /** 5195 * Register a callback function. Easily allows a callback function to be added to 5196 * an array store of callback functions that can then all be called together. 5197 * @param {object} oSettings dataTables settings object 5198 * @param {string} sStore Name of the array storage for the callbacks in oSettings 5199 * @param {function} fn Function to be called back 5200 * @param {string} sName Identifying name for the callback (i.e. a label) 5201 * @memberof DataTable#oApi 5202 */ 5203 function _fnCallbackReg( oSettings, sStore, fn, sName ) 5204 { 5205 if ( fn ) 5206 { 5207 oSettings[sStore].push( { 5208 "fn": fn, 5209 "sName": sName 5210 } ); 5211 } 5212 } 5213 5214 5215 /** 5216 * Fire callback functions and trigger events. Note that the loop over the 5217 * callback array store is done backwards! Further note that you do not want to 5218 * fire off triggers in time sensitive applications (for example cell creation) 5219 * as its slow. 5220 * @param {object} settings dataTables settings object 5221 * @param {string} callbackArr Name of the array storage for the callbacks in 5222 * oSettings 5223 * @param {string} eventName Name of the jQuery custom event to trigger. If 5224 * null no trigger is fired 5225 * @param {array} args Array of arguments to pass to the callback function / 5226 * trigger 5227 * @memberof DataTable#oApi 5228 */ 5229 function _fnCallbackFire( settings, callbackArr, eventName, args ) 5230 { 5231 var ret = []; 5232 5233 if ( callbackArr ) { 5234 ret = $.map( settings[callbackArr].slice().reverse(), function (val, i) { 5235 return val.fn.apply( settings.oInstance, args ); 5236 } ); 5237 } 5238 5239 if ( eventName !== null ) { 5240 var e = $.Event( eventName+'.dt' ); 5241 5242 $(settings.nTable).trigger( e, args ); 5243 5244 ret.push( e.result ); 5245 } 5246 5247 return ret; 5248 } 5249 5250 5251 function _fnLengthOverflow ( settings ) 5252 { 5253 var 5254 start = settings._iDisplayStart, 5255 end = settings.fnDisplayEnd(), 5256 len = settings._iDisplayLength; 5257 5258 /* If we have space to show extra rows (backing up from the end point - then do so */ 5259 if ( start >= end ) 5260 { 5261 start = end - len; 5262 } 5263 5264 // Keep the start record on the current page 5265 start -= (start % len); 5266 5267 if ( len === -1 || start < 0 ) 5268 { 5269 start = 0; 5270 } 5271 5272 settings._iDisplayStart = start; 5273 } 5274 5275 5276 function _fnRenderer( settings, type ) 5277 { 5278 var renderer = settings.renderer; 5279 var host = DataTable.ext.renderer[type]; 5280 5281 if ( $.isPlainObject( renderer ) && renderer[type] ) { 5282 // Specific renderer for this type. If available use it, otherwise use 5283 // the default. 5284 return host[renderer[type]] || host._; 5285 } 5286 else if ( typeof renderer === 'string' ) { 5287 // Common renderer - if there is one available for this type use it, 5288 // otherwise use the default 5289 return host[renderer] || host._; 5290 } 5291 5292 // Use the default 5293 return host._; 5294 } 5295 5296 5297 /** 5298 * Detect the data source being used for the table. Used to simplify the code 5299 * a little (ajax) and to make it compress a little smaller. 5300 * 5301 * @param {object} settings dataTables settings object 5302 * @returns {string} Data source 5303 * @memberof DataTable#oApi 5304 */ 5305 function _fnDataSource ( settings ) 5306 { 5307 if ( settings.oFeatures.bServerSide ) { 5308 return 'ssp'; 5309 } 5310 else if ( settings.ajax || settings.sAjaxSource ) { 5311 return 'ajax'; 5312 } 5313 return 'dom'; 5314 } 5315 5316 5317 DataTable = function( options ) 5318 { 5319 /** 5320 * Perform a jQuery selector action on the table's TR elements (from the tbody) and 5321 * return the resulting jQuery object. 5322 * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on 5323 * @param {object} [oOpts] Optional parameters for modifying the rows to be included 5324 * @param {string} [oOpts.filter=none] Select TR elements that meet the current filter 5325 * criterion ("applied") or all TR elements (i.e. no filter). 5326 * @param {string} [oOpts.order=current] Order of the TR elements in the processed array. 5327 * Can be either 'current', whereby the current sorting of the table is used, or 5328 * 'original' whereby the original order the data was read into the table is used. 5329 * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page 5330 * ("current") or not ("all"). If 'current' is given, then order is assumed to be 5331 * 'current' and filter is 'applied', regardless of what they might be given as. 5332 * @returns {object} jQuery object, filtered by the given selector. 5333 * @dtopt API 5334 * @deprecated Since v1.10 5335 * 5336 * @example 5337 * $(document).ready(function() { 5338 * var oTable = $('#example').dataTable(); 5339 * 5340 * // Highlight every second row 5341 * oTable.$('tr:odd').css('backgroundColor', 'blue'); 5342 * } ); 5343 * 5344 * @example 5345 * $(document).ready(function() { 5346 * var oTable = $('#example').dataTable(); 5347 * 5348 * // Filter to rows with 'Webkit' in them, add a background colour and then 5349 * // remove the filter, thus highlighting the 'Webkit' rows only. 5350 * oTable.fnFilter('Webkit'); 5351 * oTable.$('tr', {"search": "applied"}).css('backgroundColor', 'blue'); 5352 * oTable.fnFilter(''); 5353 * } ); 5354 */ 5355 this.$ = function ( sSelector, oOpts ) 5356 { 5357 return this.api(true).$( sSelector, oOpts ); 5358 }; 5359 5360 5361 /** 5362 * Almost identical to $ in operation, but in this case returns the data for the matched 5363 * rows - as such, the jQuery selector used should match TR row nodes or TD/TH cell nodes 5364 * rather than any descendants, so the data can be obtained for the row/cell. If matching 5365 * rows are found, the data returned is the original data array/object that was used to 5366 * create the row (or a generated array if from a DOM source). 5367 * 5368 * This method is often useful in-combination with $ where both functions are given the 5369 * same parameters and the array indexes will match identically. 5370 * @param {string|node|jQuery} sSelector jQuery selector or node collection to act on 5371 * @param {object} [oOpts] Optional parameters for modifying the rows to be included 5372 * @param {string} [oOpts.filter=none] Select elements that meet the current filter 5373 * criterion ("applied") or all elements (i.e. no filter). 5374 * @param {string} [oOpts.order=current] Order of the data in the processed array. 5375 * Can be either 'current', whereby the current sorting of the table is used, or 5376 * 'original' whereby the original order the data was read into the table is used. 5377 * @param {string} [oOpts.page=all] Limit the selection to the currently displayed page 5378 * ("current") or not ("all"). If 'current' is given, then order is assumed to be 5379 * 'current' and filter is 'applied', regardless of what they might be given as. 5380 * @returns {array} Data for the matched elements. If any elements, as a result of the 5381 * selector, were not TR, TD or TH elements in the DataTable, they will have a null 5382 * entry in the array. 5383 * @dtopt API 5384 * @deprecated Since v1.10 5385 * 5386 * @example 5387 * $(document).ready(function() { 5388 * var oTable = $('#example').dataTable(); 5389 * 5390 * // Get the data from the first row in the table 5391 * var data = oTable._('tr:first'); 5392 * 5393 * // Do something useful with the data 5394 * alert( "First cell is: "+data[0] ); 5395 * } ); 5396 * 5397 * @example 5398 * $(document).ready(function() { 5399 * var oTable = $('#example').dataTable(); 5400 * 5401 * // Filter to 'Webkit' and get all data for 5402 * oTable.fnFilter('Webkit'); 5403 * var data = oTable._('tr', {"search": "applied"}); 5404 * 5405 * // Do something with the data 5406 * alert( data.length+" rows matched the search" ); 5407 * } ); 5408 */ 5409 this._ = function ( sSelector, oOpts ) 5410 { 5411 return this.api(true).rows( sSelector, oOpts ).data(); 5412 }; 5413 5414 5415 /** 5416 * Create a DataTables Api instance, with the currently selected tables for 5417 * the Api's context. 5418 * @param {boolean} [traditional=false] Set the API instance's context to be 5419 * only the table referred to by the `DataTable.ext.iApiIndex` option, as was 5420 * used in the API presented by DataTables 1.9- (i.e. the traditional mode), 5421 * or if all tables captured in the jQuery object should be used. 5422 * @return {DataTables.Api} 5423 */ 5424 this.api = function ( traditional ) 5425 { 5426 return traditional ? 5427 new _Api( 5428 _fnSettingsFromNode( this[ _ext.iApiIndex ] ) 5429 ) : 5430 new _Api( this ); 5431 }; 5432 5433 5434 /** 5435 * Add a single new row or multiple rows of data to the table. Please note 5436 * that this is suitable for client-side processing only - if you are using 5437 * server-side processing (i.e. "bServerSide": true), then to add data, you 5438 * must add it to the data source, i.e. the server-side, through an Ajax call. 5439 * @param {array|object} data The data to be added to the table. This can be: 5440 * <ul> 5441 * <li>1D array of data - add a single row with the data provided</li> 5442 * <li>2D array of arrays - add multiple rows in a single call</li> 5443 * <li>object - data object when using <i>mData</i></li> 5444 * <li>array of objects - multiple data objects when using <i>mData</i></li> 5445 * </ul> 5446 * @param {bool} [redraw=true] redraw the table or not 5447 * @returns {array} An array of integers, representing the list of indexes in 5448 * <i>aoData</i> ({@link DataTable.models.oSettings}) that have been added to 5449 * the table. 5450 * @dtopt API 5451 * @deprecated Since v1.10 5452 * 5453 * @example 5454 * // Global var for counter 5455 * var giCount = 2; 5456 * 5457 * $(document).ready(function() { 5458 * $('#example').dataTable(); 5459 * } ); 5460 * 5461 * function fnClickAddRow() { 5462 * $('#example').dataTable().fnAddData( [ 5463 * giCount+".1", 5464 * giCount+".2", 5465 * giCount+".3", 5466 * giCount+".4" ] 5467 * ); 5468 * 5469 * giCount++; 5470 * } 5471 */ 5472 this.fnAddData = function( data, redraw ) 5473 { 5474 var api = this.api( true ); 5475 5476 /* Check if we want to add multiple rows or not */ 5477 var rows = $.isArray(data) && ( $.isArray(data[0]) || $.isPlainObject(data[0]) ) ? 5478 api.rows.add( data ) : 5479 api.row.add( data ); 5480 5481 if ( redraw === undefined || redraw ) { 5482 api.draw(); 5483 } 5484 5485 return rows.flatten().toArray(); 5486 }; 5487 5488 5489 /** 5490 * This function will make DataTables recalculate the column sizes, based on the data 5491 * contained in the table and the sizes applied to the columns (in the DOM, CSS or 5492 * through the sWidth parameter). This can be useful when the width of the table's 5493 * parent element changes (for example a window resize). 5494 * @param {boolean} [bRedraw=true] Redraw the table or not, you will typically want to 5495 * @dtopt API 5496 * @deprecated Since v1.10 5497 * 5498 * @example 5499 * $(document).ready(function() { 5500 * var oTable = $('#example').dataTable( { 5501 * "sScrollY": "200px", 5502 * "bPaginate": false 5503 * } ); 5504 * 5505 * $(window).bind('resize', function () { 5506 * oTable.fnAdjustColumnSizing(); 5507 * } ); 5508 * } ); 5509 */ 5510 this.fnAdjustColumnSizing = function ( bRedraw ) 5511 { 5512 var api = this.api( true ).columns.adjust(); 5513 var settings = api.settings()[0]; 5514 var scroll = settings.oScroll; 5515 5516 if ( bRedraw === undefined || bRedraw ) { 5517 api.draw( false ); 5518 } 5519 else if ( scroll.sX !== "" || scroll.sY !== "" ) { 5520 /* If not redrawing, but scrolling, we want to apply the new column sizes anyway */ 5521 _fnScrollDraw( settings ); 5522 } 5523 }; 5524 5525 5526 /** 5527 * Quickly and simply clear a table 5528 * @param {bool} [bRedraw=true] redraw the table or not 5529 * @dtopt API 5530 * @deprecated Since v1.10 5531 * 5532 * @example 5533 * $(document).ready(function() { 5534 * var oTable = $('#example').dataTable(); 5535 * 5536 * // Immediately 'nuke' the current rows (perhaps waiting for an Ajax callback...) 5537 * oTable.fnClearTable(); 5538 * } ); 5539 */ 5540 this.fnClearTable = function( bRedraw ) 5541 { 5542 var api = this.api( true ).clear(); 5543 5544 if ( bRedraw === undefined || bRedraw ) { 5545 api.draw(); 5546 } 5547 }; 5548 5549 5550 /** 5551 * The exact opposite of 'opening' a row, this function will close any rows which 5552 * are currently 'open'. 5553 * @param {node} nTr the table row to 'close' 5554 * @returns {int} 0 on success, or 1 if failed (can't find the row) 5555 * @dtopt API 5556 * @deprecated Since v1.10 5557 * 5558 * @example 5559 * $(document).ready(function() { 5560 * var oTable; 5561 * 5562 * // 'open' an information row when a row is clicked on 5563 * $('#example tbody tr').click( function () { 5564 * if ( oTable.fnIsOpen(this) ) { 5565 * oTable.fnClose( this ); 5566 * } else { 5567 * oTable.fnOpen( this, "Temporary row opened", "info_row" ); 5568 * } 5569 * } ); 5570 * 5571 * oTable = $('#example').dataTable(); 5572 * } ); 5573 */ 5574 this.fnClose = function( nTr ) 5575 { 5576 this.api( true ).row( nTr ).child.hide(); 5577 }; 5578 5579 5580 /** 5581 * Remove a row for the table 5582 * @param {mixed} target The index of the row from aoData to be deleted, or 5583 * the TR element you want to delete 5584 * @param {function|null} [callBack] Callback function 5585 * @param {bool} [redraw=true] Redraw the table or not 5586 * @returns {array} The row that was deleted 5587 * @dtopt API 5588 * @deprecated Since v1.10 5589 * 5590 * @example 5591 * $(document).ready(function() { 5592 * var oTable = $('#example').dataTable(); 5593 * 5594 * // Immediately remove the first row 5595 * oTable.fnDeleteRow( 0 ); 5596 * } ); 5597 */ 5598 this.fnDeleteRow = function( target, callback, redraw ) 5599 { 5600 var api = this.api( true ); 5601 var rows = api.rows( target ); 5602 var settings = rows.settings()[0]; 5603 var data = settings.aoData[ rows[0][0] ]; 5604 5605 rows.remove(); 5606 5607 if ( callback ) { 5608 callback.call( this, settings, data ); 5609 } 5610 5611 if ( redraw === undefined || redraw ) { 5612 api.draw(); 5613 } 5614 5615 return data; 5616 }; 5617 5618 5619 /** 5620 * Restore the table to it's original state in the DOM by removing all of DataTables 5621 * enhancements, alterations to the DOM structure of the table and event listeners. 5622 * @param {boolean} [remove=false] Completely remove the table from the DOM 5623 * @dtopt API 5624 * @deprecated Since v1.10 5625 * 5626 * @example 5627 * $(document).ready(function() { 5628 * // This example is fairly pointless in reality, but shows how fnDestroy can be used 5629 * var oTable = $('#example').dataTable(); 5630 * oTable.fnDestroy(); 5631 * } ); 5632 */ 5633 this.fnDestroy = function ( remove ) 5634 { 5635 this.api( true ).destroy( remove ); 5636 }; 5637 5638 5639 /** 5640 * Redraw the table 5641 * @param {bool} [complete=true] Re-filter and resort (if enabled) the table before the draw. 5642 * @dtopt API 5643 * @deprecated Since v1.10 5644 * 5645 * @example 5646 * $(document).ready(function() { 5647 * var oTable = $('#example').dataTable(); 5648 * 5649 * // Re-draw the table - you wouldn't want to do it here, but it's an example :-) 5650 * oTable.fnDraw(); 5651 * } ); 5652 */ 5653 this.fnDraw = function( complete ) 5654 { 5655 // Note that this isn't an exact match to the old call to _fnDraw - it takes 5656 // into account the new data, but can hold position. 5657 this.api( true ).draw( complete ); 5658 }; 5659 5660 5661 /** 5662 * Filter the input based on data 5663 * @param {string} sInput String to filter the table on 5664 * @param {int|null} [iColumn] Column to limit filtering to 5665 * @param {bool} [bRegex=false] Treat as regular expression or not 5666 * @param {bool} [bSmart=true] Perform smart filtering or not 5667 * @param {bool} [bShowGlobal=true] Show the input global filter in it's input box(es) 5668 * @param {bool} [bCaseInsensitive=true] Do case-insensitive matching (true) or not (false) 5669 * @dtopt API 5670 * @deprecated Since v1.10 5671 * 5672 * @example 5673 * $(document).ready(function() { 5674 * var oTable = $('#example').dataTable(); 5675 * 5676 * // Sometime later - filter... 5677 * oTable.fnFilter( 'test string' ); 5678 * } ); 5679 */ 5680 this.fnFilter = function( sInput, iColumn, bRegex, bSmart, bShowGlobal, bCaseInsensitive ) 5681 { 5682 var api = this.api( true ); 5683 5684 if ( iColumn === null || iColumn === undefined ) { 5685 api.search( sInput, bRegex, bSmart, bCaseInsensitive ); 5686 } 5687 else { 5688 api.column( iColumn ).search( sInput, bRegex, bSmart, bCaseInsensitive ); 5689 } 5690 5691 api.draw(); 5692 }; 5693 5694 5695 /** 5696 * Get the data for the whole table, an individual row or an individual cell based on the 5697 * provided parameters. 5698 * @param {int|node} [src] A TR row node, TD/TH cell node or an integer. If given as 5699 * a TR node then the data source for the whole row will be returned. If given as a 5700 * TD/TH cell node then iCol will be automatically calculated and the data for the 5701 * cell returned. If given as an integer, then this is treated as the aoData internal 5702 * data index for the row (see fnGetPosition) and the data for that row used. 5703 * @param {int} [col] Optional column index that you want the data of. 5704 * @returns {array|object|string} If mRow is undefined, then the data for all rows is 5705 * returned. If mRow is defined, just data for that row, and is iCol is 5706 * defined, only data for the designated cell is returned. 5707 * @dtopt API 5708 * @deprecated Since v1.10 5709 * 5710 * @example 5711 * // Row data 5712 * $(document).ready(function() { 5713 * oTable = $('#example').dataTable(); 5714 * 5715 * oTable.$('tr').click( function () { 5716 * var data = oTable.fnGetData( this ); 5717 * // ... do something with the array / object of data for the row 5718 * } ); 5719 * } ); 5720 * 5721 * @example 5722 * // Individual cell data 5723 * $(document).ready(function() { 5724 * oTable = $('#example').dataTable(); 5725 * 5726 * oTable.$('td').click( function () { 5727 * var sData = oTable.fnGetData( this ); 5728 * alert( 'The cell clicked on had the value of '+sData ); 5729 * } ); 5730 * } ); 5731 */ 5732 this.fnGetData = function( src, col ) 5733 { 5734 var api = this.api( true ); 5735 5736 if ( src !== undefined ) { 5737 var type = src.nodeName ? src.nodeName.toLowerCase() : ''; 5738 5739 return col !== undefined || type == 'td' || type == 'th' ? 5740 api.cell( src, col ).data() : 5741 api.row( src ).data() || null; 5742 } 5743 5744 return api.data().toArray(); 5745 }; 5746 5747 5748 /** 5749 * Get an array of the TR nodes that are used in the table's body. Note that you will 5750 * typically want to use the '$' API method in preference to this as it is more 5751 * flexible. 5752 * @param {int} [iRow] Optional row index for the TR element you want 5753 * @returns {array|node} If iRow is undefined, returns an array of all TR elements 5754 * in the table's body, or iRow is defined, just the TR element requested. 5755 * @dtopt API 5756 * @deprecated Since v1.10 5757 * 5758 * @example 5759 * $(document).ready(function() { 5760 * var oTable = $('#example').dataTable(); 5761 * 5762 * // Get the nodes from the table 5763 * var nNodes = oTable.fnGetNodes( ); 5764 * } ); 5765 */ 5766 this.fnGetNodes = function( iRow ) 5767 { 5768 var api = this.api( true ); 5769 5770 return iRow !== undefined ? 5771 api.row( iRow ).node() : 5772 api.rows().nodes().flatten().toArray(); 5773 }; 5774 5775 5776 /** 5777 * Get the array indexes of a particular cell from it's DOM element 5778 * and column index including hidden columns 5779 * @param {node} node this can either be a TR, TD or TH in the table's body 5780 * @returns {int} If nNode is given as a TR, then a single index is returned, or 5781 * if given as a cell, an array of [row index, column index (visible), 5782 * column index (all)] is given. 5783 * @dtopt API 5784 * @deprecated Since v1.10 5785 * 5786 * @example 5787 * $(document).ready(function() { 5788 * $('#example tbody td').click( function () { 5789 * // Get the position of the current data from the node 5790 * var aPos = oTable.fnGetPosition( this ); 5791 * 5792 * // Get the data array for this row 5793 * var aData = oTable.fnGetData( aPos[0] ); 5794 * 5795 * // Update the data array and return the value 5796 * aData[ aPos[1] ] = 'clicked'; 5797 * this.innerHTML = 'clicked'; 5798 * } ); 5799 * 5800 * // Init DataTables 5801 * oTable = $('#example').dataTable(); 5802 * } ); 5803 */ 5804 this.fnGetPosition = function( node ) 5805 { 5806 var api = this.api( true ); 5807 var nodeName = node.nodeName.toUpperCase(); 5808 5809 if ( nodeName == 'TR' ) { 5810 return api.row( node ).index(); 5811 } 5812 else if ( nodeName == 'TD' || nodeName == 'TH' ) { 5813 var cell = api.cell( node ).index(); 5814 5815 return [ 5816 cell.row, 5817 cell.columnVisible, 5818 cell.column 5819 ]; 5820 } 5821 return null; 5822 }; 5823 5824 5825 /** 5826 * Check to see if a row is 'open' or not. 5827 * @param {node} nTr the table row to check 5828 * @returns {boolean} true if the row is currently open, false otherwise 5829 * @dtopt API 5830 * @deprecated Since v1.10 5831 * 5832 * @example 5833 * $(document).ready(function() { 5834 * var oTable; 5835 * 5836 * // 'open' an information row when a row is clicked on 5837 * $('#example tbody tr').click( function () { 5838 * if ( oTable.fnIsOpen(this) ) { 5839 * oTable.fnClose( this ); 5840 * } else { 5841 * oTable.fnOpen( this, "Temporary row opened", "info_row" ); 5842 * } 5843 * } ); 5844 * 5845 * oTable = $('#example').dataTable(); 5846 * } ); 5847 */ 5848 this.fnIsOpen = function( nTr ) 5849 { 5850 return this.api( true ).row( nTr ).child.isShown(); 5851 }; 5852 5853 5854 /** 5855 * This function will place a new row directly after a row which is currently 5856 * on display on the page, with the HTML contents that is passed into the 5857 * function. This can be used, for example, to ask for confirmation that a 5858 * particular record should be deleted. 5859 * @param {node} nTr The table row to 'open' 5860 * @param {string|node|jQuery} mHtml The HTML to put into the row 5861 * @param {string} sClass Class to give the new TD cell 5862 * @returns {node} The row opened. Note that if the table row passed in as the 5863 * first parameter, is not found in the table, this method will silently 5864 * return. 5865 * @dtopt API 5866 * @deprecated Since v1.10 5867 * 5868 * @example 5869 * $(document).ready(function() { 5870 * var oTable; 5871 * 5872 * // 'open' an information row when a row is clicked on 5873 * $('#example tbody tr').click( function () { 5874 * if ( oTable.fnIsOpen(this) ) { 5875 * oTable.fnClose( this ); 5876 * } else { 5877 * oTable.fnOpen( this, "Temporary row opened", "info_row" ); 5878 * } 5879 * } ); 5880 * 5881 * oTable = $('#example').dataTable(); 5882 * } ); 5883 */ 5884 this.fnOpen = function( nTr, mHtml, sClass ) 5885 { 5886 return this.api( true ) 5887 .row( nTr ) 5888 .child( mHtml, sClass ) 5889 .show() 5890 .child()[0]; 5891 }; 5892 5893 5894 /** 5895 * Change the pagination - provides the internal logic for pagination in a simple API 5896 * function. With this function you can have a DataTables table go to the next, 5897 * previous, first or last pages. 5898 * @param {string|int} mAction Paging action to take: "first", "previous", "next" or "last" 5899 * or page number to jump to (integer), note that page 0 is the first page. 5900 * @param {bool} [bRedraw=true] Redraw the table or not 5901 * @dtopt API 5902 * @deprecated Since v1.10 5903 * 5904 * @example 5905 * $(document).ready(function() { 5906 * var oTable = $('#example').dataTable(); 5907 * oTable.fnPageChange( 'next' ); 5908 * } ); 5909 */ 5910 this.fnPageChange = function ( mAction, bRedraw ) 5911 { 5912 var api = this.api( true ).page( mAction ); 5913 5914 if ( bRedraw === undefined || bRedraw ) { 5915 api.draw(false); 5916 } 5917 }; 5918 5919 5920 /** 5921 * Show a particular column 5922 * @param {int} iCol The column whose display should be changed 5923 * @param {bool} bShow Show (true) or hide (false) the column 5924 * @param {bool} [bRedraw=true] Redraw the table or not 5925 * @dtopt API 5926 * @deprecated Since v1.10 5927 * 5928 * @example 5929 * $(document).ready(function() { 5930 * var oTable = $('#example').dataTable(); 5931 * 5932 * // Hide the second column after initialisation 5933 * oTable.fnSetColumnVis( 1, false ); 5934 * } ); 5935 */ 5936 this.fnSetColumnVis = function ( iCol, bShow, bRedraw ) 5937 { 5938 var api = this.api( true ).column( iCol ).visible( bShow ); 5939 5940 if ( bRedraw === undefined || bRedraw ) { 5941 api.columns.adjust().draw(); 5942 } 5943 }; 5944 5945 5946 /** 5947 * Get the settings for a particular table for external manipulation 5948 * @returns {object} DataTables settings object. See 5949 * {@link DataTable.models.oSettings} 5950 * @dtopt API 5951 * @deprecated Since v1.10 5952 * 5953 * @example 5954 * $(document).ready(function() { 5955 * var oTable = $('#example').dataTable(); 5956 * var oSettings = oTable.fnSettings(); 5957 * 5958 * // Show an example parameter from the settings 5959 * alert( oSettings._iDisplayStart ); 5960 * } ); 5961 */ 5962 this.fnSettings = function() 5963 { 5964 return _fnSettingsFromNode( this[_ext.iApiIndex] ); 5965 }; 5966 5967 5968 /** 5969 * Sort the table by a particular column 5970 * @param {int} iCol the data index to sort on. Note that this will not match the 5971 * 'display index' if you have hidden data entries 5972 * @dtopt API 5973 * @deprecated Since v1.10 5974 * 5975 * @example 5976 * $(document).ready(function() { 5977 * var oTable = $('#example').dataTable(); 5978 * 5979 * // Sort immediately with columns 0 and 1 5980 * oTable.fnSort( [ [0,'asc'], [1,'asc'] ] ); 5981 * } ); 5982 */ 5983 this.fnSort = function( aaSort ) 5984 { 5985 this.api( true ).order( aaSort ).draw(); 5986 }; 5987 5988 5989 /** 5990 * Attach a sort listener to an element for a given column 5991 * @param {node} nNode the element to attach the sort listener to 5992 * @param {int} iColumn the column that a click on this node will sort on 5993 * @param {function} [fnCallback] callback function when sort is run 5994 * @dtopt API 5995 * @deprecated Since v1.10 5996 * 5997 * @example 5998 * $(document).ready(function() { 5999 * var oTable = $('#example').dataTable(); 6000 * 6001 * // Sort on column 1, when 'sorter' is clicked on 6002 * oTable.fnSortListener( document.getElementById('sorter'), 1 ); 6003 * } ); 6004 */ 6005 this.fnSortListener = function( nNode, iColumn, fnCallback ) 6006 { 6007 this.api( true ).order.listener( nNode, iColumn, fnCallback ); 6008 }; 6009 6010 6011 /** 6012 * Update a table cell or row - this method will accept either a single value to 6013 * update the cell with, an array of values with one element for each column or 6014 * an object in the same format as the original data source. The function is 6015 * self-referencing in order to make the multi column updates easier. 6016 * @param {object|array|string} mData Data to update the cell/row with 6017 * @param {node|int} mRow TR element you want to update or the aoData index 6018 * @param {int} [iColumn] The column to update, give as null or undefined to 6019 * update a whole row. 6020 * @param {bool} [bRedraw=true] Redraw the table or not 6021 * @param {bool} [bAction=true] Perform pre-draw actions or not 6022 * @returns {int} 0 on success, 1 on error 6023 * @dtopt API 6024 * @deprecated Since v1.10 6025 * 6026 * @example 6027 * $(document).ready(function() { 6028 * var oTable = $('#example').dataTable(); 6029 * oTable.fnUpdate( 'Example update', 0, 0 ); // Single cell 6030 * oTable.fnUpdate( ['a', 'b', 'c', 'd', 'e'], $('tbody tr')[0] ); // Row 6031 * } ); 6032 */ 6033 this.fnUpdate = function( mData, mRow, iColumn, bRedraw, bAction ) 6034 { 6035 var api = this.api( true ); 6036 6037 if ( iColumn === undefined || iColumn === null ) { 6038 api.row( mRow ).data( mData ); 6039 } 6040 else { 6041 api.cell( mRow, iColumn ).data( mData ); 6042 } 6043 6044 if ( bAction === undefined || bAction ) { 6045 api.columns.adjust(); 6046 } 6047 6048 if ( bRedraw === undefined || bRedraw ) { 6049 api.draw(); 6050 } 6051 return 0; 6052 }; 6053 6054 6055 /** 6056 * Provide a common method for plug-ins to check the version of DataTables being used, in order 6057 * to ensure compatibility. 6058 * @param {string} sVersion Version string to check for, in the format "X.Y.Z". Note that the 6059 * formats "X" and "X.Y" are also acceptable. 6060 * @returns {boolean} true if this version of DataTables is greater or equal to the required 6061 * version, or false if this version of DataTales is not suitable 6062 * @method 6063 * @dtopt API 6064 * @deprecated Since v1.10 6065 * 6066 * @example 6067 * $(document).ready(function() { 6068 * var oTable = $('#example').dataTable(); 6069 * alert( oTable.fnVersionCheck( '1.9.0' ) ); 6070 * } ); 6071 */ 6072 this.fnVersionCheck = _ext.fnVersionCheck; 6073 6074 6075 var _that = this; 6076 var emptyInit = options === undefined; 6077 var len = this.length; 6078 6079 if ( emptyInit ) { 6080 options = {}; 6081 } 6082 6083 this.oApi = this.internal = _ext.internal; 6084 6085 // Extend with old style plug-in API methods 6086 for ( var fn in DataTable.ext.internal ) { 6087 if ( fn ) { 6088 this[fn] = _fnExternApiFunc(fn); 6089 } 6090 } 6091 6092 this.each(function() { 6093 // For each initialisation we want to give it a clean initialisation 6094 // object that can be bashed around 6095 var o = {}; 6096 var oInit = len > 1 ? // optimisation for single table case 6097 _fnExtend( o, options, true ) : 6098 options; 6099 6100 /*global oInit,_that,emptyInit*/ 6101 var i=0, iLen, j, jLen, k, kLen; 6102 var sId = this.getAttribute( 'id' ); 6103 var bInitHandedOff = false; 6104 var defaults = DataTable.defaults; 6105 var $this = $(this); 6106 6107 6108 /* Sanity check */ 6109 if ( this.nodeName.toLowerCase() != 'table' ) 6110 { 6111 _fnLog( null, 0, 'Non-table node initialisation ('+this.nodeName+')', 2 ); 6112 return; 6113 } 6114 6115 /* Backwards compatibility for the defaults */ 6116 _fnCompatOpts( defaults ); 6117 _fnCompatCols( defaults.column ); 6118 6119 /* Convert the camel-case defaults to Hungarian */ 6120 _fnCamelToHungarian( defaults, defaults, true ); 6121 _fnCamelToHungarian( defaults.column, defaults.column, true ); 6122 6123 /* Setting up the initialisation object */ 6124 _fnCamelToHungarian( defaults, $.extend( oInit, $this.data() ) ); 6125 6126 6127 6128 /* Check to see if we are re-initialising a table */ 6129 var allSettings = DataTable.settings; 6130 for ( i=0, iLen=allSettings.length ; i<iLen ; i++ ) 6131 { 6132 var s = allSettings[i]; 6133 6134 /* Base check on table node */ 6135 if ( s.nTable == this || s.nTHead.parentNode == this || (s.nTFoot && s.nTFoot.parentNode == this) ) 6136 { 6137 var bRetrieve = oInit.bRetrieve !== undefined ? oInit.bRetrieve : defaults.bRetrieve; 6138 var bDestroy = oInit.bDestroy !== undefined ? oInit.bDestroy : defaults.bDestroy; 6139 6140 if ( emptyInit || bRetrieve ) 6141 { 6142 return s.oInstance; 6143 } 6144 else if ( bDestroy ) 6145 { 6146 s.oInstance.fnDestroy(); 6147 break; 6148 } 6149 else 6150 { 6151 _fnLog( s, 0, 'Cannot reinitialise DataTable', 3 ); 6152 return; 6153 } 6154 } 6155 6156 /* If the element we are initialising has the same ID as a table which was previously 6157 * initialised, but the table nodes don't match (from before) then we destroy the old 6158 * instance by simply deleting it. This is under the assumption that the table has been 6159 * destroyed by other methods. Anyone using non-id selectors will need to do this manually 6160 */ 6161 if ( s.sTableId == this.id ) 6162 { 6163 allSettings.splice( i, 1 ); 6164 break; 6165 } 6166 } 6167 6168 /* Ensure the table has an ID - required for accessibility */ 6169 if ( sId === null || sId === "" ) 6170 { 6171 sId = "DataTables_Table_"+(DataTable.ext._unique++); 6172 this.id = sId; 6173 } 6174 6175 /* Create the settings object for this table and set some of the default parameters */ 6176 var oSettings = $.extend( true, {}, DataTable.models.oSettings, { 6177 "sDestroyWidth": $this[0].style.width, 6178 "sInstance": sId, 6179 "sTableId": sId 6180 } ); 6181 oSettings.nTable = this; 6182 oSettings.oApi = _that.internal; 6183 oSettings.oInit = oInit; 6184 6185 allSettings.push( oSettings ); 6186 6187 // Need to add the instance after the instance after the settings object has been added 6188 // to the settings array, so we can self reference the table instance if more than one 6189 oSettings.oInstance = (_that.length===1) ? _that : $this.dataTable(); 6190 6191 // Backwards compatibility, before we apply all the defaults 6192 _fnCompatOpts( oInit ); 6193 6194 if ( oInit.oLanguage ) 6195 { 6196 _fnLanguageCompat( oInit.oLanguage ); 6197 } 6198 6199 // If the length menu is given, but the init display length is not, use the length menu 6200 if ( oInit.aLengthMenu && ! oInit.iDisplayLength ) 6201 { 6202 oInit.iDisplayLength = $.isArray( oInit.aLengthMenu[0] ) ? 6203 oInit.aLengthMenu[0][0] : oInit.aLengthMenu[0]; 6204 } 6205 6206 // Apply the defaults and init options to make a single init object will all 6207 // options defined from defaults and instance options. 6208 oInit = _fnExtend( $.extend( true, {}, defaults ), oInit ); 6209 6210 6211 // Map the initialisation options onto the settings object 6212 _fnMap( oSettings.oFeatures, oInit, [ 6213 "bPaginate", 6214 "bLengthChange", 6215 "bFilter", 6216 "bSort", 6217 "bSortMulti", 6218 "bInfo", 6219 "bProcessing", 6220 "bAutoWidth", 6221 "bSortClasses", 6222 "bServerSide", 6223 "bDeferRender" 6224 ] ); 6225 _fnMap( oSettings, oInit, [ 6226 "asStripeClasses", 6227 "ajax", 6228 "fnServerData", 6229 "fnFormatNumber", 6230 "sServerMethod", 6231 "aaSorting", 6232 "aaSortingFixed", 6233 "aLengthMenu", 6234 "sPaginationType", 6235 "sAjaxSource", 6236 "sAjaxDataProp", 6237 "iStateDuration", 6238 "sDom", 6239 "bSortCellsTop", 6240 "iTabIndex", 6241 "fnStateLoadCallback", 6242 "fnStateSaveCallback", 6243 "renderer", 6244 "searchDelay", 6245 [ "iCookieDuration", "iStateDuration" ], // backwards compat 6246 [ "oSearch", "oPreviousSearch" ], 6247 [ "aoSearchCols", "aoPreSearchCols" ], 6248 [ "iDisplayLength", "_iDisplayLength" ], 6249 [ "bJQueryUI", "bJUI" ] 6250 ] ); 6251 _fnMap( oSettings.oScroll, oInit, [ 6252 [ "sScrollX", "sX" ], 6253 [ "sScrollXInner", "sXInner" ], 6254 [ "sScrollY", "sY" ],
6255 [ "bScrollCollapse", "bCollapse" ] 6256 ] ); 6257 _fnMap( oSettings.oLanguage, oInit, "fnInfoCallback" ); 6258 6259 /* Callback functions which are array driven */ 6260 _fnCallbackReg( oSettings, 'aoDrawCallback', oInit.fnDrawCallback, 'user' ); 6261 _fnCallbackReg( oSettings, 'aoServerParams', oInit.fnServerParams, 'user' ); 6262 _fnCallbackReg( oSettings, 'aoStateSaveParams', oInit.fnStateSaveParams, 'user' ); 6263 _fnCallbackReg( oSettings, 'aoStateLoadParams', oInit.fnStateLoadParams, 'user' ); 6264 _fnCallbackReg( oSettings, 'aoStateLoaded', oInit.fnStateLoaded, 'user' ); 6265 _fnCallbackReg( oSettings, 'aoRowCallback', oInit.fnRowCallback, 'user' ); 6266 _fnCallbackReg( oSettings, 'aoRowCreatedCallback', oInit.fnCreatedRow, 'user' ); 6267 _fnCallbackReg( oSettings, 'aoHeaderCallback', oInit.fnHeaderCallback, 'user' ); 6268 _fnCallbackReg( oSettings, 'aoFooterCallback', oInit.fnFooterCallback, 'user' ); 6269 _fnCallbackReg( oSettings, 'aoInitComplete', oInit.fnInitComplete, 'user' ); 6270 _fnCallbackReg( oSettings, 'aoPreDrawCallback', oInit.fnPreDrawCallback, 'user' ); 6271 6272 var oClasses = oSettings.oClasses; 6273 6274 // @todo Remove in 1.11 6275 if ( oInit.bJQueryUI ) 6276 { 6277 /* Use the JUI classes object for display. You could clone the oStdClasses object if 6278 * you want to have multiple tables with multiple independent classes 6279 */ 6280 $.extend( oClasses, DataTable.ext.oJUIClasses, oInit.oClasses ); 6281 6282 if ( oInit.sDom === defaults.sDom && defaults.sDom === "lfrtip" ) 6283 { 6284 /* Set the DOM to use a layout suitable for jQuery UI's theming */ 6285 oSettings.sDom = '<"H"lfr>t<"F"ip>'; 6286 } 6287 6288 if ( ! oSettings.renderer ) { 6289 oSettings.renderer = 'jqueryui'; 6290 } 6291 else if ( $.isPlainObject( oSettings.renderer ) && ! oSettings.renderer.header ) { 6292 oSettings.renderer.header = 'jqueryui'; 6293 } 6294 } 6295 else 6296 { 6297 $.extend( oClasses, DataTable.ext.classes, oInit.oClasses ); 6298 } 6299 $this.addClass( oClasses.sTable ); 6300 6301 /* Calculate the scroll bar width and cache it for use later on */ 6302 if ( oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "" ) 6303 { 6304 oSettings.oScroll.iBarWidth = _fnScrollBarWidth(); 6305 } 6306 if ( oSettings.oScroll.sX === true ) { // Easy initialisation of x-scrolling 6307 oSettings.oScroll.sX = '100%'; 6308 } 6309 6310 if ( oSettings.iInitDisplayStart === undefined ) 6311 { 6312 /* Display start point, taking into account the save saving */ 6313 oSettings.iInitDisplayStart = oInit.iDisplayStart; 6314 oSettings._iDisplayStart = oInit.iDisplayStart; 6315 } 6316 6317 if ( oInit.iDeferLoading !== null ) 6318 { 6319 oSettings.bDeferLoading = true; 6320 var tmp = $.isArray( oInit.iDeferLoading ); 6321 oSettings._iRecordsDisplay = tmp ? oInit.iDeferLoading[0] : oInit.iDeferLoading; 6322 oSettings._iRecordsTotal = tmp ? oInit.iDeferLoading[1] : oInit.iDeferLoading; 6323 } 6324 6325 /* Language definitions */ 6326 var oLanguage = oSettings.oLanguage; 6327 $.extend( true, oLanguage, oInit.oLanguage ); 6328 6329 if ( oLanguage.sUrl !== "" ) 6330 { 6331 /* Get the language definitions from a file - because this Ajax call makes the language 6332 * get async to the remainder of this function we use bInitHandedOff to indicate that 6333 * _fnInitialise will be fired by the returned Ajax handler, rather than the constructor 6334 */ 6335 $.ajax( { 6336 dataType: 'json', 6337 url: oLanguage.sUrl, 6338 success: function ( json ) { 6339 _fnLanguageCompat( json ); 6340 _fnCamelToHungarian( defaults.oLanguage, json ); 6341 $.extend( true, oLanguage, json ); 6342 _fnInitialise( oSettings ); 6343 }, 6344 error: function () { 6345 // Error occurred loading language file, continue on as best we can 6346 _fnInitialise( oSettings ); 6347 } 6348 } ); 6349 bInitHandedOff = true; 6350 } 6351 6352 /* 6353 * Stripes 6354 */ 6355 if ( oInit.asStripeClasses === null ) 6356 { 6357 oSettings.asStripeClasses =[ 6358 oClasses.sStripeOdd, 6359 oClasses.sStripeEven 6360 ]; 6361 } 6362 6363 /* Remove row stripe classes if they are already on the table row */ 6364 var stripeClasses = oSettings.asStripeClasses; 6365 var rowOne = $this.children('tbody').find('tr').eq(0); 6366 if ( $.inArray( true, $.map( stripeClasses, function(el, i) { 6367 return rowOne.hasClass(el); 6368 } ) ) !== -1 ) { 6369 $('tbody tr', this).removeClass( stripeClasses.join(' ') ); 6370 oSettings.asDestroyStripes = stripeClasses.slice(); 6371 } 6372 6373 /* 6374 * Columns 6375 * See if we should load columns automatically or use defined ones 6376 */ 6377 var anThs = []; 6378 var aoColumnsInit; 6379 var nThead = this.getElementsByTagName('thead'); 6380 if ( nThead.length !== 0 ) 6381 { 6382 _fnDetectHeader( oSettings.aoHeader, nThead[0] ); 6383 anThs = _fnGetUniqueThs( oSettings ); 6384 } 6385 6386 /* If not given a column array, generate one with nulls */ 6387 if ( oInit.aoColumns === null ) 6388 { 6389 aoColumnsInit = []; 6390 for ( i=0, iLen=anThs.length ; i<iLen ; i++ ) 6391 { 6392 aoColumnsInit.push( null ); 6393 } 6394 } 6395 else 6396 {
vendor: 62,586 bytes, lines 6397-8792
6397 aoColumnsInit = oInit.aoColumns; 6398 } 6399 6400 /* Add the columns */ 6401 for ( i=0, iLen=aoColumnsInit.length ; i<iLen ; i++ ) 6402 { 6403 _fnAddColumn( oSettings, anThs ? anThs[i] : null ); 6404 } 6405 6406 /* Apply the column definitions */ 6407 _fnApplyColumnDefs( oSettings, oInit.aoColumnDefs, aoColumnsInit, function (iCol, oDef) { 6408 _fnColumnOptions( oSettings, iCol, oDef ); 6409 } ); 6410 6411 /* HTML5 attribute detection - build an mData object automatically if the 6412 * attributes are found 6413 */ 6414 if ( rowOne.length ) { 6415 var a = function ( cell, name ) { 6416 return cell.getAttribute( 'data-'+name ) !== null ? name : null; 6417 }; 6418 6419 $.each( _fnGetRowElements( oSettings, rowOne[0] ).cells, function (i, cell) { 6420 var col = oSettings.aoColumns[i]; 6421 6422 if ( col.mData === i ) { 6423 var sort = a( cell, 'sort' ) || a( cell, 'order' ); 6424 var filter = a( cell, 'filter' ) || a( cell, 'search' ); 6425 6426 if ( sort !== null || filter !== null ) { 6427 col.mData = { 6428 _: i+'.display', 6429 sort: sort !== null ? i+'.@data-'+sort : undefined, 6430 type: sort !== null ? i+'.@data-'+sort : undefined, 6431 filter: filter !== null ? i+'.@data-'+filter : undefined 6432 }; 6433 6434 _fnColumnOptions( oSettings, i ); 6435 } 6436 } 6437 } ); 6438 } 6439 6440 var features = oSettings.oFeatures; 6441 6442 /* Must be done after everything which can be overridden by the state saving! */ 6443 if ( oInit.bStateSave ) 6444 { 6445 features.bStateSave = true; 6446 _fnLoadState( oSettings, oInit ); 6447 _fnCallbackReg( oSettings, 'aoDrawCallback', _fnSaveState, 'state_save' ); 6448 } 6449 6450 6451 /* 6452 * Sorting 6453 * @todo For modularisation (1.11) this needs to do into a sort start up handler 6454 */ 6455 6456 // If aaSorting is not defined, then we use the first indicator in asSorting 6457 // in case that has been altered, so the default sort reflects that option 6458 if ( oInit.aaSorting === undefined ) 6459 { 6460 var sorting = oSettings.aaSorting; 6461 for ( i=0, iLen=sorting.length ; i<iLen ; i++ ) 6462 { 6463 sorting[i][1] = oSettings.aoColumns[ i ].asSorting[0]; 6464 } 6465 } 6466 6467 /* Do a first pass on the sorting classes (allows any size changes to be taken into 6468 * account, and also will apply sorting disabled classes if disabled 6469 */ 6470 _fnSortingClasses( oSettings ); 6471 6472 if ( features.bSort ) 6473 { 6474 _fnCallbackReg( oSettings, 'aoDrawCallback', function () { 6475 if ( oSettings.bSorted ) { 6476 var aSort = _fnSortFlatten( oSettings ); 6477 var sortedColumns = {}; 6478 6479 $.each( aSort, function (i, val) { 6480 sortedColumns[ val.src ] = val.dir; 6481 } ); 6482 6483 _fnCallbackFire( oSettings, null, 'order', [oSettings, aSort, sortedColumns] ); 6484 _fnSortAria( oSettings ); 6485 } 6486 } ); 6487 } 6488 6489 _fnCallbackReg( oSettings, 'aoDrawCallback', function () { 6490 if ( oSettings.bSorted || _fnDataSource( oSettings ) === 'ssp' || features.bDeferRender ) { 6491 _fnSortingClasses( oSettings ); 6492 } 6493 }, 'sc' ); 6494 6495 6496 /* 6497 * Final init 6498 * Cache the header, body and footer as required, creating them if needed 6499 */ 6500 6501 /* Browser support detection */ 6502 _fnBrowserDetect( oSettings ); 6503 6504 // Work around for Webkit bug 83867 - store the caption-side before removing from doc 6505 var captions = $this.children('caption').each( function () { 6506 this._captionSide = $this.css('caption-side'); 6507 } ); 6508 6509 var thead = $this.children('thead'); 6510 if ( thead.length === 0 ) 6511 { 6512 thead = $('<thead/>').appendTo(this); 6513 } 6514 oSettings.nTHead = thead[0]; 6515 6516 var tbody = $this.children('tbody'); 6517 if ( tbody.length === 0 ) 6518 { 6519 tbody = $('<tbody/>').appendTo(this); 6520 } 6521 oSettings.nTBody = tbody[0]; 6522 6523 var tfoot = $this.children('tfoot'); 6524 if ( tfoot.length === 0 && captions.length > 0 && (oSettings.oScroll.sX !== "" || oSettings.oScroll.sY !== "") ) 6525 { 6526 // If we are a scrolling table, and no footer has been given, then we need to create 6527 // a tfoot element for the caption element to be appended to 6528 tfoot = $('<tfoot/>').appendTo(this); 6529 } 6530 6531 if ( tfoot.length === 0 || tfoot.children().length === 0 ) { 6532 $this.addClass( oClasses.sNoFooter ); 6533 } 6534 else if ( tfoot.length > 0 ) { 6535 oSettings.nTFoot = tfoot[0]; 6536 _fnDetectHeader( oSettings.aoFooter, oSettings.nTFoot ); 6537 } 6538 6539 /* Check if there is data passing into the constructor */ 6540 if ( oInit.aaData ) 6541 { 6542 for ( i=0 ; i<oInit.aaData.length ; i++ ) 6543 { 6544 _fnAddData( oSettings, oInit.aaData[ i ] ); 6545 } 6546 } 6547 else if ( oSettings.bDeferLoading || _fnDataSource( oSettings ) == 'dom' ) 6548 { 6549 /* Grab the data from the page - only do this when deferred loading or no Ajax 6550 * source since there is no point in reading the DOM data if we are then going 6551 * to replace it with Ajax data 6552 */ 6553 _fnAddTr( oSettings, $(oSettings.nTBody).children('tr') ); 6554 } 6555 6556 /* Copy the data index array */ 6557 oSettings.aiDisplay = oSettings.aiDisplayMaster.slice(); 6558 6559 /* Initialisation complete - table can be drawn */ 6560 oSettings.bInitialised = true; 6561 6562 /* Check if we need to initialise the table (it might not have been handed off to the 6563 * language processor) 6564 */ 6565 if ( bInitHandedOff === false ) 6566 { 6567 _fnInitialise( oSettings ); 6568 } 6569 } ); 6570 _that = null; 6571 return this; 6572 }; 6573 6574 6575 6576 /** 6577 * Computed structure of the DataTables API, defined by the options passed to 6578 * `DataTable.Api.register()` when building the API. 6579 * 6580 * The structure is built in order to speed creation and extension of the Api 6581 * objects since the extensions are effectively pre-parsed. 6582 * 6583 * The array is an array of objects with the following structure, where this 6584 * base array represents the Api prototype base: 6585 * 6586 * [ 6587 * { 6588 * name: 'data' -- string - Property name 6589 * val: function () {}, -- function - Api method (or undefined if just an object 6590 * methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result 6591 * propExt: [ ... ] -- array - Array of Api object definitions to extend the property 6592 * }, 6593 * { 6594 * name: 'row' 6595 * val: {}, 6596 * methodExt: [ ... ], 6597 * propExt: [ 6598 * { 6599 * name: 'data' 6600 * val: function () {}, 6601 * methodExt: [ ... ], 6602 * propExt: [ ... ] 6603 * }, 6604 * ... 6605 * ] 6606 * } 6607 * ] 6608 * 6609 * @type {Array} 6610 * @ignore 6611 */ 6612 var __apiStruct = []; 6613 6614 6615 /** 6616 * `Array.prototype` reference. 6617 * 6618 * @type object 6619 * @ignore 6620 */ 6621 var __arrayProto = Array.prototype; 6622 6623 6624 /** 6625 * Abstraction for `context` parameter of the `Api` constructor to allow it to 6626 * take several different forms for ease of use. 6627 * 6628 * Each of the input parameter types will be converted to a DataTables settings 6629 * object where possible. 6630 * 6631 * @param {string|node|jQuery|object} mixed DataTable identifier. Can be one 6632 * of: 6633 * 6634 * * `string` - jQuery selector. Any DataTables' matching the given selector 6635 * with be found and used. 6636 * * `node` - `TABLE` node which has already been formed into a DataTable. 6637 * * `jQuery` - A jQuery object of `TABLE` nodes. 6638 * * `object` - DataTables settings object 6639 * * `DataTables.Api` - API instance 6640 * @return {array|null} Matching DataTables settings objects. `null` or 6641 * `undefined` is returned if no matching DataTable is found. 6642 * @ignore 6643 */ 6644 var _toSettings = function ( mixed ) 6645 { 6646 var idx, jq; 6647 var settings = DataTable.settings; 6648 var tables = $.map( settings, function (el, i) { 6649 return el.nTable; 6650 } ); 6651 6652 if ( ! mixed ) { 6653 return []; 6654 } 6655 else if ( mixed.nTable && mixed.oApi ) { 6656 // DataTables settings object 6657 return [ mixed ]; 6658 } 6659 else if ( mixed.nodeName && mixed.nodeName.toLowerCase() === 'table' ) { 6660 // Table node 6661 idx = $.inArray( mixed, tables ); 6662 return idx !== -1 ? [ settings[idx] ] : null; 6663 } 6664 else if ( mixed && typeof mixed.settings === 'function' ) { 6665 return mixed.settings().toArray(); 6666 } 6667 else if ( typeof mixed === 'string' ) { 6668 // jQuery selector 6669 jq = $(mixed); 6670 } 6671 else if ( mixed instanceof $ ) { 6672 // jQuery object (also DataTables instance) 6673 jq = mixed; 6674 } 6675 6676 if ( jq ) { 6677 return jq.map( function(i) { 6678 idx = $.inArray( this, tables ); 6679 return idx !== -1 ? settings[idx] : null; 6680 } ).toArray(); 6681 } 6682 }; 6683 6684 6685 /** 6686 * DataTables API class - used to control and interface with one or more 6687 * DataTables enhanced tables. 6688 * 6689 * The API class is heavily based on jQuery, presenting a chainable interface 6690 * that you can use to interact with tables. Each instance of the API class has 6691 * a "context" - i.e. the tables that it will operate on. This could be a single 6692 * table, all tables on a page or a sub-set thereof. 6693 * 6694 * Additionally the API is designed to allow you to easily work with the data in 6695 * the tables, retrieving and manipulating it as required. This is done by 6696 * presenting the API class as an array like interface. The contents of the 6697 * array depend upon the actions requested by each method (for example 6698 * `rows().nodes()` will return an array of nodes, while `rows().data()` will 6699 * return an array of objects or arrays depending upon your table's 6700 * configuration). The API object has a number of array like methods (`push`, 6701 * `pop`, `reverse` etc) as well as additional helper methods (`each`, `pluck`, 6702 * `unique` etc) to assist your working with the data held in a table. 6703 * 6704 * Most methods (those which return an Api instance) are chainable, which means 6705 * the return from a method call also has all of the methods available that the 6706 * top level object had. For example, these two calls are equivalent: 6707 * 6708 * // Not chained 6709 * api.row.add( {...} ); 6710 * api.draw(); 6711 * 6712 * // Chained 6713 * api.row.add( {...} ).draw(); 6714 * 6715 * @class DataTable.Api 6716 * @param {array|object|string|jQuery} context DataTable identifier. This is 6717 * used to define which DataTables enhanced tables this API will operate on. 6718 * Can be one of: 6719 * 6720 * * `string` - jQuery selector. Any DataTables' matching the given selector 6721 * with be found and used. 6722 * * `node` - `TABLE` node which has already been formed into a DataTable. 6723 * * `jQuery` - A jQuery object of `TABLE` nodes. 6724 * * `object` - DataTables settings object 6725 * @param {array} [data] Data to initialise the Api instance with. 6726 * 6727 * @example 6728 * // Direct initialisation during DataTables construction 6729 * var api = $('#example').DataTable(); 6730 * 6731 * @example 6732 * // Initialisation using a DataTables jQuery object 6733 * var api = $('#example').dataTable().api(); 6734 * 6735 * @example 6736 * // Initialisation as a constructor 6737 * var api = new $.fn.DataTable.Api( 'table.dataTable' ); 6738 */ 6739 _Api = function ( context, data ) 6740 { 6741 if ( ! (this instanceof _Api) ) { 6742 return new _Api( context, data ); 6743 } 6744 6745 var settings = []; 6746 var ctxSettings = function ( o ) { 6747 var a = _toSettings( o ); 6748 if ( a ) { 6749 settings.push.apply( settings, a ); 6750 } 6751 }; 6752 6753 if ( $.isArray( context ) ) { 6754 for ( var i=0, ien=context.length ; i<ien ; i++ ) { 6755 ctxSettings( context[i] ); 6756 } 6757 } 6758 else { 6759 ctxSettings( context ); 6760 } 6761 6762 // Remove duplicates 6763 this.context = _unique( settings ); 6764 6765 // Initial data 6766 if ( data ) { 6767 this.push.apply( this, data.toArray ? data.toArray() : data ); 6768 } 6769 6770 // selector 6771 this.selector = { 6772 rows: null, 6773 cols: null, 6774 opts: null 6775 }; 6776 6777 _Api.extend( this, this, __apiStruct ); 6778 }; 6779 6780 DataTable.Api = _Api; 6781 6782 _Api.prototype = /** @lends DataTables.Api */{ 6783 any: function () 6784 { 6785 return this.flatten().length !== 0; 6786 }, 6787 6788 6789 concat: __arrayProto.concat, 6790 6791 6792 context: [], // array of table settings objects 6793 6794 6795 each: function ( fn ) 6796 { 6797 for ( var i=0, ien=this.length ; i<ien; i++ ) { 6798 fn.call( this, this[i], i, this ); 6799 } 6800 6801 return this; 6802 }, 6803 6804 6805 eq: function ( idx ) 6806 { 6807 var ctx = this.context; 6808 6809 return ctx.length > idx ? 6810 new _Api( ctx[idx], this[idx] ) : 6811 null; 6812 }, 6813 6814 6815 filter: function ( fn ) 6816 { 6817 var a = []; 6818 6819 if ( __arrayProto.filter ) { 6820 a = __arrayProto.filter.call( this, fn, this ); 6821 } 6822 else { 6823 // Compatibility for browsers without EMCA-252-5 (JS 1.6) 6824 for ( var i=0, ien=this.length ; i<ien ; i++ ) { 6825 if ( fn.call( this, this[i], i, this ) ) { 6826 a.push( this[i] ); 6827 } 6828 } 6829 } 6830 6831 return new _Api( this.context, a ); 6832 }, 6833 6834 6835 flatten: function () 6836 { 6837 var a = []; 6838 return new _Api( this.context, a.concat.apply( a, this.toArray() ) ); 6839 }, 6840 6841 6842 join: __arrayProto.join, 6843 6844 6845 indexOf: __arrayProto.indexOf || function (obj, start) 6846 { 6847 for ( var i=(start || 0), ien=this.length ; i<ien ; i++ ) { 6848 if ( this[i] === obj ) { 6849 return i; 6850 } 6851 } 6852 return -1; 6853 }, 6854 6855 iterator: function ( flatten, type, fn, alwaysNew ) { 6856 var 6857 a = [], ret, 6858 i, ien, j, jen, 6859 context = this.context, 6860 rows, items, item, 6861 selector = this.selector; 6862 6863 // Argument shifting 6864 if ( typeof flatten === 'string' ) { 6865 alwaysNew = fn; 6866 fn = type; 6867 type = flatten; 6868 flatten = false; 6869 } 6870 6871 for ( i=0, ien=context.length ; i<ien ; i++ ) { 6872 var apiInst = new _Api( context[i] ); 6873 6874 if ( type === 'table' ) { 6875 ret = fn.call( apiInst, context[i], i ); 6876 6877 if ( ret !== undefined ) { 6878 a.push( ret ); 6879 } 6880 } 6881 else if ( type === 'columns' || type === 'rows' ) { 6882 // this has same length as context - one entry for each table 6883 ret = fn.call( apiInst, context[i], this[i], i ); 6884 6885 if ( ret !== undefined ) { 6886 a.push( ret ); 6887 } 6888 } 6889 else if ( type === 'column' || type === 'column-rows' || type === 'row' || type === 'cell' ) { 6890 // columns and rows share the same structure. 6891 // 'this' is an array of column indexes for each context 6892 items = this[i]; 6893 6894 if ( type === 'column-rows' ) { 6895 rows = _selector_row_indexes( context[i], selector.opts ); 6896 } 6897 6898 for ( j=0, jen=items.length ; j<jen ; j++ ) { 6899 item = items[j]; 6900 6901 if ( type === 'cell' ) { 6902 ret = fn.call( apiInst, context[i], item.row, item.column, i, j ); 6903 } 6904 else { 6905 ret = fn.call( apiInst, context[i], item, i, j, rows ); 6906 } 6907 6908 if ( ret !== undefined ) { 6909 a.push( ret ); 6910 } 6911 } 6912 } 6913 } 6914 6915 if ( a.length || alwaysNew ) { 6916 var api = new _Api( context, flatten ? a.concat.apply( [], a ) : a ); 6917 var apiSelector = api.selector; 6918 apiSelector.rows = selector.rows; 6919 apiSelector.cols = selector.cols; 6920 apiSelector.opts = selector.opts; 6921 return api; 6922 } 6923 return this; 6924 }, 6925 6926 6927 lastIndexOf: __arrayProto.lastIndexOf || function (obj, start) 6928 { 6929 // Bit cheeky... 6930 return this.indexOf.apply( this.toArray.reverse(), arguments ); 6931 }, 6932 6933 6934 length: 0, 6935 6936 6937 map: function ( fn ) 6938 { 6939 var a = []; 6940 6941 if ( __arrayProto.map ) { 6942 a = __arrayProto.map.call( this, fn, this ); 6943 } 6944 else { 6945 // Compatibility for browsers without EMCA-252-5 (JS 1.6) 6946 for ( var i=0, ien=this.length ; i<ien ; i++ ) { 6947 a.push( fn.call( this, this[i], i ) ); 6948 } 6949 } 6950 6951 return new _Api( this.context, a ); 6952 }, 6953 6954 6955 pluck: function ( prop ) 6956 { 6957 return this.map( function ( el ) { 6958 return el[ prop ]; 6959 } ); 6960 }, 6961 6962 pop: __arrayProto.pop, 6963 6964 6965 push: __arrayProto.push, 6966 6967 6968 // Does not return an API instance 6969 reduce: __arrayProto.reduce || function ( fn, init ) 6970 { 6971 return _fnReduce( this, fn, init, 0, this.length, 1 ); 6972 }, 6973 6974 6975 reduceRight: __arrayProto.reduceRight || function ( fn, init ) 6976 { 6977 return _fnReduce( this, fn, init, this.length-1, -1, -1 ); 6978 }, 6979 6980 6981 reverse: __arrayProto.reverse, 6982 6983 6984 // Object with rows, columns and opts 6985 selector: null, 6986 6987 6988 shift: __arrayProto.shift, 6989 6990 6991 sort: __arrayProto.sort, // ? name - order? 6992 6993 6994 splice: __arrayProto.splice, 6995 6996 6997 toArray: function () 6998 { 6999 return __arrayProto.slice.call( this ); 7000 }, 7001 7002 7003 to$: function () 7004 { 7005 return $( this ); 7006 }, 7007 7008 7009 toJQuery: function () 7010 { 7011 return $( this ); 7012 }, 7013 7014 7015 unique: function () 7016 { 7017 return new _Api( this.context, _unique(this) ); 7018 }, 7019 7020 7021 unshift: __arrayProto.unshift 7022 }; 7023 7024 7025 _Api.extend = function ( scope, obj, ext ) 7026 { 7027 // Only extend API instances and static properties of the API 7028 if ( ! ext.length || ! obj || ( ! (obj instanceof _Api) && ! obj.__dt_wrapper ) ) { 7029 return; 7030 } 7031 7032 var 7033 i, ien, 7034 j, jen, 7035 struct, inner, 7036 methodScoping = function ( scope, fn, struc ) { 7037 return function () { 7038 var ret = fn.apply( scope, arguments ); 7039 7040 // Method extension 7041 _Api.extend( ret, ret, struc.methodExt ); 7042 return ret; 7043 }; 7044 }; 7045 7046 for ( i=0, ien=ext.length ; i<ien ; i++ ) { 7047 struct = ext[i]; 7048 7049 // Value 7050 obj[ struct.name ] = typeof struct.val === 'function' ? 7051 methodScoping( scope, struct.val, struct ) : 7052 $.isPlainObject( struct.val ) ? 7053 {} : 7054 struct.val; 7055 7056 obj[ struct.name ].__dt_wrapper = true; 7057 7058 // Property extension 7059 _Api.extend( scope, obj[ struct.name ], struct.propExt ); 7060 } 7061 }; 7062 7063 7064 // @todo - Is there need for an augment function? 7065 // _Api.augment = function ( inst, name ) 7066 // { 7067 // // Find src object in the structure from the name 7068 // var parts = name.split('.'); 7069 7070 // _Api.extend( inst, obj ); 7071 // }; 7072 7073 7074 // [ 7075 // { 7076 // name: 'data' -- string - Property name 7077 // val: function () {}, -- function - Api method (or undefined if just an object 7078 // methodExt: [ ... ], -- array - Array of Api object definitions to extend the method result 7079 // propExt: [ ... ] -- array - Array of Api object definitions to extend the property 7080 // }, 7081 // { 7082 // name: 'row' 7083 // val: {}, 7084 // methodExt: [ ... ], 7085 // propExt: [ 7086 // { 7087 // name: 'data' 7088 // val: function () {}, 7089 // methodExt: [ ... ], 7090 // propExt: [ ... ] 7091 // }, 7092 // ... 7093 // ] 7094 // } 7095 // ] 7096 7097 _Api.register = _api_register = function ( name, val ) 7098 { 7099 if ( $.isArray( name ) ) { 7100 for ( var j=0, jen=name.length ; j<jen ; j++ ) { 7101 _Api.register( name[j], val ); 7102 } 7103 return; 7104 } 7105 7106 var 7107 i, ien, 7108 heir = name.split('.'), 7109 struct = __apiStruct, 7110 key, method; 7111 7112 var find = function ( src, name ) { 7113 for ( var i=0, ien=src.length ; i<ien ; i++ ) { 7114 if ( src[i].name === name ) { 7115 return src[i]; 7116 } 7117 } 7118 return null; 7119 }; 7120 7121 for ( i=0, ien=heir.length ; i<ien ; i++ ) { 7122 method = heir[i].indexOf('()') !== -1; 7123 key = method ? 7124 heir[i].replace('()', '') : 7125 heir[i]; 7126 7127 var src = find( struct, key ); 7128 if ( ! src ) { 7129 src = { 7130 name: key, 7131 val: {}, 7132 methodExt: [], 7133 propExt: [] 7134 }; 7135 struct.push( src ); 7136 } 7137 7138 if ( i === ien-1 ) { 7139 src.val = val; 7140 } 7141 else { 7142 struct = method ? 7143 src.methodExt : 7144 src.propExt; 7145 } 7146 } 7147 }; 7148 7149 7150 _Api.registerPlural = _api_registerPlural = function ( pluralName, singularName, val ) { 7151 _Api.register( pluralName, val ); 7152 7153 _Api.register( singularName, function () { 7154 var ret = val.apply( this, arguments ); 7155 7156 if ( ret === this ) { 7157 // Returned item is the API instance that was passed in, return it 7158 return this; 7159 } 7160 else if ( ret instanceof _Api ) { 7161 // New API instance returned, want the value from the first item 7162 // in the returned array for the singular result. 7163 return ret.length ? 7164 $.isArray( ret[0] ) ? 7165 new _Api( ret.context, ret[0] ) : // Array results are 'enhanced' 7166 ret[0] : 7167 undefined; 7168 } 7169 7170 // Non-API return - just fire it back 7171 return ret; 7172 } ); 7173 }; 7174 7175 7176 /** 7177 * Selector for HTML tables. Apply the given selector to the give array of 7178 * DataTables settings objects. 7179 * 7180 * @param {string|integer} [selector] jQuery selector string or integer 7181 * @param {array} Array of DataTables settings objects to be filtered 7182 * @return {array} 7183 * @ignore 7184 */ 7185 var __table_selector = function ( selector, a ) 7186 { 7187 // Integer is used to pick out a table by index 7188 if ( typeof selector === 'number' ) { 7189 return [ a[ selector ] ]; 7190 } 7191 7192 // Perform a jQuery selector on the table nodes 7193 var nodes = $.map( a, function (el, i) { 7194 return el.nTable; 7195 } ); 7196 7197 return $(nodes) 7198 .filter( selector ) 7199 .map( function (i) { 7200 // Need to translate back from the table node to the settings 7201 var idx = $.inArray( this, nodes ); 7202 return a[ idx ]; 7203 } ) 7204 .toArray(); 7205 }; 7206 7207 7208 7209 /** 7210 * Context selector for the API's context (i.e. the tables the API instance 7211 * refers to. 7212 * 7213 * @name DataTable.Api#tables 7214 * @param {string|integer} [selector] Selector to pick which tables the iterator 7215 * should operate on. If not given, all tables in the current context are 7216 * used. This can be given as a jQuery selector (for example `':gt(0)'`) to 7217 * select multiple tables or as an integer to select a single table. 7218 * @returns {DataTable.Api} Returns a new API instance if a selector is given. 7219 */ 7220 _api_register( 'tables()', function ( selector ) { 7221 // A new instance is created if there was a selector specified 7222 return selector ? 7223 new _Api( __table_selector( selector, this.context ) ) : 7224 this; 7225 } ); 7226 7227 7228 _api_register( 'table()', function ( selector ) { 7229 var tables = this.tables( selector ); 7230 var ctx = tables.context; 7231 7232 // Truncate to the first matched table 7233 return ctx.length ? 7234 new _Api( ctx[0] ) : 7235 tables; 7236 } ); 7237 7238 7239 _api_registerPlural( 'tables().nodes()', 'table().node()' , function () { 7240 return this.iterator( 'table', function ( ctx ) { 7241 return ctx.nTable; 7242 }, 1 ); 7243 } ); 7244 7245 7246 _api_registerPlural( 'tables().body()', 'table().body()' , function () { 7247 return this.iterator( 'table', function ( ctx ) { 7248 return ctx.nTBody; 7249 }, 1 ); 7250 } ); 7251 7252 7253 _api_registerPlural( 'tables().header()', 'table().header()' , function () { 7254 return this.iterator( 'table', function ( ctx ) { 7255 return ctx.nTHead; 7256 }, 1 ); 7257 } ); 7258 7259 7260 _api_registerPlural( 'tables().footer()', 'table().footer()' , function () { 7261 return this.iterator( 'table', function ( ctx ) { 7262 return ctx.nTFoot; 7263 }, 1 ); 7264 } ); 7265 7266 7267 _api_registerPlural( 'tables().containers()', 'table().container()' , function () { 7268 return this.iterator( 'table', function ( ctx ) { 7269 return ctx.nTableWrapper; 7270 }, 1 ); 7271 } ); 7272 7273 7274 7275 /** 7276 * Redraw the tables in the current context. 7277 * 7278 * @param {boolean} [reset=true] Reset (default) or hold the current paging 7279 * position. A full re-sort and re-filter is performed when this method is 7280 * called, which is why the pagination reset is the default action. 7281 * @returns {DataTables.Api} this 7282 */ 7283 _api_register( 'draw()', function ( resetPaging ) { 7284 return this.iterator( 'table', function ( settings ) { 7285 _fnReDraw( settings, resetPaging===false ); 7286 } ); 7287 } ); 7288 7289 7290 7291 /** 7292 * Get the current page index. 7293 * 7294 * @return {integer} Current page index (zero based) 7295 *//** 7296 * Set the current page. 7297 * 7298 * Note that if you attempt to show a page which does not exist, DataTables will 7299 * not throw an error, but rather reset the paging. 7300 * 7301 * @param {integer|string} action The paging action to take. This can be one of: 7302 * * `integer` - The page index to jump to 7303 * * `string` - An action to take: 7304 * * `first` - Jump to first page. 7305 * * `next` - Jump to the next page 7306 * * `previous` - Jump to previous page 7307 * * `last` - Jump to the last page. 7308 * @returns {DataTables.Api} this 7309 */ 7310 _api_register( 'page()', function ( action ) { 7311 if ( action === undefined ) { 7312 return this.page.info().page; // not an expensive call 7313 } 7314 7315 // else, have an action to take on all tables 7316 return this.iterator( 'table', function ( settings ) { 7317 _fnPageChange( settings, action ); 7318 } ); 7319 } ); 7320 7321 7322 /** 7323 * Paging information for the first table in the current context. 7324 * 7325 * If you require paging information for another table, use the `table()` method 7326 * with a suitable selector. 7327 * 7328 * @return {object} Object with the following properties set: 7329 * * `page` - Current page index (zero based - i.e. the first page is `0`) 7330 * * `pages` - Total number of pages 7331 * * `start` - Display index for the first record shown on the current page 7332 * * `end` - Display index for the last record shown on the current page 7333 * * `length` - Display length (number of records). Note that generally `start 7334 * + length = end`, but this is not always true, for example if there are 7335 * only 2 records to show on the final page, with a length of 10. 7336 * * `recordsTotal` - Full data set length 7337 * * `recordsDisplay` - Data set length once the current filtering criterion 7338 * are applied. 7339 */ 7340 _api_register( 'page.info()', function ( action ) { 7341 if ( this.context.length === 0 ) { 7342 return undefined; 7343 } 7344 7345 var 7346 settings = this.context[0], 7347 start = settings._iDisplayStart, 7348 len = settings._iDisplayLength, 7349 visRecords = settings.fnRecordsDisplay(), 7350 all = len === -1; 7351 7352 return { 7353 "page": all ? 0 : Math.floor( start / len ), 7354 "pages": all ? 1 : Math.ceil( visRecords / len ), 7355 "start": start, 7356 "end": settings.fnDisplayEnd(), 7357 "length": len, 7358 "recordsTotal": settings.fnRecordsTotal(), 7359 "recordsDisplay": visRecords 7360 }; 7361 } ); 7362 7363 7364 /** 7365 * Get the current page length. 7366 * 7367 * @return {integer} Current page length. Note `-1` indicates that all records 7368 * are to be shown. 7369 *//** 7370 * Set the current page length. 7371 * 7372 * @param {integer} Page length to set. Use `-1` to show all records. 7373 * @returns {DataTables.Api} this 7374 */ 7375 _api_register( 'page.len()', function ( len ) { 7376 // Note that we can't call this function 'length()' because `length` 7377 // is a Javascript property of functions which defines how many arguments 7378 // the function expects. 7379 if ( len === undefined ) { 7380 return this.context.length !== 0 ? 7381 this.context[0]._iDisplayLength : 7382 undefined; 7383 } 7384 7385 // else, set the page length 7386 return this.iterator( 'table', function ( settings ) { 7387 _fnLengthChange( settings, len ); 7388 } ); 7389 } ); 7390 7391 7392 7393 var __reload = function ( settings, holdPosition, callback ) { 7394 // Use the draw event to trigger a callback 7395 if ( callback ) { 7396 var api = new _Api( settings ); 7397 7398 api.one( 'draw', function () { 7399 callback( api.ajax.json() ); 7400 } ); 7401 } 7402 7403 if ( _fnDataSource( settings ) == 'ssp' ) { 7404 _fnReDraw( settings, holdPosition ); 7405 } 7406 else { 7407 // Trigger xhr 7408 _fnProcessingDisplay( settings, true ); 7409 7410 _fnBuildAjax( settings, [], function( json ) { 7411 _fnClearTable( settings ); 7412 7413 var data = _fnAjaxDataSrc( settings, json ); 7414 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 7415 _fnAddData( settings, data[i] ); 7416 } 7417 7418 _fnReDraw( settings, holdPosition ); 7419 _fnProcessingDisplay( settings, false ); 7420 } ); 7421 } 7422 }; 7423 7424 7425 /** 7426 * Get the JSON response from the last Ajax request that DataTables made to the 7427 * server. Note that this returns the JSON from the first table in the current 7428 * context. 7429 * 7430 * @return {object} JSON received from the server. 7431 */ 7432 _api_register( 'ajax.json()', function () { 7433 var ctx = this.context; 7434 7435 if ( ctx.length > 0 ) { 7436 return ctx[0].json; 7437 } 7438 7439 // else return undefined; 7440 } ); 7441 7442 7443 /** 7444 * Get the data submitted in the last Ajax request 7445 */ 7446 _api_register( 'ajax.params()', function () { 7447 var ctx = this.context; 7448 7449 if ( ctx.length > 0 ) { 7450 return ctx[0].oAjaxData; 7451 } 7452 7453 // else return undefined; 7454 } ); 7455 7456 7457 /** 7458 * Reload tables from the Ajax data source. Note that this function will 7459 * automatically re-draw the table when the remote data has been loaded. 7460 * 7461 * @param {boolean} [reset=true] Reset (default) or hold the current paging 7462 * position. A full re-sort and re-filter is performed when this method is 7463 * called, which is why the pagination reset is the default action. 7464 * @returns {DataTables.Api} this 7465 */ 7466 _api_register( 'ajax.reload()', function ( callback, resetPaging ) { 7467 return this.iterator( 'table', function (settings) { 7468 __reload( settings, resetPaging===false, callback ); 7469 } ); 7470 } ); 7471 7472 7473 /** 7474 * Get the current Ajax URL. Note that this returns the URL from the first 7475 * table in the current context. 7476 * 7477 * @return {string} Current Ajax source URL 7478 *//** 7479 * Set the Ajax URL. Note that this will set the URL for all tables in the 7480 * current context. 7481 * 7482 * @param {string} url URL to set. 7483 * @returns {DataTables.Api} this 7484 */ 7485 _api_register( 'ajax.url()', function ( url ) { 7486 var ctx = this.context; 7487 7488 if ( url === undefined ) { 7489 // get 7490 if ( ctx.length === 0 ) { 7491 return undefined; 7492 } 7493 ctx = ctx[0]; 7494 7495 return ctx.ajax ? 7496 $.isPlainObject( ctx.ajax ) ? 7497 ctx.ajax.url : 7498 ctx.ajax : 7499 ctx.sAjaxSource; 7500 } 7501 7502 // set 7503 return this.iterator( 'table', function ( settings ) { 7504 if ( $.isPlainObject( settings.ajax ) ) { 7505 settings.ajax.url = url; 7506 } 7507 else { 7508 settings.ajax = url; 7509 } 7510 // No need to consider sAjaxSource here since DataTables gives priority 7511 // to `ajax` over `sAjaxSource`. So setting `ajax` here, renders any 7512 // value of `sAjaxSource` redundant. 7513 } ); 7514 } ); 7515 7516 7517 /** 7518 * Load data from the newly set Ajax URL. Note that this method is only 7519 * available when `ajax.url()` is used to set a URL. Additionally, this method 7520 * has the same effect as calling `ajax.reload()` but is provided for 7521 * convenience when setting a new URL. Like `ajax.reload()` it will 7522 * automatically redraw the table once the remote data has been loaded. 7523 * 7524 * @returns {DataTables.Api} this 7525 */ 7526 _api_register( 'ajax.url().load()', function ( callback, resetPaging ) { 7527 // Same as a reload, but makes sense to present it for easy access after a 7528 // url change 7529 return this.iterator( 'table', function ( ctx ) { 7530 __reload( ctx, resetPaging===false, callback ); 7531 } ); 7532 } ); 7533 7534 7535 7536 7537 var _selector_run = function ( type, selector, selectFn, settings, opts ) 7538 { 7539 var 7540 out = [], res, 7541 a, i, ien, j, jen, 7542 selectorType = typeof selector; 7543 7544 // Can't just check for isArray here, as an API or jQuery instance might be 7545 // given with their array like look 7546 if ( ! selector || selectorType === 'string' || selectorType === 'function' || selector.length === undefined ) { 7547 selector = [ selector ]; 7548 } 7549 7550 for ( i=0, ien=selector.length ; i<ien ; i++ ) { 7551 a = selector[i] && selector[i].split ? 7552 selector[i].split(',') : 7553 [ selector[i] ]; 7554 7555 for ( j=0, jen=a.length ; j<jen ; j++ ) { 7556 res = selectFn( typeof a[j] === 'string' ? $.trim(a[j]) : a[j] ); 7557 7558 if ( res && res.length ) { 7559 out.push.apply( out, res ); 7560 } 7561 } 7562 } 7563 7564 // selector extensions 7565 var ext = _ext.selector[ type ]; 7566 if ( ext.length ) { 7567 for ( i=0, ien=ext.length ; i<ien ; i++ ) { 7568 out = ext[i]( settings, opts, out ); 7569 } 7570 } 7571 7572 return out; 7573 }; 7574 7575 7576 var _selector_opts = function ( opts ) 7577 { 7578 if ( ! opts ) { 7579 opts = {}; 7580 } 7581 7582 // Backwards compatibility for 1.9- which used the terminology filter rather 7583 // than search 7584 if ( opts.filter && opts.search === undefined ) { 7585 opts.search = opts.filter; 7586 } 7587 7588 return $.extend( { 7589 search: 'none', 7590 order: 'current', 7591 page: 'all' 7592 }, opts ); 7593 }; 7594 7595 7596 var _selector_first = function ( inst ) 7597 { 7598 // Reduce the API instance to the first item found 7599 for ( var i=0, ien=inst.length ; i<ien ; i++ ) { 7600 if ( inst[i].length > 0 ) { 7601 // Assign the first element to the first item in the instance 7602 // and truncate the instance and context 7603 inst[0] = inst[i]; 7604 inst[0].length = 1; 7605 inst.length = 1; 7606 inst.context = [ inst.context[i] ]; 7607 7608 return inst; 7609 } 7610 } 7611 7612 // Not found - return an empty instance 7613 inst.length = 0; 7614 return inst; 7615 }; 7616 7617 7618 var _selector_row_indexes = function ( settings, opts ) 7619 { 7620 var 7621 i, ien, tmp, a=[], 7622 displayFiltered = settings.aiDisplay, 7623 displayMaster = settings.aiDisplayMaster; 7624 7625 var 7626 search = opts.search, // none, applied, removed 7627 order = opts.order, // applied, current, index (original - compatibility with 1.9) 7628 page = opts.page; // all, current 7629 7630 if ( _fnDataSource( settings ) == 'ssp' ) { 7631 // In server-side processing mode, most options are irrelevant since 7632 // rows not shown don't exist and the index order is the applied order 7633 // Removed is a special case - for consistency just return an empty 7634 // array 7635 return search === 'removed' ? 7636 [] : 7637 _range( 0, displayMaster.length ); 7638 } 7639 else if ( page == 'current' ) { 7640 // Current page implies that order=current and fitler=applied, since it is 7641 // fairly senseless otherwise, regardless of what order and search actually 7642 // are 7643 for ( i=settings._iDisplayStart, ien=settings.fnDisplayEnd() ; i<ien ; i++ ) { 7644 a.push( displayFiltered[i] ); 7645 } 7646 } 7647 else if ( order == 'current' || order == 'applied' ) { 7648 a = search == 'none' ? 7649 displayMaster.slice() : // no search 7650 search == 'applied' ? 7651 displayFiltered.slice() : // applied search 7652 $.map( displayMaster, function (el, i) { // removed search 7653 return $.inArray( el, displayFiltered ) === -1 ? el : null; 7654 } ); 7655 } 7656 else if ( order == 'index' || order == 'original' ) { 7657 for ( i=0, ien=settings.aoData.length ; i<ien ; i++ ) { 7658 if ( search == 'none' ) { 7659 a.push( i ); 7660 } 7661 else { // applied | removed 7662 tmp = $.inArray( i, displayFiltered ); 7663 7664 if ((tmp === -1 && search == 'removed') || 7665 (tmp >= 0 && search == 'applied') ) 7666 { 7667 a.push( i ); 7668 } 7669 } 7670 } 7671 } 7672 7673 return a; 7674 }; 7675 7676 7677 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 7678 * Rows 7679 * 7680 * {} - no selector - use all available rows 7681 * {integer} - row aoData index 7682 * {node} - TR node 7683 * {string} - jQuery selector to apply to the TR elements 7684 * {array} - jQuery array of nodes, or simply an array of TR nodes 7685 * 7686 */ 7687 7688 7689 var __row_selector = function ( settings, selector, opts ) 7690 { 7691 var run = function ( sel ) { 7692 var selInt = _intVal( sel ); 7693 var i, ien; 7694 7695 // Short cut - selector is a number and no options provided (default is 7696 // all records, so no need to check if the index is in there, since it 7697 // must be - dev error if the index doesn't exist). 7698 if ( selInt !== null && ! opts ) { 7699 return [ selInt ]; 7700 } 7701 7702 var rows = _selector_row_indexes( settings, opts ); 7703 7704 if ( selInt !== null && $.inArray( selInt, rows ) !== -1 ) { 7705 // Selector - integer 7706 return [ selInt ]; 7707 } 7708 else if ( ! sel ) { 7709 // Selector - none 7710 return rows; 7711 } 7712 7713 // Selector - function 7714 if ( typeof sel === 'function' ) { 7715 return $.map( rows, function (idx) { 7716 var row = settings.aoData[ idx ]; 7717 return sel( idx, row._aData, row.nTr ) ? idx : null; 7718 } ); 7719 } 7720 7721 // Get nodes in the order from the `rows` array with null values removed 7722 var nodes = _removeEmpty( 7723 _pluck_order( settings.aoData, rows, 'nTr' ) 7724 ); 7725 7726 // Selector - node 7727 if ( sel.nodeName ) { 7728 if ( $.inArray( sel, nodes ) !== -1 ) { 7729 return [ sel._DT_RowIndex ]; // sel is a TR node that is in the table 7730 // and DataTables adds a prop for fast lookup 7731 } 7732 } 7733 7734 // Selector - jQuery selector string, array of nodes or jQuery object/ 7735 // As jQuery's .filter() allows jQuery objects to be passed in filter, 7736 // it also allows arrays, so this will cope with all three options 7737 return $(nodes) 7738 .filter( sel ) 7739 .map( function () { 7740 return this._DT_RowIndex; 7741 } ) 7742 .toArray(); 7743 }; 7744 7745 return _selector_run( 'row', selector, run, settings, opts ); 7746 }; 7747 7748 7749 _api_register( 'rows()', function ( selector, opts ) { 7750 // argument shifting 7751 if ( selector === undefined ) { 7752 selector = ''; 7753 } 7754 else if ( $.isPlainObject( selector ) ) { 7755 opts = selector; 7756 selector = ''; 7757 } 7758 7759 opts = _selector_opts( opts ); 7760 7761 var inst = this.iterator( 'table', function ( settings ) { 7762 return __row_selector( settings, selector, opts ); 7763 }, 1 ); 7764 7765 // Want argument shifting here and in __row_selector? 7766 inst.selector.rows = selector; 7767 inst.selector.opts = opts; 7768 7769 return inst; 7770 } ); 7771 7772 _api_register( 'rows().nodes()', function () { 7773 return this.iterator( 'row', function ( settings, row ) { 7774 return settings.aoData[ row ].nTr || undefined; 7775 }, 1 ); 7776 } ); 7777 7778 _api_register( 'rows().data()', function () { 7779 return this.iterator( true, 'rows', function ( settings, rows ) { 7780 return _pluck_order( settings.aoData, rows, '_aData' ); 7781 }, 1 ); 7782 } ); 7783 7784 _api_registerPlural( 'rows().cache()', 'row().cache()', function ( type ) { 7785 return this.iterator( 'row', function ( settings, row ) { 7786 var r = settings.aoData[ row ]; 7787 return type === 'search' ? r._aFilterData : r._aSortData; 7788 }, 1 ); 7789 } ); 7790 7791 _api_registerPlural( 'rows().invalidate()', 'row().invalidate()', function ( src ) { 7792 return this.iterator( 'row', function ( settings, row ) { 7793 _fnInvalidate( settings, row, src ); 7794 } ); 7795 } ); 7796 7797 _api_registerPlural( 'rows().indexes()', 'row().index()', function () { 7798 return this.iterator( 'row', function ( settings, row ) { 7799 return row; 7800 }, 1 ); 7801 } ); 7802 7803 _api_registerPlural( 'rows().remove()', 'row().remove()', function () { 7804 var that = this; 7805 7806 return this.iterator( 'row', function ( settings, row, thatIdx ) { 7807 var data = settings.aoData; 7808 7809 data.splice( row, 1 ); 7810 7811 // Update the _DT_RowIndex parameter on all rows in the table 7812 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 7813 if ( data[i].nTr !== null ) { 7814 data[i].nTr._DT_RowIndex = i; 7815 } 7816 } 7817 7818 // Remove the target row from the search array 7819 var displayIndex = $.inArray( row, settings.aiDisplay ); 7820 7821 // Delete from the display arrays 7822 _fnDeleteIndex( settings.aiDisplayMaster, row ); 7823 _fnDeleteIndex( settings.aiDisplay, row ); 7824 _fnDeleteIndex( that[ thatIdx ], row, false ); // maintain local indexes 7825 7826 // Check for an 'overflow' they case for displaying the table 7827 _fnLengthOverflow( settings ); 7828 } ); 7829 } ); 7830 7831 7832 _api_register( 'rows.add()', function ( rows ) { 7833 var newRows = this.iterator( 'table', function ( settings ) { 7834 var row, i, ien; 7835 var out = []; 7836 7837 for ( i=0, ien=rows.length ; i<ien ; i++ ) { 7838 row = rows[i]; 7839 7840 if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) { 7841 out.push( _fnAddTr( settings, row )[0] ); 7842 } 7843 else { 7844 out.push( _fnAddData( settings, row ) ); 7845 } 7846 } 7847 7848 return out; 7849 }, 1 ); 7850 7851 // Return an Api.rows() extended instance, so rows().nodes() etc can be used 7852 var modRows = this.rows( -1 ); 7853 modRows.pop(); 7854 modRows.push.apply( modRows, newRows.toArray() ); 7855 7856 return modRows; 7857 } ); 7858 7859 7860 7861 7862 7863 /** 7864 * 7865 */ 7866 _api_register( 'row()', function ( selector, opts ) { 7867 return _selector_first( this.rows( selector, opts ) ); 7868 } ); 7869 7870 7871 _api_register( 'row().data()', function ( data ) { 7872 var ctx = this.context; 7873 7874 if ( data === undefined ) { 7875 // Get 7876 return ctx.length && this.length ? 7877 ctx[0].aoData[ this[0] ]._aData : 7878 undefined; 7879 } 7880 7881 // Set 7882 ctx[0].aoData[ this[0] ]._aData = data; 7883 7884 // Automatically invalidate 7885 _fnInvalidate( ctx[0], this[0], 'data' ); 7886 7887 return this; 7888 } ); 7889 7890 7891 _api_register( 'row().node()', function () { 7892 var ctx = this.context; 7893 7894 return ctx.length && this.length ? 7895 ctx[0].aoData[ this[0] ].nTr || null : 7896 null; 7897 } ); 7898 7899 7900 _api_register( 'row.add()', function ( row ) { 7901 // Allow a jQuery object to be passed in - only a single row is added from 7902 // it though - the first element in the set 7903 if ( row instanceof $ && row.length ) { 7904 row = row[0]; 7905 } 7906 7907 var rows = this.iterator( 'table', function ( settings ) { 7908 if ( row.nodeName && row.nodeName.toUpperCase() === 'TR' ) { 7909 return _fnAddTr( settings, row )[0]; 7910 } 7911 return _fnAddData( settings, row ); 7912 } ); 7913 7914 // Return an Api.rows() extended instance, with the newly added row selected 7915 return this.row( rows[0] ); 7916 } ); 7917 7918 7919 7920 var __details_add = function ( ctx, row, data, klass ) 7921 { 7922 // Convert to array of TR elements 7923 var rows = []; 7924 var addRow = function ( r, k ) { 7925 // Recursion to allow for arrays of jQuery objects 7926 if ( $.isArray( r ) || r instanceof $ ) { 7927 for ( var i=0, ien=r.length ; i<ien ; i++ ) { 7928 addRow( r[i], k ); 7929 } 7930 return; 7931 } 7932 7933 // If we get a TR element, then just add it directly - up to the dev 7934 // to add the correct number of columns etc 7935 if ( r.nodeName && r.nodeName.toLowerCase() === 'tr' ) { 7936 rows.push( r ); 7937 } 7938 else { 7939 // Otherwise create a row with a wrapper 7940 var created = $('<tr><td/></tr>').addClass( k ); 7941 $('td', created) 7942 .addClass( k ) 7943 .html( r ) 7944 [0].colSpan = _fnVisbleColumns( ctx ); 7945 7946 rows.push( created[0] ); 7947 } 7948 }; 7949 7950 addRow( data, klass ); 7951 7952 if ( row._details ) { 7953 row._details.remove(); 7954 } 7955 7956 row._details = $(rows); 7957 7958 // If the children were already shown, that state should be retained 7959 if ( row._detailsShow ) { 7960 row._details.insertAfter( row.nTr ); 7961 } 7962 }; 7963 7964 7965 var __details_remove = function ( api, idx ) 7966 { 7967 var ctx = api.context; 7968 7969 if ( ctx.length ) { 7970 var row = ctx[0].aoData[ idx !== undefined ? idx : api[0] ]; 7971 7972 if ( row._details ) { 7973 row._details.remove(); 7974 7975 row._detailsShow = undefined; 7976 row._details = undefined; 7977 } 7978 } 7979 }; 7980 7981 7982 var __details_display = function ( api, show ) { 7983 var ctx = api.context; 7984 7985 if ( ctx.length && api.length ) { 7986 var row = ctx[0].aoData[ api[0] ]; 7987 7988 if ( row._details ) { 7989 row._detailsShow = show; 7990 7991 if ( show ) { 7992 row._details.insertAfter( row.nTr ); 7993 } 7994 else { 7995 row._details.detach(); 7996 } 7997 7998 __details_events( ctx[0] ); 7999 } 8000 } 8001 }; 8002 8003 8004 var __details_events = function ( settings ) 8005 { 8006 var api = new _Api( settings ); 8007 var namespace = '.dt.DT_details'; 8008 var drawEvent = 'draw'+namespace; 8009 var colvisEvent = 'column-visibility'+namespace; 8010 var destroyEvent = 'destroy'+namespace; 8011 var data = settings.aoData; 8012 8013 api.off( drawEvent +' '+ colvisEvent +' '+ destroyEvent ); 8014 8015 if ( _pluck( data, '_details' ).length > 0 ) { 8016 // On each draw, insert the required elements into the document 8017 api.on( drawEvent, function ( e, ctx ) { 8018 if ( settings !== ctx ) { 8019 return; 8020 } 8021 8022 api.rows( {page:'current'} ).eq(0).each( function (idx) { 8023 // Internal data grab 8024 var row = data[ idx ]; 8025 8026 if ( row._detailsShow ) { 8027 row._details.insertAfter( row.nTr ); 8028 } 8029 } ); 8030 } ); 8031 8032 // Column visibility change - update the colspan 8033 api.on( colvisEvent, function ( e, ctx, idx, vis ) { 8034 if ( settings !== ctx ) { 8035 return; 8036 } 8037 8038 // Update the colspan for the details rows (note, only if it already has 8039 // a colspan) 8040 var row, visible = _fnVisbleColumns( ctx ); 8041 8042 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 8043 row = data[i]; 8044 8045 if ( row._details ) { 8046 row._details.children('td[colspan]').attr('colspan', visible ); 8047 } 8048 } 8049 } ); 8050 8051 // Table destroyed - nuke any child rows 8052 api.on( destroyEvent, function ( e, ctx ) { 8053 if ( settings !== ctx ) { 8054 return; 8055 } 8056 8057 for ( var i=0, ien=data.length ; i<ien ; i++ ) { 8058 if ( data[i]._details ) { 8059 __details_remove( api, i ); 8060 } 8061 } 8062 } ); 8063 } 8064 }; 8065 8066 // Strings for the method names to help minification 8067 var _emp = ''; 8068 var _child_obj = _emp+'row().child'; 8069 var _child_mth = _child_obj+'()'; 8070 8071 // data can be: 8072 // tr 8073 // string 8074 // jQuery or array of any of the above 8075 _api_register( _child_mth, function ( data, klass ) { 8076 var ctx = this.context; 8077 8078 if ( data === undefined ) { 8079 // get 8080 return ctx.length && this.length ? 8081 ctx[0].aoData[ this[0] ]._details : 8082 undefined; 8083 } 8084 else if ( data === true ) { 8085 // show 8086 this.child.show(); 8087 } 8088 else if ( data === false ) { 8089 // remove 8090 __details_remove( this ); 8091 } 8092 else if ( ctx.length && this.length ) { 8093 // set 8094 __details_add( ctx[0], ctx[0].aoData[ this[0] ], data, klass ); 8095 } 8096 8097 return this; 8098 } ); 8099 8100 8101 _api_register( [ 8102 _child_obj+'.show()', 8103 _child_mth+'.show()' // only when `child()` was called with parameters (without 8104 ], function ( show ) { // it returns an object and this method is not executed) 8105 __details_display( this, true ); 8106 return this; 8107 } ); 8108 8109 8110 _api_register( [ 8111 _child_obj+'.hide()', 8112 _child_mth+'.hide()' // only when `child()` was called with parameters (without 8113 ], function () { // it returns an object and this method is not executed) 8114 __details_display( this, false ); 8115 return this; 8116 } ); 8117 8118 8119 _api_register( [ 8120 _child_obj+'.remove()', 8121 _child_mth+'.remove()' // only when `child()` was called with parameters (without 8122 ], function () { // it returns an object and this method is not executed) 8123 __details_remove( this ); 8124 return this; 8125 } ); 8126 8127 8128 _api_register( _child_obj+'.isShown()', function () { 8129 var ctx = this.context; 8130 8131 if ( ctx.length && this.length ) { 8132 // _detailsShown as false or undefined will fall through to return false 8133 return ctx[0].aoData[ this[0] ]._detailsShow || false; 8134 } 8135 return false; 8136 } ); 8137 8138 8139 8140 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * 8141 * Columns 8142 * 8143 * {integer} - column index (>=0 count from left, <0 count from right) 8144 * "{integer}:visIdx" - visible column index (i.e. translate to column index) (>=0 count from left, <0 count from right) 8145 * "{integer}:visible" - alias for {integer}:visIdx (>=0 count from left, <0 count from right) 8146 * "{string}:name" - column name 8147 * "{string}" - jQuery selector on column header nodes 8148 * 8149 */ 8150 8151 // can be an array of these items, comma separated list, or an array of comma 8152 // separated lists 8153 8154 var __re_column_selector = /^(.+):(name|visIdx|visible)$/; 8155 8156 8157 // r1 and r2 are redundant - but it means that the parameters match for the 8158 // iterator callback in columns().data() 8159 var __columnData = function ( settings, column, r1, r2, rows ) { 8160 var a = []; 8161 for ( var row=0, ien=rows.length ; row<ien ; row++ ) { 8162 a.push( _fnGetCellData( settings, rows[row], column ) ); 8163 } 8164 return a; 8165 }; 8166 8167 8168 var __column_selector = function ( settings, selector, opts ) 8169 { 8170 var 8171 columns = settings.aoColumns, 8172 names = _pluck( columns, 'sName' ), 8173 nodes = _pluck( columns, 'nTh' ); 8174 8175 var run = function ( s ) { 8176 var selInt = _intVal( s ); 8177 8178 // Selector - all 8179 if ( s === '' ) { 8180 return _range( columns.length ); 8181 } 8182 8183 // Selector - index 8184 if ( selInt !== null ) { 8185 return [ selInt >= 0 ? 8186 selInt : // Count from left 8187 columns.length + selInt // Count from right (+ because its a negative value) 8188 ]; 8189 } 8190 8191 // Selector = function 8192 if ( typeof s === 'function' ) { 8193 var rows = _selector_row_indexes( settings, opts ); 8194 8195 return $.map( columns, function (col, idx) { 8196 return s( 8197 idx, 8198 __columnData( settings, idx, 0, 0, rows ), 8199 nodes[ idx ] 8200 ) ? idx : null; 8201 } ); 8202 } 8203 8204 // jQuery or string selector 8205 var match = typeof s === 'string' ? 8206 s.match( __re_column_selector ) : 8207 ''; 8208 8209 if ( match ) { 8210 switch( match[2] ) { 8211 case 'visIdx': 8212 case 'visible': 8213 var idx = parseInt( match[1], 10 ); 8214 // Visible index given, convert to column index 8215 if ( idx < 0 ) { 8216 // Counting from the right 8217 var visColumns = $.map( columns, function (col,i) { 8218 return col.bVisible ? i : null; 8219 } ); 8220 return [ visColumns[ visColumns.length + idx ] ]; 8221 } 8222 // Counting from the left 8223 return [ _fnVisibleToColumnIndex( settings, idx ) ]; 8224 8225 case 'name': 8226 // match by name. `names` is column index complete and in order 8227 return $.map( names, function (name, i) { 8228 return name === match[1] ? i : null; 8229 } ); 8230 } 8231 } 8232 else { 8233 // jQuery selector on the TH elements for the columns 8234 return $( nodes ) 8235 .filter( s ) 8236 .map( function () { 8237 return $.inArray( this, nodes ); // `nodes` is column index complete and in order 8238 } ) 8239 .toArray(); 8240 } 8241 }; 8242 8243 return _selector_run( 'column', selector, run, settings, opts ); 8244 }; 8245 8246 8247 var __setColumnVis = function ( settings, column, vis, recalc ) { 8248 var 8249 cols = settings.aoColumns, 8250 col = cols[ column ], 8251 data = settings.aoData, 8252 row, cells, i, ien, tr; 8253 8254 // Get 8255 if ( vis === undefined ) { 8256 return col.bVisible; 8257 } 8258 8259 // Set 8260 // No change 8261 if ( col.bVisible === vis ) { 8262 return; 8263 } 8264 8265 if ( vis ) { 8266 // Insert column 8267 // Need to decide if we should use appendChild or insertBefore 8268 var insertBefore = $.inArray( true, _pluck(cols, 'bVisible'), column+1 ); 8269 8270 for ( i=0, ien=data.length ; i<ien ; i++ ) { 8271 tr = data[i].nTr; 8272 cells = data[i].anCells; 8273 8274 if ( tr ) { 8275 // insertBefore can act like appendChild if 2nd arg is null 8276 tr.insertBefore( cells[ column ], cells[ insertBefore ] || null ); 8277 } 8278 } 8279 } 8280 else { 8281 // Remove column 8282 $( _pluck( settings.aoData, 'anCells', column ) ).detach(); 8283 } 8284 8285 // Common actions 8286 col.bVisible = vis; 8287 _fnDrawHead( settings, settings.aoHeader ); 8288 _fnDrawHead( settings, settings.aoFooter ); 8289 8290 if ( recalc === undefined || recalc ) { 8291 // Automatically adjust column sizing 8292 _fnAdjustColumnSizing( settings ); 8293 8294 // Realign columns for scrolling 8295 if ( settings.oScroll.sX || settings.oScroll.sY ) { 8296 _fnScrollDraw( settings ); 8297 } 8298 } 8299 8300 _fnCallbackFire( settings, null, 'column-visibility', [settings, column, vis] ); 8301 8302 _fnSaveState( settings ); 8303 }; 8304 8305 8306 _api_register( 'columns()', function ( selector, opts ) { 8307 // argument shifting 8308 if ( selector === undefined ) { 8309 selector = ''; 8310 } 8311 else if ( $.isPlainObject( selector ) ) { 8312 opts = selector; 8313 selector = ''; 8314 } 8315 8316 opts = _selector_opts( opts ); 8317 8318 var inst = this.iterator( 'table', function ( settings ) { 8319 return __column_selector( settings, selector, opts ); 8320 }, 1 ); 8321 8322 // Want argument shifting here and in _row_selector? 8323 inst.selector.cols = selector; 8324 inst.selector.opts = opts; 8325 8326 return inst; 8327 } ); 8328 8329 _api_registerPlural( 'columns().header()', 'column().header()', function ( selector, opts ) { 8330 return this.iterator( 'column', function ( settings, column ) { 8331 return settings.aoColumns[column].nTh; 8332 }, 1 ); 8333 } ); 8334 8335 _api_registerPlural( 'columns().footer()', 'column().footer()', function ( selector, opts ) { 8336 return this.iterator( 'column', function ( settings, column ) { 8337 return settings.aoColumns[column].nTf; 8338 }, 1 ); 8339 } ); 8340 8341 _api_registerPlural( 'columns().data()', 'column().data()', function () { 8342 return this.iterator( 'column-rows', __columnData, 1 ); 8343 } ); 8344 8345 _api_registerPlural( 'columns().dataSrc()', 'column().dataSrc()', function () { 8346 return this.iterator( 'column', function ( settings, column ) { 8347 return settings.aoColumns[column].mData; 8348 }, 1 ); 8349 } ); 8350 8351 _api_registerPlural( 'columns().cache()', 'column().cache()', function ( type ) { 8352 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) { 8353 return _pluck_order( settings.aoData, rows, 8354 type === 'search' ? '_aFilterData' : '_aSortData', column 8355 ); 8356 }, 1 ); 8357 } ); 8358 8359 _api_registerPlural( 'columns().nodes()', 'column().nodes()', function () { 8360 return this.iterator( 'column-rows', function ( settings, column, i, j, rows ) { 8361 return _pluck_order( settings.aoData, rows, 'anCells', column ) ; 8362 }, 1 ); 8363 } ); 8364 8365 _api_registerPlural( 'columns().visible()', 'column().visible()', function ( vis, calc ) { 8366 return this.iterator( 'column', function ( settings, column ) { 8367 if ( vis === undefined ) { 8368 return settings.aoColumns[ column ].bVisible; 8369 } // else 8370 __setColumnVis( settings, column, vis, calc ); 8371 } ); 8372 } ); 8373 8374 _api_registerPlural( 'columns().indexes()', 'column().index()', function ( type ) { 8375 return this.iterator( 'column', function ( settings, column ) { 8376 return type === 'visible' ? 8377 _fnColumnIndexToVisible( settings, column ) : 8378 column; 8379 }, 1 ); 8380 } ); 8381 8382 _api_register( 'columns.adjust()', function () { 8383 return this.iterator( 'table', function ( settings ) { 8384 _fnAdjustColumnSizing( settings ); 8385 }, 1 ); 8386 } ); 8387 8388 _api_register( 'column.index()', function ( type, idx ) { 8389 if ( this.context.length !== 0 ) { 8390 var ctx = this.context[0]; 8391 8392 if ( type === 'fromVisible' || type === 'toData' ) { 8393 return _fnVisibleToColumnIndex( ctx, idx ); 8394 } 8395 else if ( type === 'fromData' || type === 'toVisible' ) { 8396 return _fnColumnIndexToVisible( ctx, idx ); 8397 } 8398 } 8399 } ); 8400 8401 _api_register( 'column()', function ( selector, opts ) { 8402 return _selector_first( this.columns( selector, opts ) ); 8403 } ); 8404 8405 8406 8407 8408 var __cell_selector = function ( settings, selector, opts ) 8409 { 8410 var data = settings.aoData; 8411 var rows = _selector_row_indexes( settings, opts ); 8412 var cells = _removeEmpty( _pluck_order( data, rows, 'anCells' ) ); 8413 var allCells = $( [].concat.apply([], cells) ); 8414 var row; 8415 var columns = settings.aoColumns.length; 8416 var a, i, ien, j, o, host; 8417 8418 var run = function ( s ) { 8419 var fnSelector = typeof s === 'function'; 8420 8421 if ( s === null || s === undefined || fnSelector ) { 8422 // All cells and function selectors 8423 a = []; 8424 8425 for ( i=0, ien=rows.length ; i<ien ; i++ ) { 8426 row = rows[i]; 8427 8428 for ( j=0 ; j<columns ; j++ ) { 8429 o = { 8430 row: row, 8431 column: j 8432 }; 8433 8434 if ( fnSelector ) { 8435 // Selector - function 8436 host = settings.aoData[ row ]; 8437 8438 if ( s( o, _fnGetCellData(settings, row, j), host.anCells ? host.anCells[j] : null ) ) { 8439 a.push( o ); 8440 } 8441 } 8442 else { 8443 // Selector - all 8444 a.push( o ); 8445 } 8446 } 8447 } 8448 8449 return a; 8450 } 8451 8452 // Selector - index 8453 if ( $.isPlainObject( s ) ) { 8454 return [s]; 8455 } 8456 8457 // Selector - jQuery filtered cells 8458 return allCells 8459 .filter( s ) 8460 .map( function (i, el) { 8461 row = el.parentNode._DT_RowIndex; 8462 8463 return { 8464 row: row, 8465 column: $.inArray( el, data[ row ].anCells ) 8466 }; 8467 } ) 8468 .toArray(); 8469 }; 8470 8471 return _selector_run( 'cell', selector, run, settings, opts ); 8472 }; 8473 8474 8475 8476 8477 _api_register( 'cells()', function ( rowSelector, columnSelector, opts ) { 8478 // Argument shifting 8479 if ( $.isPlainObject( rowSelector ) ) { 8480 // Indexes 8481 if ( rowSelector.row === undefined ) { 8482 // Selector options in first parameter 8483 opts = rowSelector; 8484 rowSelector = null; 8485 } 8486 else { 8487 // Cell index objects in first parameter 8488 opts = columnSelector; 8489 columnSelector = null; 8490 } 8491 } 8492 if ( $.isPlainObject( columnSelector ) ) { 8493 opts = columnSelector; 8494 columnSelector = null; 8495 } 8496 8497 // Cell selector 8498 if ( columnSelector === null || columnSelector === undefined ) { 8499 return this.iterator( 'table', function ( settings ) { 8500 return __cell_selector( settings, rowSelector, _selector_opts( opts ) ); 8501 } ); 8502 } 8503 8504 // Row + column selector 8505 var columns = this.columns( columnSelector, opts ); 8506 var rows = this.rows( rowSelector, opts ); 8507 var a, i, ien, j, jen; 8508 8509 var cells = this.iterator( 'table', function ( settings, idx ) { 8510 a = []; 8511 8512 for ( i=0, ien=rows[idx].length ; i<ien ; i++ ) { 8513 for ( j=0, jen=columns[idx].length ; j<jen ; j++ ) { 8514 a.push( { 8515 row: rows[idx][i], 8516 column: columns[idx][j] 8517 } ); 8518 } 8519 } 8520 8521 return a; 8522 }, 1 ); 8523 8524 $.extend( cells.selector, { 8525 cols: columnSelector, 8526 rows: rowSelector, 8527 opts: opts 8528 } ); 8529 8530 return cells; 8531 } ); 8532 8533 8534 _api_registerPlural( 'cells().nodes()', 'cell().node()', function () { 8535 return this.iterator( 'cell', function ( settings, row, column ) { 8536 var cells = settings.aoData[ row ].anCells; 8537 return cells ? 8538 cells[ column ] : 8539 undefined; 8540 }, 1 ); 8541 } ); 8542 8543 8544 _api_register( 'cells().data()', function () { 8545 return this.iterator( 'cell', function ( settings, row, column ) { 8546 return _fnGetCellData( settings, row, column ); 8547 }, 1 ); 8548 } ); 8549 8550 8551 _api_registerPlural( 'cells().cache()', 'cell().cache()', function ( type ) { 8552 type = type === 'search' ? '_aFilterData' : '_aSortData'; 8553 8554 return this.iterator( 'cell', function ( settings, row, column ) { 8555 return settings.aoData[ row ][ type ][ column ]; 8556 }, 1 ); 8557 } ); 8558 8559 8560 _api_registerPlural( 'cells().render()', 'cell().render()', function ( type ) { 8561 return this.iterator( 'cell', function ( settings, row, column ) { 8562 return _fnGetCellData( settings, row, column, type ); 8563 }, 1 ); 8564 } ); 8565 8566 8567 _api_registerPlural( 'cells().indexes()', 'cell().index()', function () { 8568 return this.iterator( 'cell', function ( settings, row, column ) { 8569 return { 8570 row: row, 8571 column: column, 8572 columnVisible: _fnColumnIndexToVisible( settings, column ) 8573 }; 8574 }, 1 ); 8575 } ); 8576 8577 8578 _api_registerPlural( 'cells().invalidate()', 'cell().invalidate()', function ( src ) { 8579 return this.iterator( 'cell', function ( settings, row, column ) { 8580 _fnInvalidate( settings, row, src, column ); 8581 } ); 8582 } ); 8583 8584 8585 8586 _api_register( 'cell()', function ( rowSelector, columnSelector, opts ) { 8587 return _selector_first( this.cells( rowSelector, columnSelector, opts ) ); 8588 } ); 8589 8590 8591 _api_register( 'cell().data()', function ( data ) { 8592 var ctx = this.context; 8593 var cell = this[0]; 8594 8595 if ( data === undefined ) { 8596 // Get 8597 return ctx.length && cell.length ? 8598 _fnGetCellData( ctx[0], cell[0].row, cell[0].column ) : 8599 undefined; 8600 } 8601 8602 // Set 8603 _fnSetCellData( ctx[0], cell[0].row, cell[0].column, data ); 8604 _fnInvalidate( ctx[0], cell[0].row, 'data', cell[0].column ); 8605 8606 return this; 8607 } ); 8608 8609 8610 8611 /** 8612 * Get current ordering (sorting) that has been applied to the table. 8613 * 8614 * @returns {array} 2D array containing the sorting information for the first 8615 * table in the current context. Each element in the parent array represents 8616 * a column being sorted upon (i.e. multi-sorting with two columns would have 8617 * 2 inner arrays). The inner arrays may have 2 or 3 elements. The first is 8618 * the column index that the sorting condition applies to, the second is the 8619 * direction of the sort (`desc` or `asc`) and, optionally, the third is the 8620 * index of the sorting order from the `column.sorting` initialisation array. 8621 *//** 8622 * Set the ordering for the table. 8623 * 8624 * @param {integer} order Column index to sort upon. 8625 * @param {string} direction Direction of the sort to be applied (`asc` or `desc`) 8626 * @returns {DataTables.Api} this 8627 *//** 8628 * Set the ordering for the table. 8629 * 8630 * @param {array} order 1D array of sorting information to be applied. 8631 * @param {array} [...] Optional additional sorting conditions 8632 * @returns {DataTables.Api} this 8633 *//** 8634 * Set the ordering for the table. 8635 * 8636 * @param {array} order 2D array of sorting information to be applied. 8637 * @returns {DataTables.Api} this 8638 */ 8639 _api_register( 'order()', function ( order, dir ) { 8640 var ctx = this.context; 8641 8642 if ( order === undefined ) { 8643 // get 8644 return ctx.length !== 0 ? 8645 ctx[0].aaSorting : 8646 undefined; 8647 } 8648 8649 // set 8650 if ( typeof order === 'number' ) { 8651 // Simple column / direction passed in 8652 order = [ [ order, dir ] ]; 8653 } 8654 else if ( ! $.isArray( order[0] ) ) { 8655 // Arguments passed in (list of 1D arrays) 8656 order = Array.prototype.slice.call( arguments ); 8657 } 8658 // otherwise a 2D array was passed in 8659 8660 return this.iterator( 'table', function ( settings ) { 8661 settings.aaSorting = order.slice(); 8662 } ); 8663 } ); 8664 8665 8666 /** 8667 * Attach a sort listener to an element for a given column 8668 * 8669 * @param {node|jQuery|string} node Identifier for the element(s) to attach the 8670 * listener to. This can take the form of a single DOM node, a jQuery 8671 * collection of nodes or a jQuery selector which will identify the node(s). 8672 * @param {integer} column the column that a click on this node will sort on 8673 * @param {function} [callback] callback function when sort is run 8674 * @returns {DataTables.Api} this 8675 */ 8676 _api_register( 'order.listener()', function ( node, column, callback ) { 8677 return this.iterator( 'table', function ( settings ) { 8678 _fnSortAttachListener( settings, node, column, callback ); 8679 } ); 8680 } ); 8681 8682 8683 // Order by the selected column(s) 8684 _api_register( [ 8685 'columns().order()', 8686 'column().order()' 8687 ], function ( dir ) { 8688 var that = this; 8689 8690 return this.iterator( 'table', function ( settings, i ) { 8691 var sort = []; 8692 8693 $.each( that[i], function (j, col) { 8694 sort.push( [ col, dir ] ); 8695 } ); 8696 8697 settings.aaSorting = sort; 8698 } ); 8699 } ); 8700 8701 8702 8703 _api_register( 'search()', function ( input, regex, smart, caseInsen ) { 8704 var ctx = this.context; 8705 8706 if ( input === undefined ) { 8707 // get 8708 return ctx.length !== 0 ? 8709 ctx[0].oPreviousSearch.sSearch : 8710 undefined; 8711 } 8712 8713 // set 8714 return this.iterator( 'table', function ( settings ) { 8715 if ( ! settings.oFeatures.bFilter ) { 8716 return; 8717 } 8718 8719 _fnFilterComplete( settings, $.extend( {}, settings.oPreviousSearch, { 8720 "sSearch": input+"", 8721 "bRegex": regex === null ? false : regex, 8722 "bSmart": smart === null ? true : smart, 8723 "bCaseInsensitive": caseInsen === null ? true : caseInsen 8724 } ), 1 ); 8725 } ); 8726 } ); 8727 8728 8729 _api_registerPlural( 8730 'columns().search()', 8731 'column().search()', 8732 function ( input, regex, smart, caseInsen ) { 8733 return this.iterator( 'column', function ( settings, column ) { 8734 var preSearch = settings.aoPreSearchCols; 8735 8736 if ( input === undefined ) { 8737 // get 8738 return preSearch[ column ].sSearch; 8739 } 8740 8741 // set 8742 if ( ! settings.oFeatures.bFilter ) { 8743 return; 8744 } 8745 8746 $.extend( preSearch[ column ], { 8747 "sSearch": input+"", 8748 "bRegex": regex === null ? false : regex, 8749 "bSmart": smart === null ? true : smart, 8750 "bCaseInsensitive": caseInsen === null ? true : caseInsen 8751 } ); 8752 8753 _fnFilterComplete( settings, settings.oPreviousSearch, 1 ); 8754 } ); 8755 } 8756 ); 8757 8758 /* 8759 * State API methods 8760 */ 8761 8762 _api_register( 'state()', function () { 8763 return this.context.length ? 8764 this.context[0].oSavedState : 8765 null; 8766 } ); 8767 8768 8769 _api_register( 'state.clear()', function () { 8770 return this.iterator( 'table', function ( settings ) { 8771 // Save an empty object 8772 settings.fnStateSaveCallback.call( settings.oInstance, settings, {} ); 8773 } ); 8774 } ); 8775 8776 8777 _api_register( 'state.loaded()', function () { 8778 return this.context.length ? 8779 this.context[0].oLoadedState : 8780 null; 8781 } ); 8782 8783 8784 _api_register( 'state.save()', function () { 8785 return this.iterator( 'table', function ( settings ) { 8786 _fnSaveState( settings ); 8787 } ); 8788 } ); 8789 8790 8791 8792 /**
8793 * Provide a common method for plug-ins to check the version of DataTables being 8794 * used, in order to ensure compatibility. 8795 * 8796 * @param {string} version Version string to check for, in the format "X.Y.Z". 8797 * Note that the formats "X" and "X.Y" are also acceptable. 8798 * @returns {boolean} true if this version of DataTables is greater or equal to 8799 * the required version, or false if this version of DataTales is not 8800 * suitable 8801 * @static 8802 * @dtopt API-Static 8803 * 8804 * @example 8805 * alert( $.fn.dataTable.versionCheck( '1.9.0' ) ); 8806 */ 8807 DataTable.versionCheck = DataTable.fnVersionCheck = function( version ) 8808 { 8809 var aThis = DataTable.version.split('.'); 8810 var aThat = version.split('.'); 8811 var iThis, iThat; 8812 8813 for ( var i=0, iLen=aThat.length ; i<iLen ; i++ ) { 8814 iThis = parseInt( aThis[i], 10 ) || 0; 8815 iThat = parseInt( aThat[i], 10 ) || 0; 8816 8817 // Parts are the same, keep comparing 8818 if (iThis === iThat) { 8819 continue; 8820 } 8821 8822 // Parts are different, return immediately 8823 return iThis > iThat; 8824 } 8825 8826 return true; 8827 }; 8828 8829 8830 /** 8831 * Check if a `<table>` node is a DataTable table already or not. 8832 * 8833 * @param {node|jquery|string} table Table node, jQuery object or jQuery 8834 * selector for the table to test. Note that if more than more than one 8835 * table is passed on, only the first will be checked 8836 * @returns {boolean} true the table given is a DataTable, or false otherwise 8837 * @static 8838 * @dtopt API-Static 8839 * 8840 * @example 8841 * if ( ! $.fn.DataTable.isDataTable( '#example' ) ) { 8842 * $('#example').dataTable(); 8843 * } 8844 */ 8845 DataTable.isDataTable = DataTable.fnIsDataTable = function ( table ) 8846 { 8847 var t = $(table).get(0); 8848 var is = false; 8849 8850 $.each( DataTable.settings, function (i, o) { 8851 var head = o.nScrollHead ? $('table', o.nScrollHead)[0] : null; 8852 var foot = o.nScrollFoot ? $('table', o.nScrollFoot)[0] : null; 8853 8854 if ( o.nTable === t || head === t || foot === t ) { 8855 is = true; 8856 } 8857 } ); 8858 8859 return is; 8860 }; 8861 8862 8863 /** 8864 * Get all DataTable tables that have been initialised - optionally you can 8865 * select to get only currently visible tables. 8866 * 8867 * @param {boolean} [visible=false] Flag to indicate if you want all (default) 8868 * or visible tables only. 8869 * @returns {array} Array of `table` nodes (not DataTable instances) which are 8870 * DataTables 8871 * @static 8872 * @dtopt API-Static 8873 * 8874 * @example 8875 * $.each( $.fn.dataTable.tables(true), function () { 8876 * $(table).DataTable().columns.adjust(); 8877 * } ); 8878 */ 8879 DataTable.tables = DataTable.fnTables = function ( visible ) 8880 { 8881 return $.map( DataTable.settings, function (o) { 8882 if ( !visible || (visible && $(o.nTable).is(':visible')) ) { 8883 return o.nTable; 8884 } 8885 } ); 8886 }; 8887 8888 8889 /** 8890 * DataTables utility methods 8891 * 8892 * This namespace provides helper methods that DataTables uses internally to 8893 * create a DataTable, but which are not exclusively used only for DataTables. 8894 * These methods can be used by extension authors to save the duplication of 8895 * code. 8896 * 8897 * @namespace 8898 */ 8899 DataTable.util = { 8900 /** 8901 * Throttle the calls to a function. Arguments and context are maintained 8902 * for the throttled function. 8903 * 8904 * @param {function} fn Function to be called 8905 * @param {integer} freq Call frequency in mS 8906 * @return {function} Wrapped function 8907 */ 8908 throttle: _fnThrottle, 8909 8910 8911 /** 8912 * Escape a string such that it can be used in a regular expression 8913 * 8914 * @param {string} sVal string to escape 8915 * @returns {string} escaped string 8916 */ 8917 escapeRegex: _fnEscapeRegex 8918 }; 8919 8920 8921 /** 8922 * Convert from camel case parameters to Hungarian notation. This is made public 8923 * for the extensions to provide the same ability as DataTables core to accept 8924 * either the 1.9 style Hungarian notation, or the 1.10+ style camelCase 8925 * parameters. 8926 * 8927 * @param {object} src The model object which holds all parameters that can be 8928 * mapped. 8929 * @param {object} user The object to convert from camel case to Hungarian. 8930 * @param {boolean} force When set to `true`, properties which already have a 8931 * Hungarian value in the `user` object will be overwritten. Otherwise they 8932 * won't be. 8933 */ 8934 DataTable.camelToHungarian = _fnCamelToHungarian; 8935 8936 8937 8938 /** 8939 * 8940 */ 8941 _api_register( '$()', function ( selector, opts ) { 8942 var 8943 rows = this.rows( opts ).nodes(), // Get all rows 8944 jqRows = $(rows); 8945 8946 return $( [].concat( 8947 jqRows.filter( selector ).toArray(), 8948 jqRows.find( selector ).toArray() 8949 ) ); 8950 } ); 8951 8952 8953 // jQuery functions to operate on the tables 8954 $.each( [ 'on', 'one', 'off' ], function (i, key) { 8955 _api_register( key+'()', function ( /* event, handler */ ) { 8956 var args = Array.prototype.slice.call(arguments); 8957 8958 // Add the `dt` namespace automatically if it isn't already present 8959 if ( ! args[0].match(/\.dt\b/) ) { 8960 args[0] += '.dt'; 8961 } 8962 8963 var inst = $( this.tables().nodes() ); 8964 inst[key].apply( inst, args ); 8965 return this; 8966 } ); 8967 } ); 8968 8969 8970 _api_register( 'clear()', function () { 8971 return this.iterator( 'table', function ( settings ) { 8972 _fnClearTable( settings ); 8973 } ); 8974 } ); 8975 8976 8977 _api_register( 'settings()', function () { 8978 return new _Api( this.context, this.context ); 8979 } ); 8980 8981 8982 _api_register( 'init()', function () { 8983 var ctx = this.context; 8984 return ctx.length ? ctx[0].oInit : null; 8985 } ); 8986 8987 8988 _api_register( 'data()', function () { 8989 return this.iterator( 'table', function ( settings ) { 8990 return _pluck( settings.aoData, '_aData' ); 8991 } ).flatten(); 8992 } ); 8993 8994 8995 _api_register( 'destroy()', function ( remove ) { 8996 remove = remove || false; 8997 8998 return this.iterator( 'table', function ( settings ) { 8999 var orig = settings.nTableWrapper.parentNode; 9000 var classes = settings.oClasses; 9001 var table = settings.nTable; 9002 var tbody = settings.nTBody; 9003 var thead = settings.nTHead; 9004 var tfoot = settings.nTFoot; 9005 var jqTable = $(table); 9006 var jqTbody = $(tbody); 9007 var jqWrapper = $(settings.nTableWrapper); 9008 var rows = $.map( settings.aoData, function (r) { return r.nTr; } ); 9009 var i, ien; 9010 9011 // Flag to note that the table is currently being destroyed - no action 9012 // should be taken 9013 settings.bDestroying = true; 9014
9015 // Fire off the destroy callbacks for plug-ins etc 9016 _fnCallbackFire( settings, "aoDestroyCallback", "destroy", [settings] ); 9017 9018 // If not being removed from the document, make all columns visible 9019 if ( ! remove ) { 9020 new _Api( settings ).columns().visible( true ); 9021 } 9022 9023 // Blitz all `DT` namespaced events (these are internal events, the 9024 // lowercase, `dt` events are user subscribed and they are responsible 9025 // for removing them 9026 jqWrapper.unbind('.DT').find(':not(tbody *)').unbind('.DT'); 9027 $(window).unbind('.DT-'+settings.sInstance); 9028 9029 // When scrolling we had to break the table up - restore it 9030 if ( table != thead.parentNode ) { 9031 jqTable.children('thead').detach(); 9032 jqTable.append( thead ); 9033 } 9034 9035 if ( tfoot && table != tfoot.parentNode ) { 9036 jqTable.children('tfoot').detach(); 9037 jqTable.append( tfoot ); 9038 } 9039 9040 // Remove the DataTables generated nodes, events and classes 9041 jqTable.detach(); 9042 jqWrapper.detach(); 9043 9044 settings.aaSorting = []; 9045 settings.aaSortingFixed = []; 9046 _fnSortingClasses( settings ); 9047 9048 $( rows ).removeClass( settings.asStripeClasses.join(' ') ); 9049 9050 $('th, td', thead).removeClass( classes.sSortable+' '+ 9051 classes.sSortableAsc+' '+classes.sSortableDesc+' '+classes.sSortableNone 9052 ); 9053 9054 if ( settings.bJUI ) { 9055 $('th span.'+classes.sSortIcon+ ', td span.'+classes.sSortIcon, thead).detach(); 9056 $('th, td', thead).each( function () { 9057 var wrapper = $('div.'+classes.sSortJUIWrapper, this); 9058 $(this).append( wrapper.contents() ); 9059 wrapper.detach(); 9060 } ); 9061 } 9062 9063 if ( ! remove && orig ) { 9064 // insertBefore acts like appendChild if !arg[1] 9065 orig.insertBefore( table, settings.nTableReinsertBefore ); 9066 } 9067 9068 // Add the TR elements back into the table in their original order 9069 jqTbody.children().detach(); 9070 jqTbody.append( rows ); 9071 9072 // Restore the width of the original table - was read from the style property, 9073 // so we can restore directly to that 9074 jqTable 9075 .css( 'width', settings.sDestroyWidth ) 9076 .removeClass( classes.sTable ); 9077 9078 // If the were originally stripe classes - then we add them back here. 9079 // Note this is not fool proof (for example if not all rows had stripe 9080 // classes - but it's a good effort without getting carried away 9081 ien = settings.asDestroyStripes.length; 9082 9083 if ( ien ) { 9084 jqTbody.children().each( function (i) { 9085 $(this).addClass( settings.asDestroyStripes[i % ien] ); 9086 } ); 9087 } 9088 9089 /* Remove the settings object from the settings array */ 9090 var idx = $.inArray( settings, DataTable.settings ); 9091 if ( idx !== -1 ) { 9092 DataTable.settings.splice( idx, 1 ); 9093 } 9094 } ); 9095 } ); 9096 9097 9098 // Add the `every()` method for rows, columns and cells in a compact form 9099 $.each( [ 'column', 'row', 'cell' ], function ( i, type ) { 9100 _api_register( type+'s().every()', function ( fn ) { 9101 return this.iterator( type, function ( settings, idx, idx2 ) { 9102 // idx2 is undefined for rows and columns. 9103 fn.call( new _Api( settings )[ type ]( idx, idx2 ) ); 9104 } ); 9105 } ); 9106 } ); 9107 9108 9109 // i18n method for extensions to be able to use the language object from the 9110 // DataTable 9111 _api_register( 'i18n()', function ( token, def, plural ) { 9112 var ctx = this.context[0]; 9113 var resolved = _fnGetObjectDataFn( token )( ctx.oLanguage ); 9114 9115 if ( resolved === undefined ) { 9116 resolved = def; 9117 } 9118 9119 if ( plural !== undefined && $.isPlainObject( resolved ) ) { 9120 resolved = resolved[ plural ] !== undefined ? 9121 resolved[ plural ] : 9122 resolved._; 9123 } 9124 9125 return resolved.replace( '%d', plural ); // nb: plural might be undefined, 9126 } ); 9127 9128 /** 9129 * Version string for plug-ins to check compatibility. Allowed format is 9130 * `a.b.c-d` where: a:int, b:int, c:int, d:string(dev|beta|alpha). `d` is used 9131 * only for non-release builds. See http://semver.org/ for more information. 9132 * @member 9133 * @type string 9134 * @default Version number 9135 */ 9136 DataTable.version = "1.10.7"; 9137 9138 /** 9139 * Private data store, containing all of the settings objects that are 9140 * created for the tables on a given page. 9141 * 9142 * Note that the `DataTable.settings` object is aliased to 9143 * `jQuery.fn.dataTableExt` through which it may be accessed and 9144 * manipulated, or `jQuery.fn.dataTable.settings`. 9145 * @member 9146 * @type array 9147 * @default [] 9148 * @private 9149 */ 9150 DataTable.settings = []; 9151 9152 /** 9153 * Object models container, for the various models that DataTables has 9154 * available to it. These models define the objects that are used to hold 9155 * the active state and configuration of the table. 9156 * @namespace 9157 */ 9158 DataTable.models = {}; 9159 9160 9161 9162 /** 9163 * Template object for the way in which DataTables holds information about 9164 * search information for the global filter and individual column filters. 9165 * @namespace 9166 */ 9167 DataTable.models.oSearch = { 9168 /** 9169 * Flag to indicate if the filtering should be case insensitive or not 9170 * @type boolean 9171 * @default true 9172 */ 9173 "bCaseInsensitive": true, 9174 9175 /** 9176 * Applied search term 9177 * @type string 9178 * @default <i>Empty string</i> 9179 */ 9180 "sSearch": "", 9181 9182 /** 9183 * Flag to indicate if the search term should be interpreted as a 9184 * regular expression (true) or not (false) and therefore and special 9185 * regex characters escaped. 9186 * @type boolean 9187 * @default false 9188 */ 9189 "bRegex": false, 9190 9191 /** 9192 * Flag to indicate if DataTables is to use its smart filtering or not. 9193 * @type boolean 9194 * @default true 9195 */ 9196 "bSmart": true 9197 }; 9198 9199 9200 9201 9202 /** 9203 * Template object for the way in which DataTables holds information about 9204 * each individual row. This is the object format used for the settings 9205 * aoData array.
9206 * @namespace 9207 */ 9208 DataTable.models.oRow = { 9209 /** 9210 * TR element for the row 9211 * @type node 9212 * @default null 9213 */ 9214 "nTr": null, 9215 9216 /** 9217 * Array of TD elements for each row. This is null until the row has been 9218 * created. 9219 * @type array nodes 9220 * @default [] 9221 */ 9222 "anCells": null, 9223 9224 /** 9225 * Data object from the original data source for the row. This is either 9226 * an array if using the traditional form of DataTables, or an object if 9227 * using mData options. The exact type will depend on the passed in 9228 * data from the data source, or will be an array if using DOM a data 9229 * source. 9230 * @type array|object 9231 * @default [] 9232 */ 9233 "_aData": [], 9234 9235 /** 9236 * Sorting data cache - this array is ostensibly the same length as the 9237 * number of columns (although each index is generated only as it is 9238 * needed), and holds the data that is used for sorting each column in the 9239 * row. We do this cache generation at the start of the sort in order that 9240 * the formatting of the sort data need be done only once for each cell 9241 * per sort. This array should not be read from or written to by anything 9242 * other than the master sorting methods. 9243 * @type array 9244 * @default null 9245 * @private 9246 */ 9247 "_aSortData": null, 9248 9249 /** 9250 * Per cell filtering data cache. As per the sort data cache, used to 9251 * increase the performance of the filtering in DataTables 9252 * @type array 9253 * @default null 9254 * @private 9255 */ 9256 "_aFilterData": null, 9257 9258 /** 9259 * Filtering data cache. This is the same as the cell filtering cache, but 9260 * in this case a string rather than an array. This is easily computed with 9261 * a join on `_aFilterData`, but is provided as a cache so the join isn't 9262 * needed on every search (memory traded for performance) 9263 * @type array 9264 * @default null 9265 * @private 9266 */ 9267 "_sFilterRow": null, 9268 9269 /** 9270 * Cache of the class name that DataTables has applied to the row, so we 9271 * can quickly look at this variable rather than needing to do a DOM check 9272 * on className for the nTr property. 9273 * @type string 9274 * @default <i>Empty string</i> 9275 * @private 9276 */ 9277 "_sRowStripe": "", 9278 9279 /** 9280 * Denote if the original data source was from the DOM, or the data source 9281 * object. This is used for invalidating data, so DataTables can 9282 * automatically read data from the original source, unless uninstructed 9283 * otherwise. 9284 * @type string 9285 * @default null 9286 * @private 9287 */ 9288 "src": null 9289 }; 9290 9291 9292 /** 9293 * Template object for the column information object in DataTables. This object 9294 * is held in the settings aoColumns array and contains all the information that 9295 * DataTables needs about each individual column. 9296 * 9297 * Note that this object is related to {@link DataTable.defaults.column} 9298 * but this one is the internal data store for DataTables's cache of columns. 9299 * It should NOT be manipulated outside of DataTables. Any configuration should 9300 * be done through the initialisation options. 9301 * @namespace 9302 */ 9303 DataTable.models.oColumn = { 9304 /** 9305 * Column index. This could be worked out on-the-fly with $.inArray, but it 9306 * is faster to just hold it as a variable 9307 * @type integer 9308 * @default null 9309 */ 9310 "idx": null, 9311 9312 /** 9313 * A list of the columns that sorting should occur on when this column 9314 * is sorted. That this property is an array allows multi-column sorting 9315 * to be defined for a column (for example first name / last name columns 9316 * would benefit from this). The values are integers pointing to the 9317 * columns to be sorted on (typically it will be a single integer pointing 9318 * at itself, but that doesn't need to be the case). 9319 * @type array 9320 */ 9321 "aDataSort": null, 9322 9323 /** 9324 * Define the sorting directions that are applied to the column, in sequence 9325 * as the column is repeatedly sorted upon - i.e. the first value is used 9326 * as the sorting direction when the column if first sorted (clicked on). 9327 * Sort it again (click again) and it will move on to the next index. 9328 * Repeat until loop. 9329 * @type array 9330 */ 9331 "asSorting": null, 9332 9333 /** 9334 * Flag to indicate if the column is searchable, and thus should be included 9335 * in the filtering or not. 9336 * @type boolean 9337 */ 9338 "bSearchable": null, 9339 9340 /** 9341 * Flag to indicate if the column is sortable or not. 9342 * @type boolean 9343 */ 9344 "bSortable": null, 9345 9346 /** 9347 * Flag to indicate if the column is currently visible in the table or not 9348 * @type boolean 9349 */ 9350 "bVisible": null, 9351 9352 /** 9353 * Store for manual type assignment using the `column.type` option. This 9354 * is held in store so we can manipulate the column's `sType` property. 9355 * @type string 9356 * @default null 9357 * @private 9358 */ 9359 "_sManualType": null, 9360 9361 /** 9362 * Flag to indicate if HTML5 data attributes should be used as the data 9363 * source for filtering or sorting. True is either are. 9364 * @type boolean 9365 * @default false 9366 * @private 9367 */ 9368 "_bAttrSrc": false, 9369 9370 /** 9371 * Developer definable function that is called whenever a cell is created (Ajax source, 9372 * etc) or processed for input (DOM source). This can be used as a compliment to mRender 9373 * allowing you to modify the DOM element (add background colour for example) when the 9374 * element is available. 9375 * @type function 9376 * @param {element} nTd The TD node that has been created 9377 * @param {*} sData The Data for the cell 9378 * @param {array|object} oData The data for the whole row 9379 * @param {int} iRow The row index for the aoData data store 9380 * @default null 9381 */ 9382 "fnCreatedCell": null, 9383 9384 /** 9385 * Function to get data from a cell in a column. You should <b>never</b> 9386 * access data directly through _aData internally in DataTables - always use 9387 * the method attached to this property. It allows mData to function as 9388 * required. This function is automatically assigned by the column 9389 * initialisation method 9390 * @type function 9391 * @param {array|object} oData The data array/object for the array 9392 * (i.e. aoData[]._aData) 9393 * @param {string} sSpecific The specific data type you want to get - 9394 * 'display', 'type' 'filter' 'sort' 9395 * @returns {*} The data for the cell from the given row's data 9396 * @default null 9397 */ 9398 "fnGetData": null, 9399 9400 /** 9401 * Function to set data for a cell in the column. You should <b>never</b> 9402 * set the data directly to _aData internally in DataTables - always use 9403 * this method. It allows mData to function as required. This function 9404 * is automatically assigned by the column initialisation method 9405 * @type function 9406 * @param {array|object} oData The data array/object for the array 9407 * (i.e. aoData[]._aData) 9408 * @param {*} sValue Value to set 9409 * @default null 9410 */ 9411 "fnSetData": null, 9412 9413 /** 9414 * Property to read the value for the cells in the column from the data 9415 * source array / object. If null, then the default content is used, if a 9416 * function is given then the return from the function is used. 9417 * @type function|int|string|null 9418 * @default null 9419 */ 9420 "mData": null, 9421 9422 /** 9423 * Partner property to mData which is used (only when defined) to get 9424 * the data - i.e. it is basically the same as mData, but without the 9425 * 'set' option, and also the data fed to it is the result from mData. 9426 * This is the rendering method to match the data method of mData. 9427 * @type function|int|string|null 9428 * @default null 9429 */
9430 "mRender": null, 9431 9432 /** 9433 * Unique header TH/TD element for this column - this is what the sorting 9434 * listener is attached to (if sorting is enabled.) 9435 * @type node 9436 * @default null 9437 */ 9438 "nTh": null, 9439 9440 /** 9441 * Unique footer TH/TD element for this column (if there is one). Not used 9442 * in DataTables as such, but can be used for plug-ins to reference the 9443 * footer for each column. 9444 * @type node 9445 * @default null 9446 */ 9447 "nTf": null, 9448 9449 /** 9450 * The class to apply to all TD elements in the table's TBODY for the column 9451 * @type string 9452 * @default null 9453 */ 9454 "sClass": null, 9455 9456 /** 9457 * When DataTables calculates the column widths to assign to each column, 9458 * it finds the longest string in each column and then constructs a 9459 * temporary table and reads the widths from that. The problem with this 9460 * is that "mmm" is much wider then "iiii", but the latter is a longer 9461 * string - thus the calculation can go wrong (doing it properly and putting 9462 * it into an DOM object and measuring that is horribly(!) slow). Thus as 9463 * a "work around" we provide this option. It will append its value to the 9464 * text that is found to be the longest string for the column - i.e. padding. 9465 * @type string 9466 */ 9467 "sContentPadding": null, 9468 9469 /** 9470 * Allows a default value to be given for a column's data, and will be used 9471 * whenever a null data source is encountered (this can be because mData 9472 * is set to null, or because the data source itself is null). 9473 * @type string 9474 * @default null 9475 */ 9476 "sDefaultContent": null, 9477 9478 /** 9479 * Name for the column, allowing reference to the column by name as well as 9480 * by index (needs a lookup to work by name). 9481 * @type string 9482 */ 9483 "sName": null, 9484 9485 /** 9486 * Custom sorting data type - defines which of the available plug-ins in 9487 * afnSortData the custom sorting will use - if any is defined. 9488 * @type string 9489 * @default std 9490 */ 9491 "sSortDataType": 'std', 9492 9493 /** 9494 * Class to be applied to the header element when sorting on this column 9495 * @type string 9496 * @default null 9497 */ 9498 "sSortingClass": null, 9499 9500 /** 9501 * Class to be applied to the header element when sorting on this column - 9502 * when jQuery UI theming is used. 9503 * @type string 9504 * @default null 9505 */ 9506 "sSortingClassJUI": null, 9507 9508 /** 9509 * Title of the column - what is seen in the TH element (nTh). 9510 * @type string 9511 */ 9512 "sTitle": null, 9513 9514 /** 9515 * Column sorting and filtering type 9516 * @type string 9517 * @default null 9518 */ 9519 "sType": null, 9520 9521 /** 9522 * Width of the column 9523 * @type string 9524 * @default null 9525 */ 9526 "sWidth": null, 9527 9528 /** 9529 * Width of the column when it was first "encountered" 9530 * @type string 9531 * @default null 9532 */ 9533 "sWidthOrig": null 9534 }; 9535 9536 9537 /* 9538 * Developer note: The properties of the object below are given in Hungarian 9539 * notation, that was used as the interface for DataTables prior to v1.10, however 9540 * from v1.10 onwards the primary interface is camel case. In order to avoid 9541 * breaking backwards compatibility utterly with this change, the Hungarian 9542 * version is still, internally the primary interface, but is is not documented 9543 * - hence the @name tags in each doc comment. This allows a Javascript function 9544 * to create a map from Hungarian notation to camel case (going the other direction 9545 * would require each property to be listed, which would at around 3K to the size 9546 * of DataTables, while this method is about a 0.5K hit
vendor: 16,919 bytes, lines 9546-10057
9546. 9547 * 9548 * Ultimately this does pave the way for Hungarian notation to be dropped 9549 * completely, but that is a massive amount of work and will break current 9550 * installs (therefore is on-hold until v2). 9551 */ 9552 9553 /** 9554 * Initialisation options that can be given to DataTables at initialisation 9555 * time. 9556 * @namespace 9557 */ 9558 DataTable.defaults = { 9559 /** 9560 * An array of data to use for the table, passed in at initialisation which 9561 * will be used in preference to any data which is already in the DOM. This is 9562 * particularly useful for constructing tables purely in Javascript, for 9563 * example with a custom Ajax call. 9564 * @type array 9565 * @default null 9566 * 9567 * @dtopt Option 9568 * @name DataTable.defaults.data 9569 * 9570 * @example 9571 * // Using a 2D array data source 9572 * $(document).ready( function () { 9573 * $('#example').dataTable( { 9574 * "data": [ 9575 * ['Trident', 'Internet Explorer 4.0', 'Win 95+', 4, 'X'], 9576 * ['Trident', 'Internet Explorer 5.0', 'Win 95+', 5, 'C'], 9577 * ], 9578 * "columns": [ 9579 * { "title": "Engine" }, 9580 * { "title": "Browser" }, 9581 * { "title": "Platform" }, 9582 * { "title": "Version" }, 9583 * { "title": "Grade" } 9584 * ] 9585 * } ); 9586 * } ); 9587 * 9588 * @example 9589 * // Using an array of objects as a data source (`data`) 9590 * $(document).ready( function () { 9591 * $('#example').dataTable( { 9592 * "data": [ 9593 * { 9594 * "engine": "Trident", 9595 * "browser": "Internet Explorer 4.0", 9596 * "platform": "Win 95+", 9597 * "version": 4, 9598 * "grade": "X" 9599 * }, 9600 * { 9601 * "engine": "Trident", 9602 * "browser": "Internet Explorer 5.0", 9603 * "platform": "Win 95+", 9604 * "version": 5, 9605 * "grade": "C" 9606 * } 9607 * ], 9608 * "columns": [ 9609 * { "title": "Engine", "data": "engine" }, 9610 * { "title": "Browser", "data": "browser" }, 9611 * { "title": "Platform", "data": "platform" }, 9612 * { "title": "Version", "data": "version" }, 9613 * { "title": "Grade", "data": "grade" } 9614 * ] 9615 * } ); 9616 * } ); 9617 */ 9618 "aaData": null, 9619 9620 9621 /** 9622 * If ordering is enabled, then DataTables will perform a first pass sort on 9623 * initialisation. You can define which column(s) the sort is performed 9624 * upon, and the sorting direction, with this variable. The `sorting` array 9625 * should contain an array for each column to be sorted initially containing 9626 * the column's index and a direction string ('asc' or 'desc'). 9627 * @type array 9628 * @default [[0,'asc']] 9629 * 9630 * @dtopt Option 9631 * @name DataTable.defaults.order 9632 * 9633 * @example 9634 * // Sort by 3rd column first, and then 4th column 9635 * $(document).ready( function() { 9636 * $('#example').dataTable( { 9637 * "order": [[2,'asc'], [3,'desc']] 9638 * } ); 9639 * } ); 9640 * 9641 * // No initial sorting 9642 * $(document).ready( function() { 9643 * $('#example').dataTable( { 9644 * "order": [] 9645 * } ); 9646 * } ); 9647 */ 9648 "aaSorting": [[0,'asc']], 9649 9650 9651 /** 9652 * This parameter is basically identical to the `sorting` parameter, but 9653 * cannot be overridden by user interaction with the table. What this means 9654 * is that you could have a column (visible or hidden) which the sorting 9655 * will always be forced on first - any sorting after that (from the user) 9656 * will then be performed as required. This can be useful for grouping rows 9657 * together. 9658 * @type array 9659 * @default null 9660 * 9661 * @dtopt Option 9662 * @name DataTable.defaults.orderFixed 9663 * 9664 * @example 9665 * $(document).ready( function() { 9666 * $('#example').dataTable( { 9667 * "orderFixed": [[0,'asc']] 9668 * } ); 9669 * } ) 9670 */ 9671 "aaSortingFixed": [], 9672 9673 9674 /** 9675 * DataTables can be instructed to load data to display in the table from a 9676 * Ajax source. This option defines how that Ajax call is made and where to. 9677 * 9678 * The `ajax` property has three different modes of operation, depending on 9679 * how it is defined. These are: 9680 * 9681 * * `string` - Set the URL from where the data should be loaded from. 9682 * * `object` - Define properties for `jQuery.ajax`. 9683 * * `function` - Custom data get function 9684 * 9685 * `string` 9686 * -------- 9687 * 9688 * As a string, the `ajax` property simply defines the URL from which 9689 * DataTables will load data. 9690 * 9691 * `object` 9692 * -------- 9693 * 9694 * As an object, the parameters in the object are passed to 9695 * [jQuery.ajax](http://api.jquery.com/jQuery.ajax/) allowing fine control 9696 * of the Ajax request. DataTables has a number of default parameters which 9697 * you can override using this option. Please refer to the jQuery 9698 * documentation for a full description of the options available, although 9699 * the following parameters provide additional options in DataTables or 9700 * require special consideration: 9701 * 9702 * * `data` - As with jQuery, `data` can be provided as an object, but it 9703 * can also be used as a function to manipulate the data DataTables sends 9704 * to the server. The function takes a single parameter, an object of 9705 * parameters with the values that DataTables has readied for sending. An 9706 * object may be returned which will be merged into the DataTables 9707 * defaults, or you can add the items to the object that was passed in and 9708 * not return anything from the function. This supersedes `fnServerParams` 9709 * from DataTables 1.9-. 9710 * 9711 * * `dataSrc` - By default DataTables will look for the property `data` (or 9712 * `aaData` for compatibility with DataTables 1.9-) when obtaining data 9713 * from an Ajax source or for server-side processing - this parameter 9714 * allows that property to be changed. You can use Javascript dotted 9715 * object notation to get a data source for multiple levels of nesting, or 9716 * it my be used as a function. As a function it takes a single parameter, 9717 * the JSON returned from the server, which can be manipulated as 9718 * required, with the returned value being that used by DataTables as the 9719 * data source for the table. This supersedes `sAjaxDataProp` from 9720 * DataTables 1.9-. 9721 * 9722 * * `success` - Should not be overridden it is used internally in 9723 * DataTables. To manipulate / transform the data returned by the server 9724 * use `ajax.dataSrc`, or use `ajax` as a function (see below). 9725 * 9726 * `function` 9727 * ---------- 9728 * 9729 * As a function, making the Ajax call is left up to yourself allowing 9730 * complete control of the Ajax request. Indeed, if desired, a method other 9731 * than Ajax could be used to obtain the required data, such as Web storage 9732 * or an AIR database. 9733 * 9734 * The function is given four parameters and no return is required. The 9735 * parameters are: 9736 * 9737 * 1. _object_ - Data to send to the server 9738 * 2. _function_ - Callback function that must be executed when the required 9739 * data has been obtained. That data should be passed into the callback 9740 * as the only parameter 9741 * 3. _object_ - DataTables settings object for the table 9742 * 9743 * Note that this supersedes `fnServerData` from DataTables 1.9-. 9744 * 9745 * @type string|object|function 9746 * @default null 9747 * 9748 * @dtopt Option 9749 * @name DataTable.defaults.ajax 9750 * @since 1.10.0 9751 * 9752 * @example 9753 * // Get JSON data from a file via Ajax. 9754 * // Note DataTables expects data in the form `{ data: [ ...data... ] }` by default). 9755 * $('#example').dataTable( { 9756 * "ajax": "data.json" 9757 * } ); 9758 * 9759 * @example 9760 * // Get JSON data from a file via Ajax, using `dataSrc` to change 9761 * // `data` to `tableData` (i.e. `{ tableData: [ ...data... ] }`) 9762 * $('#example').dataTable( { 9763 * "ajax": { 9764 * "url": "data.json", 9765 * "dataSrc": "tableData" 9766 * } 9767 * } ); 9768 * 9769 * @example 9770 * // Get JSON data from a file via Ajax, using `dataSrc` to read data 9771 * // from a plain array rather than an array in an object 9772 * $('#example').dataTable( { 9773 * "ajax": { 9774 * "url": "data.json", 9775 * "dataSrc": "" 9776 * } 9777 * } ); 9778 * 9779 * @example 9780 * // Manipulate the data returned from the server - add a link to data 9781 * // (note this can, should, be done using `render` for the column - this 9782 * // is just a simple example of how the data can be manipulated). 9783 * $('#example').dataTable( { 9784 * "ajax": { 9785 * "url": "data.json", 9786 * "dataSrc": function ( json ) { 9787 * for ( var i=0, ien=json.length ; i<ien ; i++ ) { 9788 * json[i][0] = '<a href="/message/'+json[i][0]+'>View message</a>'; 9789 * } 9790 * return json; 9791 * } 9792 * } 9793 * } ); 9794 * 9795 * @example 9796 * // Add data to the request 9797 * $('#example').dataTable( { 9798 * "ajax": { 9799 * "url": "data.json", 9800 * "data": function ( d ) { 9801 * return { 9802 * "extra_search": $('#extra').val() 9803 * }; 9804 * } 9805 * } 9806 * } ); 9807 * 9808 * @example 9809 * // Send request as POST 9810 * $('#example').dataTable( { 9811 * "ajax": { 9812 * "url": "data.json", 9813 * "type": "POST" 9814 * } 9815 * } ); 9816 * 9817 * @example 9818 * // Get the data from localStorage (could interface with a form for 9819 * // adding, editing and removing rows). 9820 * $('#example').dataTable( { 9821 * "ajax": function (data, callback, settings) { 9822 * callback( 9823 * JSON.parse( localStorage.getItem('dataTablesData') ) 9824 * ); 9825 * } 9826 * } ); 9827 */ 9828 "ajax": null, 9829 9830 9831 /** 9832 * This parameter allows you to readily specify the entries in the length drop 9833 * down menu that DataTables shows when pagination is enabled. It can be 9834 * either a 1D array of options which will be used for both the displayed 9835 * option and the value, or a 2D array which will use the array in the first 9836 * position as the value, and the array in the second position as the 9837 * displayed options (useful for language strings such as 'All'). 9838 * 9839 * Note that the `pageLength` property will be automatically set to the 9840 * first value given in this array, unless `pageLength` is also provided. 9841 * @type array 9842 * @default [ 10, 25, 50, 100 ] 9843 * 9844 * @dtopt Option 9845 * @name DataTable.defaults.lengthMenu 9846 * 9847 * @example 9848 * $(document).ready( function() { 9849 * $('#example').dataTable( { 9850 * "lengthMenu": [[10, 25, 50, -1], [10, 25, 50, "All"]] 9851 * } ); 9852 * } ); 9853 */ 9854 "aLengthMenu": [ 10, 25, 50, 100 ], 9855 9856 9857 /** 9858 * The `columns` option in the initialisation parameter allows you to define 9859 * details about the way individual columns behave. For a full list of 9860 * column options that can be set, please see 9861 * {@link DataTable.defaults.column}. Note that if you use `columns` to 9862 * define your columns, you must have an entry in the array for every single 9863 * column that you have in your table (these can be null if you don't which 9864 * to specify any options). 9865 * @member 9866 * 9867 * @name DataTable.defaults.column 9868 */ 9869 "aoColumns": null, 9870 9871 /** 9872 * Very similar to `columns`, `columnDefs` allows you to target a specific 9873 * column, multiple columns, or all columns, using the `targets` property of 9874 * each object in the array. This allows great flexibility when creating 9875 * tables, as the `columnDefs` arrays can be of any length, targeting the 9876 * columns you specifically want. `columnDefs` may use any of the column 9877 * options available: {@link DataTable.defaults.column}, but it _must_ 9878 * have `targets` defined in each object in the array. Values in the `targets` 9879 * array may be: 9880 * <ul> 9881 * <li>a string - class name will be matched on the TH for the column</li> 9882 * <li>0 or a positive integer - column index counting from the left</li> 9883 * <li>a negative integer - column index counting from the right</li> 9884 * <li>the string "_all" - all columns (i.e. assign a default)</li> 9885 * </ul> 9886 * @member 9887 * 9888 * @name DataTable.defaults.columnDefs 9889 */ 9890 "aoColumnDefs": null, 9891 9892 9893 /** 9894 * Basically the same as `search`, this parameter defines the individual column 9895 * filtering state at initialisation time. The array must be of the same size 9896 * as the number of columns, and each element be an object with the parameters 9897 * `search` and `escapeRegex` (the latter is optional). 'null' is also 9898 * accepted and the default will be used. 9899 * @type array 9900 * @default [] 9901 * 9902 * @dtopt Option 9903 * @name DataTable.defaults.searchCols 9904 * 9905 * @example 9906 * $(document).ready( function() { 9907 * $('#example').dataTable( { 9908 * "searchCols": [ 9909 * null, 9910 * { "search": "My filter" }, 9911 * null, 9912 * { "search": "^[0-9]", "escapeRegex": false } 9913 * ] 9914 * } ); 9915 * } ) 9916 */ 9917 "aoSearchCols": [], 9918 9919 9920 /** 9921 * An array of CSS classes that should be applied to displayed rows. This 9922 * array may be of any length, and DataTables will apply each class 9923 * sequentially, looping when required. 9924 * @type array 9925 * @default null <i>Will take the values determined by the `oClasses.stripe*` 9926 * options</i> 9927 * 9928 * @dtopt Option 9929 * @name DataTable.defaults.stripeClasses 9930 * 9931 * @example 9932 * $(document).ready( function() { 9933 * $('#example').dataTable( { 9934 * "stripeClasses": [ 'strip1', 'strip2', 'strip3' ] 9935 * } ); 9936 * } ) 9937 */ 9938 "asStripeClasses": null, 9939 9940 9941 /** 9942 * Enable or disable automatic column width calculation. This can be disabled 9943 * as an optimisation (it takes some time to calculate the widths) if the 9944 * tables widths are passed in using `columns`. 9945 * @type boolean 9946 * @default true 9947 * 9948 * @dtopt Features 9949 * @name DataTable.defaults.autoWidth 9950 * 9951 * @example 9952 * $(document).ready( function () { 9953 * $('#example').dataTable( { 9954 * "autoWidth": false 9955 * } ); 9956 * } ); 9957 */ 9958 "bAutoWidth": true, 9959 9960 9961 /** 9962 * Deferred rendering can provide DataTables with a huge speed boost when you 9963 * are using an Ajax or JS data source for the table. This option, when set to 9964 * true, will cause DataTables to defer the creation of the table elements for 9965 * each row until they are needed for a draw - saving a significant amount of 9966 * time. 9967 * @type boolean 9968 * @default false 9969 * 9970 * @dtopt Features 9971 * @name DataTable.defaults.deferRender 9972 * 9973 * @example 9974 * $(document).ready( function() { 9975 * $('#example').dataTable( { 9976 * "ajax": "sources/arrays.txt", 9977 * "deferRender": true 9978 * } ); 9979 * } ); 9980 */ 9981 "bDeferRender": false, 9982 9983 9984 /** 9985 * Replace a DataTable which matches the given selector and replace it with 9986 * one which has the properties of the new initialisation object passed. If no 9987 * table matches the selector, then the new DataTable will be constructed as 9988 * per normal. 9989 * @type boolean 9990 * @default false 9991 * 9992 * @dtopt Options 9993 * @name DataTable.defaults.destroy 9994 * 9995 * @example 9996 * $(document).ready( function() { 9997 * $('#example').dataTable( { 9998 * "srollY": "200px", 9999 * "paginate": false 10000 * } ); 10001 * 10002 * // Some time later.... 10003 * $('#example').dataTable( { 10004 * "filter": false, 10005 * "destroy": true 10006 * } ); 10007 * } ); 10008 */ 10009 "bDestroy": false, 10010 10011 10012 /** 10013 * Enable or disable filtering of data. Filtering in DataTables is "smart" in 10014 * that it allows the end user to input multiple words (space separated) and 10015 * will match a row containing those words, even if not in the order that was 10016 * specified (this allow matching across multiple columns). Note that if you 10017 * wish to use filtering in DataTables this must remain 'true' - to remove the 10018 * default filtering input box and retain filtering abilities, please use 10019 * {@link DataTable.defaults.dom}. 10020 * @type boolean 10021 * @default true 10022 * 10023 * @dtopt Features 10024 * @name DataTable.defaults.searching 10025 * 10026 * @example 10027 * $(document).ready( function () { 10028 * $('#example').dataTable( { 10029 * "searching": false 10030 * } ); 10031 * } ); 10032 */ 10033 "bFilter": true, 10034 10035 10036 /** 10037 * Enable or disable the table information display. This shows information 10038 * about the data that is currently visible on the page, including information 10039 * about filtered data if that action is being performed. 10040 * @type boolean 10041 * @default true 10042 * 10043 * @dtopt Features 10044 * @name DataTable.defaults.info 10045 * 10046 * @example 10047 * $(document).ready( function () { 10048 * $('#example').dataTable( { 10049 * "info": false 10050 * } ); 10051 * } ); 10052 */ 10053 "bInfo": true, 10054 10055 10056 /** 10057 *
10057Enable jQuery UI ThemeRoller support (required as ThemeRoller requires some 10058 * slightly different and additional mark-up from what DataTables has 10059 * traditionally used). 10060 * @type boolean 10061 * @default false 10062 * 10063 * @dtopt Features 10064 * @name DataTable.defaults.jQueryUI 10065 * 10066 * @example 10067 * $(document).ready( function() { 10068 * $('#example').dataTable( { 10069 * "jQueryUI": true 10070 * } ); 10071 * } ); 10072 */ 10073 "bJQueryUI": fals
vendor: 18,080 bytes, lines 10073-10635
10073e, 10074 10075 10076 /** 10077 * Allows the end user to select the size of a formatted page from a select 10078 * menu (sizes are 10, 25, 50 and 100). Requires pagination (`paginate`). 10079 * @type boolean 10080 * @default true 10081 * 10082 * @dtopt Features 10083 * @name DataTable.defaults.lengthChange 10084 * 10085 * @example 10086 * $(document).ready( function () { 10087 * $('#example').dataTable( { 10088 * "lengthChange": false 10089 * } ); 10090 * } ); 10091 */ 10092 "bLengthChange": true, 10093 10094 10095 /** 10096 * Enable or disable pagination. 10097 * @type boolean 10098 * @default true 10099 * 10100 * @dtopt Features 10101 * @name DataTable.defaults.paging 10102 * 10103 * @example 10104 * $(document).ready( function () { 10105 * $('#example').dataTable( { 10106 * "paging": false 10107 * } ); 10108 * } ); 10109 */ 10110 "bPaginate": true, 10111 10112 10113 /** 10114 * Enable or disable the display of a 'processing' indicator when the table is 10115 * being processed (e.g. a sort). This is particularly useful for tables with 10116 * large amounts of data where it can take a noticeable amount of time to sort 10117 * the entries. 10118 * @type boolean 10119 * @default false 10120 * 10121 * @dtopt Features 10122 * @name DataTable.defaults.processing 10123 * 10124 * @example 10125 * $(document).ready( function () { 10126 * $('#example').dataTable( { 10127 * "processing": true 10128 * } ); 10129 * } ); 10130 */ 10131 "bProcessing": false, 10132 10133 10134 /** 10135 * Retrieve the DataTables object for the given selector. Note that if the 10136 * table has already been initialised, this parameter will cause DataTables 10137 * to simply return the object that has already been set up - it will not take 10138 * account of any changes you might have made to the initialisation object 10139 * passed to DataTables (setting this parameter to true is an acknowledgement 10140 * that you understand this). `destroy` can be used to reinitialise a table if 10141 * you need. 10142 * @type boolean 10143 * @default false 10144 * 10145 * @dtopt Options 10146 * @name DataTable.defaults.retrieve 10147 * 10148 * @example 10149 * $(document).ready( function() { 10150 * initTable(); 10151 * tableActions(); 10152 * } ); 10153 * 10154 * function initTable () 10155 * { 10156 * return $('#example').dataTable( { 10157 * "scrollY": "200px", 10158 * "paginate": false, 10159 * "retrieve": true 10160 * } ); 10161 * } 10162 * 10163 * function tableActions () 10164 * { 10165 * var table = initTable(); 10166 * // perform API operations with oTable 10167 * } 10168 */ 10169 "bRetrieve": false, 10170 10171 10172 /** 10173 * When vertical (y) scrolling is enabled, DataTables will force the height of 10174 * the table's viewport to the given height at all times (useful for layout). 10175 * However, this can look odd when filtering data down to a small data set, 10176 * and the footer is left "floating" further down. This parameter (when 10177 * enabled) will cause DataTables to collapse the table's viewport down when 10178 * the result set will fit within the given Y height. 10179 * @type boolean 10180 * @default false 10181 * 10182 * @dtopt Options 10183 * @name DataTable.defaults.scrollCollapse 10184 * 10185 * @example 10186 * $(document).ready( function() { 10187 * $('#example').dataTable( { 10188 * "scrollY": "200", 10189 * "scrollCollapse": true 10190 * } ); 10191 * } ); 10192 */ 10193 "bScrollCollapse": false, 10194 10195 10196 /** 10197 * Configure DataTables to use server-side processing. Note that the 10198 * `ajax` parameter must also be given in order to give DataTables a 10199 * source to obtain the required data for each draw. 10200 * @type boolean 10201 * @default false 10202 * 10203 * @dtopt Features 10204 * @dtopt Server-side 10205 * @name DataTable.defaults.serverSide 10206 * 10207 * @example 10208 * $(document).ready( function () { 10209 * $('#example').dataTable( { 10210 * "serverSide": true, 10211 * "ajax": "xhr.php" 10212 * } ); 10213 * } ); 10214 */ 10215 "bServerSide": false, 10216 10217 10218 /** 10219 * Enable or disable sorting of columns. Sorting of individual columns can be 10220 * disabled by the `sortable` option for each column. 10221 * @type boolean 10222 * @default true 10223 * 10224 * @dtopt Features 10225 * @name DataTable.defaults.ordering 10226 * 10227 * @example 10228 * $(document).ready( function () { 10229 * $('#example').dataTable( { 10230 * "ordering": false 10231 * } ); 10232 * } ); 10233 */ 10234 "bSort": true, 10235 10236 10237 /** 10238 * Enable or display DataTables' ability to sort multiple columns at the 10239 * same time (activated by shift-click by the user). 10240 * @type boolean 10241 * @default true 10242 * 10243 * @dtopt Options 10244 * @name DataTable.defaults.orderMulti 10245 * 10246 * @example 10247 * // Disable multiple column sorting ability 10248 * $(document).ready( function () { 10249 * $('#example').dataTable( { 10250 * "orderMulti": false 10251 * } ); 10252 * } ); 10253 */ 10254 "bSortMulti": true, 10255 10256 10257 /** 10258 * Allows control over whether DataTables should use the top (true) unique 10259 * cell that is found for a single column, or the bottom (false - default). 10260 * This is useful when using complex headers. 10261 * @type boolean 10262 * @default false 10263 * 10264 * @dtopt Options 10265 * @name DataTable.defaults.orderCellsTop 10266 * 10267 * @example 10268 * $(document).ready( function() { 10269 * $('#example').dataTable( { 10270 * "orderCellsTop": true 10271 * } ); 10272 * } ); 10273 */ 10274 "bSortCellsTop": false, 10275 10276 10277 /** 10278 * Enable or disable the addition of the classes `sorting\_1`, `sorting\_2` and 10279 * `sorting\_3` to the columns which are currently being sorted on. This is 10280 * presented as a feature switch as it can increase processing time (while 10281 * classes are removed and added) so for large data sets you might want to 10282 * turn this off. 10283 * @type boolean 10284 * @default true 10285 * 10286 * @dtopt Features 10287 * @name DataTable.defaults.orderClasses 10288 * 10289 * @example 10290 * $(document).ready( function () { 10291 * $('#example').dataTable( { 10292 * "orderClasses": false 10293 * } ); 10294 * } ); 10295 */ 10296 "bSortClasses": true, 10297 10298 10299 /** 10300 * Enable or disable state saving. When enabled HTML5 `localStorage` will be 10301 * used to save table display information such as pagination information, 10302 * display length, filtering and sorting. As such when the end user reloads 10303 * the page the display display will match what thy had previously set up. 10304 * 10305 * Due to the use of `localStorage` the default state saving is not supported 10306 * in IE6 or 7. If state saving is required in those browsers, use 10307 * `stateSaveCallback` to provide a storage solution such as cookies. 10308 * @type boolean 10309 * @default false 10310 * 10311 * @dtopt Features 10312 * @name DataTable.defaults.stateSave 10313 * 10314 * @example 10315 * $(document).ready( function () { 10316 * $('#example').dataTable( { 10317 * "stateSave": true 10318 * } ); 10319 * } ); 10320 */ 10321 "bStateSave": false, 10322 10323 10324 /** 10325 * This function is called when a TR element is created (and all TD child 10326 * elements have been inserted), or registered if using a DOM source, allowing 10327 * manipulation of the TR element (adding classes etc). 10328 * @type function 10329 * @param {node} row "TR" element for the current row 10330 * @param {array} data Raw data array for this row 10331 * @param {int} dataIndex The index of this row in the internal aoData array 10332 * 10333 * @dtopt Callbacks 10334 * @name DataTable.defaults.createdRow 10335 * 10336 * @example 10337 * $(document).ready( function() { 10338 * $('#example').dataTable( { 10339 * "createdRow": function( row, data, dataIndex ) { 10340 * // Bold the grade for all 'A' grade browsers 10341 * if ( data[4] == "A" ) 10342 * { 10343 * $('td:eq(4)', row).html( '<b>A</b>' ); 10344 * } 10345 * } 10346 * } ); 10347 * } ); 10348 */ 10349 "fnCreatedRow": null, 10350 10351 10352 /** 10353 * This function is called on every 'draw' event, and allows you to 10354 * dynamically modify any aspect you want about the created DOM. 10355 * @type function 10356 * @param {object} settings DataTables settings object 10357 * 10358 * @dtopt Callbacks 10359 * @name DataTable.defaults.drawCallback 10360 * 10361 * @example 10362 * $(document).ready( function() { 10363 * $('#example').dataTable( { 10364 * "drawCallback": function( settings ) { 10365 * alert( 'DataTables has redrawn the table' ); 10366 * } 10367 * } ); 10368 * } ); 10369 */ 10370 "fnDrawCallback": null, 10371 10372 10373 /** 10374 * Identical to fnHeaderCallback() but for the table footer this function 10375 * allows you to modify the table footer on every 'draw' event. 10376 * @type function 10377 * @param {node} foot "TR" element for the footer 10378 * @param {array} data Full table data (as derived from the original HTML) 10379 * @param {int} start Index for the current display starting point in the 10380 * display array 10381 * @param {int} end Index for the current display ending point in the 10382 * display array 10383 * @param {array int} display Index array to translate the visual position 10384 * to the full data array 10385 * 10386 * @dtopt Callbacks 10387 * @name DataTable.defaults.footerCallback 10388 * 10389 * @example 10390 * $(document).ready( function() { 10391 * $('#example').dataTable( { 10392 * "footerCallback": function( tfoot, data, start, end, display ) { 10393 * tfoot.getElementsByTagName('th')[0].innerHTML = "Starting index is "+start; 10394 * } 10395 * } ); 10396 * } ) 10397 */ 10398 "fnFooterCallback": null, 10399 10400 10401 /** 10402 * When rendering large numbers in the information element for the table 10403 * (i.e. "Showing 1 to 10 of 57 entries") DataTables will render large numbers 10404 * to have a comma separator for the 'thousands' units (e.g. 1 million is 10405 * rendered as "1,000,000") to help readability for the end user. This 10406 * function will override the default method DataTables uses. 10407 * @type function 10408 * @member 10409 * @param {int} toFormat number to be formatted 10410 * @returns {string} formatted string for DataTables to show the number 10411 * 10412 * @dtopt Callbacks 10413 * @name DataTable.defaults.formatNumber 10414 * 10415 * @example 10416 * // Format a number using a single quote for the separator (note that 10417 * // this can also be done with the language.thousands option) 10418 * $(document).ready( function() { 10419 * $('#example').dataTable( { 10420 * "formatNumber": function ( toFormat ) { 10421 * return toFormat.toString().replace( 10422 * /\B(?=(\d{3})+(?!\d))/g, "'" 10423 * ); 10424 * }; 10425 * } ); 10426 * } ); 10427 */ 10428 "fnFormatNumber": function ( toFormat ) { 10429 return toFormat.toString().replace( 10430 /\B(?=(\d{3})+(?!\d))/g, 10431 this.oLanguage.sThousands 10432 ); 10433 }, 10434 10435 10436 /** 10437 * This function is called on every 'draw' event, and allows you to 10438 * dynamically modify the header row. This can be used to calculate and 10439 * display useful information about the table. 10440 * @type function 10441 * @param {node} head "TR" element for the header 10442 * @param {array} data Full table data (as derived from the original HTML) 10443 * @param {int} start Index for the current display starting point in the 10444 * display array 10445 * @param {int} end Index for the current display ending point in the 10446 * display array 10447 * @param {array int} display Index array to translate the visual position 10448 * to the full data array 10449 * 10450 * @dtopt Callbacks 10451 * @name DataTable.defaults.headerCallback 10452 * 10453 * @example 10454 * $(document).ready( function() { 10455 * $('#example').dataTable( { 10456 * "fheaderCallback": function( head, data, start, end, display ) { 10457 * head.getElementsByTagName('th')[0].innerHTML = "Displaying "+(end-start)+" records"; 10458 * } 10459 * } ); 10460 * } ) 10461 */ 10462 "fnHeaderCallback": null, 10463 10464 10465 /** 10466 * The information element can be used to convey information about the current 10467 * state of the table. Although the internationalisation options presented by 10468 * DataTables are quite capable of dealing with most customisations, there may 10469 * be times where you wish to customise the string further. This callback 10470 * allows you to do exactly that. 10471 * @type function 10472 * @param {object} oSettings DataTables settings object 10473 * @param {int} start Starting position in data for the draw 10474 * @param {int} end End position in data for the draw 10475 * @param {int} max Total number of rows in the table (regardless of 10476 * filtering) 10477 * @param {int} total Total number of rows in the data set, after filtering 10478 * @param {string} pre The string that DataTables has formatted using it's 10479 * own rules 10480 * @returns {string} The string to be displayed in the information element. 10481 * 10482 * @dtopt Callbacks 10483 * @name DataTable.defaults.infoCallback 10484 * 10485 * @example 10486 * $('#example').dataTable( { 10487 * "infoCallback": function( settings, start, end, max, total, pre ) { 10488 * return start +" to "+ end; 10489 * } 10490 * } ); 10491 */ 10492 "fnInfoCallback": null, 10493 10494 10495 /** 10496 * Called when the table has been initialised. Normally DataTables will 10497 * initialise sequentially and there will be no need for this function, 10498 * however, this does not hold true when using external language information 10499 * since that is obtained using an async XHR call. 10500 * @type function 10501 * @param {object} settings DataTables settings object 10502 * @param {object} json The JSON object request from the server - only 10503 * present if client-side Ajax sourced data is used 10504 * 10505 * @dtopt Callbacks 10506 * @name DataTable.defaults.initComplete 10507 * 10508 * @example 10509 * $(document).ready( function() { 10510 * $('#example').dataTable( { 10511 * "initComplete": function(settings, json) { 10512 * alert( 'DataTables has finished its initialisation.' ); 10513 * } 10514 * } ); 10515 * } ) 10516 */ 10517 "fnInitComplete": null, 10518 10519 10520 /** 10521 * Called at the very start of each table draw and can be used to cancel the 10522 * draw by returning false, any other return (including undefined) results in 10523 * the full draw occurring). 10524 * @type function 10525 * @param {object} settings DataTables settings object 10526 * @returns {boolean} False will cancel the draw, anything else (including no 10527 * return) will allow it to complete. 10528 * 10529 * @dtopt Callbacks 10530 * @name DataTable.defaults.preDrawCallback 10531 * 10532 * @example 10533 * $(document).ready( function() { 10534 * $('#example').dataTable( { 10535 * "preDrawCallback": function( settings ) { 10536 * if ( $('#test').val() == 1 ) { 10537 * return false; 10538 * } 10539 * } 10540 * } ); 10541 * } ); 10542 */ 10543 "fnPreDrawCallback": null, 10544 10545 10546 /** 10547 * This function allows you to 'post process' each row after it have been 10548 * generated for each table draw, but before it is rendered on screen. This 10549 * function might be used for setting the row class name etc. 10550 * @type function 10551 * @param {node} row "TR" element for the current row 10552 * @param {array} data Raw data array for this row 10553 * @param {int} displayIndex The display index for the current table draw 10554 * @param {int} displayIndexFull The index of the data in the full list of 10555 * rows (after filtering) 10556 * 10557 * @dtopt Callbacks 10558 * @name DataTable.defaults.rowCallback 10559 * 10560 * @example 10561 * $(document).ready( function() { 10562 * $('#example').dataTable( { 10563 * "rowCallback": function( row, data, displayIndex, displayIndexFull ) { 10564 * // Bold the grade for all 'A' grade browsers 10565 * if ( data[4] == "A" ) { 10566 * $('td:eq(4)', row).html( '<b>A</b>' ); 10567 * } 10568 * } 10569 * } ); 10570 * } ); 10571 */ 10572 "fnRowCallback": null, 10573 10574 10575 /** 10576 * __Deprecated__ The functionality provided by this parameter has now been 10577 * superseded by that provided through `ajax`, which should be used instead. 10578 * 10579 * This parameter allows you to override the default function which obtains 10580 * the data from the server so something more suitable for your application. 10581 * For example you could use POST data, or pull information from a Gears or 10582 * AIR database. 10583 * @type function 10584 * @member 10585 * @param {string} source HTTP source to obtain the data from (`ajax`) 10586 * @param {array} data A key/value pair object containing the data to send 10587 * to the server 10588 * @param {function} callback to be called on completion of the data get 10589 * process that will draw the data on the page. 10590 * @param {object} settings DataTables settings object 10591 * 10592 * @dtopt Callbacks 10593 * @dtopt Server-side 10594 * @name DataTable.defaults.serverData 10595 * 10596 * @deprecated 1.10. Please use `ajax` for this functionality now. 10597 */ 10598 "fnServerData": null, 10599 10600 10601 /** 10602 * __Deprecated__ The functionality provided by this parameter has now been 10603 * superseded by that provided through `ajax`, which should be used instead. 10604 * 10605 * It is often useful to send extra data to the server when making an Ajax 10606 * request - for example custom filtering information, and this callback 10607 * function makes it trivial to send extra information to the server. The 10608 * passed in parameter is the data set that has been constructed by 10609 * DataTables, and you can add to this or modify it as you require. 10610 * @type function 10611 * @param {array} data Data array (array of objects which are name/value 10612 * pairs) that has been constructed by DataTables and will be sent to the 10613 * server. In the case of Ajax sourced data with server-side processing 10614 * this will be an empty array, for server-side processing there will be a 10615 * significant number of parameters! 10616 * @returns {undefined} Ensure that you modify the data array passed in, 10617 * as this is passed by reference. 10618 * 10619 * @dtopt Callbacks 10620 * @dtopt Server-side 10621 * @name DataTable.defaults.serverParams 10622 * 10623 * @deprecated 1.10. Please use `ajax` for this functionality now. 10624 */ 10625 "fnServerParams": null, 10626 10627 10628 /** 10629 * Load the table state. With this function you can define from where, and how, the 10630 * state of a table is loaded. By default DataTables will load from `localStorage` 10631 * but you might wish to use a server-side database or cookies. 10632 * @type function 10633 * @member 10634 * @param {object} settings DataTables settings object 10635 * @
10635return {object} The DataTables state object to be loaded 10636 * 10637 * @dtopt Callbacks 10638 * @name DataTable.defaults.stateLoadCallback 10639 * 10640 * @example 10641 * $(document).ready( function() { 10642 * $('#example').dataTable( { 10643 * "stateSave": true, 10644 * "stateLoadCallback": function (settings) { 10645 * var o; 10646 * 10647 * // Send an Ajax request to the server to get the data. Note that 10648 * // this is a synchronous request. 10649 * $.ajax( { 10650 * "url": "/state_load", 10651 * "async": false, 10652 * "dataType": "json", 10653 * "success": function (json) { 10654 * o = json; 10655 * } 10656 * } ); 10657 * 10658 * return o; 10659 * } 10660 * } ); 10661 * } ); 10662 */ 10663 "fnStateLoadCallback": function ( settings ) { 10664 try { 10665 return JSON.parse( 10666 (settings.iStateDuration === -1 ? sessionStorage : localStorage).getItem( 10667 'DataTables_'+settings.sInstance+'_'+location.pathname 10668 ) 10669 ); 10670 } catch (e) {
vendor: 21,139 bytes, lines 10670-11347
10670} 10671 }, 10672 10673 10674 /** 10675 * Callback which allows modification of the saved state prior to loading that state. 10676 * This callback is called when the table is loading state from the stored data, but 10677 * prior to the settings object being modified by the saved state. Note that for 10678 * plug-in authors, you should use the `stateLoadParams` event to load parameters for 10679 * a plug-in. 10680 * @type function 10681 * @param {object} settings DataTables settings object 10682 * @param {object} data The state object that is to be loaded 10683 * 10684 * @dtopt Callbacks 10685 * @name DataTable.defaults.stateLoadParams 10686 * 10687 * @example 10688 * // Remove a saved filter, so filtering is never loaded 10689 * $(document).ready( function() { 10690 * $('#example').dataTable( { 10691 * "stateSave": true, 10692 * "stateLoadParams": function (settings, data) { 10693 * data.oSearch.sSearch = ""; 10694 * } 10695 * } ); 10696 * } ); 10697 * 10698 * @example 10699 * // Disallow state loading by returning false 10700 * $(document).ready( function() { 10701 * $('#example').dataTable( { 10702 * "stateSave": true, 10703 * "stateLoadParams": function (settings, data) { 10704 * return false; 10705 * } 10706 * } ); 10707 * } ); 10708 */ 10709 "fnStateLoadParams": null, 10710 10711 10712 /** 10713 * Callback that is called when the state has been loaded from the state saving method 10714 * and the DataTables settings object has been modified as a result of the loaded state. 10715 * @type function 10716 * @param {object} settings DataTables settings object 10717 * @param {object} data The state object that was loaded 10718 * 10719 * @dtopt Callbacks 10720 * @name DataTable.defaults.stateLoaded 10721 * 10722 * @example 10723 * // Show an alert with the filtering value that was saved 10724 * $(document).ready( function() { 10725 * $('#example').dataTable( { 10726 * "stateSave": true, 10727 * "stateLoaded": function (settings, data) { 10728 * alert( 'Saved filter was: '+data.oSearch.sSearch ); 10729 * } 10730 * } ); 10731 * } ); 10732 */ 10733 "fnStateLoaded": null, 10734 10735 10736 /** 10737 * Save the table state. This function allows you to define where and how the state 10738 * information for the table is stored By default DataTables will use `localStorage` 10739 * but you might wish to use a server-side database or cookies. 10740 * @type function 10741 * @member 10742 * @param {object} settings DataTables settings object 10743 * @param {object} data The state object to be saved 10744 * 10745 * @dtopt Callbacks 10746 * @name DataTable.defaults.stateSaveCallback 10747 * 10748 * @example 10749 * $(document).ready( function() { 10750 * $('#example').dataTable( { 10751 * "stateSave": true, 10752 * "stateSaveCallback": function (settings, data) { 10753 * // Send an Ajax request to the server with the state object 10754 * $.ajax( { 10755 * "url": "/state_save", 10756 * "data": data, 10757 * "dataType": "json", 10758 * "method": "POST" 10759 * "success": function () {} 10760 * } ); 10761 * } 10762 * } ); 10763 * } ); 10764 */ 10765 "fnStateSaveCallback": function ( settings, data ) { 10766 try { 10767 (settings.iStateDuration === -1 ? sessionStorage : localStorage).setItem( 10768 'DataTables_'+settings.sInstance+'_'+location.pathname, 10769 JSON.stringify( data ) 10770 ); 10771 } catch (e) {} 10772 }, 10773 10774 10775 /** 10776 * Callback which allows modification of the state to be saved. Called when the table 10777 * has changed state a new state save is required. This method allows modification of 10778 * the state saving object prior to actually doing the save, including addition or 10779 * other state properties or modification. Note that for plug-in authors, you should 10780 * use the `stateSaveParams` event to save parameters for a plug-in. 10781 * @type function 10782 * @param {object} settings DataTables settings object 10783 * @param {object} data The state object to be saved 10784 * 10785 * @dtopt Callbacks 10786 * @name DataTable.defaults.stateSaveParams 10787 * 10788 * @example 10789 * // Remove a saved filter, so filtering is never saved 10790 * $(document).ready( function() { 10791 * $('#example').dataTable( { 10792 * "stateSave": true, 10793 * "stateSaveParams": function (settings, data) { 10794 * data.oSearch.sSearch = ""; 10795 * } 10796 * } ); 10797 * } ); 10798 */ 10799 "fnStateSaveParams": null, 10800 10801 10802 /** 10803 * Duration for which the saved state information is considered valid. After this period 10804 * has elapsed the state will be returned to the default. 10805 * Value is given in seconds. 10806 * @type int 10807 * @default 7200 <i>(2 hours)</i> 10808 * 10809 * @dtopt Options 10810 * @name DataTable.defaults.stateDuration 10811 * 10812 * @example 10813 * $(document).ready( function() { 10814 * $('#example').dataTable( { 10815 * "stateDuration": 60*60*24; // 1 day 10816 * } ); 10817 * } ) 10818 */ 10819 "iStateDuration": 7200, 10820 10821 10822 /** 10823 * When enabled DataTables will not make a request to the server for the first 10824 * page draw - rather it will use the data already on the page (no sorting etc 10825 * will be applied to it), thus saving on an XHR at load time. `deferLoading` 10826 * is used to indicate that deferred loading is required, but it is also used 10827 * to tell DataTables how many records there are in the full table (allowing 10828 * the information element and pagination to be displayed correctly). In the case 10829 * where a filtering is applied to the table on initial load, this can be 10830 * indicated by giving the parameter as an array, where the first element is 10831 * the number of records available after filtering and the second element is the 10832 * number of records without filtering (allowing the table information element 10833 * to be shown correctly). 10834 * @type int | array 10835 * @default null 10836 * 10837 * @dtopt Options 10838 * @name DataTable.defaults.deferLoading 10839 * 10840 * @example 10841 * // 57 records available in the table, no filtering applied 10842 * $(document).ready( function() { 10843 * $('#example').dataTable( { 10844 * "serverSide": true, 10845 * "ajax": "scripts/server_processing.php", 10846 * "deferLoading": 57 10847 * } ); 10848 * } ); 10849 * 10850 * @example 10851 * // 57 records after filtering, 100 without filtering (an initial filter applied) 10852 * $(document).ready( function() { 10853 * $('#example').dataTable( { 10854 * "serverSide": true, 10855 * "ajax": "scripts/server_processing.php", 10856 * "deferLoading": [ 57, 100 ], 10857 * "search": { 10858 * "search": "my_filter" 10859 * } 10860 * } ); 10861 * } ); 10862 */ 10863 "iDeferLoading": null, 10864 10865 10866 /** 10867 * Number of rows to display on a single page when using pagination. If 10868 * feature enabled (`lengthChange`) then the end user will be able to override 10869 * this to a custom setting using a pop-up menu. 10870 * @type int 10871 * @default 10 10872 * 10873 * @dtopt Options 10874 * @name DataTable.defaults.pageLength 10875 * 10876 * @example 10877 * $(document).ready( function() { 10878 * $('#example').dataTable( { 10879 * "pageLength": 50 10880 * } ); 10881 * } ) 10882 */ 10883 "iDisplayLength": 10, 10884 10885 10886 /** 10887 * Define the starting point for data display when using DataTables with 10888 * pagination. Note that this parameter is the number of records, rather than 10889 * the page number, so if you have 10 records per page and want to start on 10890 * the third page, it should be "20". 10891 * @type int 10892 * @default 0 10893 * 10894 * @dtopt Options 10895 * @name DataTable.defaults.displayStart 10896 * 10897 * @example 10898 * $(document).ready( function() { 10899 * $('#example').dataTable( { 10900 * "displayStart": 20 10901 * } ); 10902 * } ) 10903 */ 10904 "iDisplayStart": 0, 10905 10906 10907 /** 10908 * By default DataTables allows keyboard navigation of the table (sorting, paging, 10909 * and filtering) by adding a `tabindex` attribute to the required elements. This 10910 * allows you to tab through the controls and press the enter key to activate them. 10911 * The tabindex is default 0, meaning that the tab follows the flow of the document. 10912 * You can overrule this using this parameter if you wish. Use a value of -1 to 10913 * disable built-in keyboard navigation. 10914 * @type int 10915 * @default 0 10916 * 10917 * @dtopt Options 10918 * @name DataTable.defaults.tabIndex 10919 * 10920 * @example 10921 * $(document).ready( function() { 10922 * $('#example').dataTable( { 10923 * "tabIndex": 1 10924 * } ); 10925 * } ); 10926 */ 10927 "iTabIndex": 0, 10928 10929 10930 /** 10931 * Classes that DataTables assigns to the various components and features 10932 * that it adds to the HTML table. This allows classes to be configured 10933 * during initialisation in addition to through the static 10934 * {@link DataTable.ext.oStdClasses} object). 10935 * @namespace 10936 * @name DataTable.defaults.classes 10937 */ 10938 "oClasses": {}, 10939 10940 10941 /** 10942 * All strings that DataTables uses in the user interface that it creates 10943 * are defined in this object, allowing you to modified them individually or 10944 * completely replace them all as required. 10945 * @namespace 10946 * @name DataTable.defaults.language 10947 */ 10948 "oLanguage": { 10949 /** 10950 * Strings that are used for WAI-ARIA labels and controls only (these are not 10951 * actually visible on the page, but will be read by screenreaders, and thus 10952 * must be internationalised as well). 10953 * @namespace 10954 * @name DataTable.defaults.language.aria 10955 */ 10956 "oAria": { 10957 /** 10958 * ARIA label that is added to the table headers when the column may be 10959 * sorted ascending by activing the column (click or return when focused). 10960 * Note that the column header is prefixed to this string. 10961 * @type string 10962 * @default : activate to sort column ascending 10963 * 10964 * @dtopt Language 10965 * @name DataTable.defaults.language.aria.sortAscending 10966 * 10967 * @example 10968 * $(document).ready( function() { 10969 * $('#example').dataTable( { 10970 * "language": { 10971 * "aria": { 10972 * "sortAscending": " - click/return to sort ascending" 10973 * } 10974 * } 10975 * } ); 10976 * } ); 10977 */ 10978 "sSortAscending": ": activate to sort column ascending", 10979 10980 /** 10981 * ARIA label that is added to the table headers when the column may be 10982 * sorted descending by activing the column (click or return when focused). 10983 * Note that the column header is prefixed to this string. 10984 * @type string 10985 * @default : activate to sort column ascending 10986 * 10987 * @dtopt Language 10988 * @name DataTable.defaults.language.aria.sortDescending 10989 * 10990 * @example 10991 * $(document).ready( function() { 10992 * $('#example').dataTable( { 10993 * "language": { 10994 * "aria": { 10995 * "sortDescending": " - click/return to sort descending" 10996 * } 10997 * } 10998 * } ); 10999 * } ); 11000 */ 11001 "sSortDescending": ": activate to sort column descending" 11002 }, 11003 11004 /** 11005 * Pagination string used by DataTables for the built-in pagination 11006 * control types. 11007 * @namespace 11008 * @name DataTable.defaults.language.paginate 11009 */ 11010 "oPaginate": { 11011 /** 11012 * Text to use when using the 'full_numbers' type of pagination for the 11013 * button to take the user to the first page. 11014 * @type string 11015 * @default First 11016 * 11017 * @dtopt Language 11018 * @name DataTable.defaults.language.paginate.first 11019 * 11020 * @example 11021 * $(document).ready( function() { 11022 * $('#example').dataTable( { 11023 * "language": { 11024 * "paginate": { 11025 * "first": "First page" 11026 * } 11027 * } 11028 * } ); 11029 * } ); 11030 */ 11031 "sFirst": "First", 11032 11033 11034 /** 11035 * Text to use when using the 'full_numbers' type of pagination for the 11036 * button to take the user to the last page. 11037 * @type string 11038 * @default Last 11039 * 11040 * @dtopt Language 11041 * @name DataTable.defaults.language.paginate.last 11042 * 11043 * @example 11044 * $(document).ready( function() { 11045 * $('#example').dataTable( { 11046 * "language": { 11047 * "paginate": { 11048 * "last": "Last page" 11049 * } 11050 * } 11051 * } ); 11052 * } ); 11053 */ 11054 "sLast": "Last", 11055 11056 11057 /** 11058 * Text to use for the 'next' pagination button (to take the user to the 11059 * next page). 11060 * @type string 11061 * @default Next 11062 * 11063 * @dtopt Language 11064 * @name DataTable.defaults.language.paginate.next 11065 * 11066 * @example 11067 * $(document).ready( function() { 11068 * $('#example').dataTable( { 11069 * "language": { 11070 * "paginate": { 11071 * "next": "Next page" 11072 * } 11073 * } 11074 * } ); 11075 * } ); 11076 */ 11077 "sNext": "Next", 11078 11079 11080 /** 11081 * Text to use for the 'previous' pagination button (to take the user to 11082 * the previous page). 11083 * @type string 11084 * @default Previous 11085 * 11086 * @dtopt Language 11087 * @name DataTable.defaults.language.paginate.previous 11088 * 11089 * @example 11090 * $(document).ready( function() { 11091 * $('#example').dataTable( { 11092 * "language": { 11093 * "paginate": { 11094 * "previous": "Previous page" 11095 * } 11096 * } 11097 * } ); 11098 * } ); 11099 */ 11100 "sPrevious": "Previous" 11101 }, 11102 11103 /** 11104 * This string is shown in preference to `zeroRecords` when the table is 11105 * empty of data (regardless of filtering). Note that this is an optional 11106 * parameter - if it is not given, the value of `zeroRecords` will be used 11107 * instead (either the default or given value). 11108 * @type string 11109 * @default No data available in table 11110 * 11111 * @dtopt Language 11112 * @name DataTable.defaults.language.emptyTable 11113 * 11114 * @example 11115 * $(document).ready( function() { 11116 * $('#example').dataTable( { 11117 * "language": { 11118 * "emptyTable": "No data available in table" 11119 * } 11120 * } ); 11121 * } ); 11122 */ 11123 "sEmptyTable": "No data available in table", 11124 11125 11126 /** 11127 * This string gives information to the end user about the information 11128 * that is current on display on the page. The following tokens can be 11129 * used in the string and will be dynamically replaced as the table 11130 * display updates. This tokens can be placed anywhere in the string, or 11131 * removed as needed by the language requires: 11132 * 11133 * * `\_START\_` - Display index of the first record on the current page 11134 * * `\_END\_` - Display index of the last record on the current page 11135 * * `\_TOTAL\_` - Number of records in the table after filtering 11136 * * `\_MAX\_` - Number of records in the table without filtering 11137 * * `\_PAGE\_` - Current page number 11138 * * `\_PAGES\_` - Total number of pages of data in the table 11139 * 11140 * @type string 11141 * @default Showing _START_ to _END_ of _TOTAL_ entries 11142 * 11143 * @dtopt Language 11144 * @name DataTable.defaults.language.info 11145 * 11146 * @example 11147 * $(document).ready( function() { 11148 * $('#example').dataTable( { 11149 * "language": { 11150 * "info": "Showing page _PAGE_ of _PAGES_" 11151 * } 11152 * } ); 11153 * } ); 11154 */ 11155 "sInfo": "Showing _START_ to _END_ of _TOTAL_ entries", 11156 11157 11158 /** 11159 * Display information string for when the table is empty. Typically the 11160 * format of this string should match `info`. 11161 * @type string 11162 * @default Showing 0 to 0 of 0 entries 11163 * 11164 * @dtopt Language 11165 * @name DataTable.defaults.language.infoEmpty 11166 * 11167 * @example 11168 * $(document).ready( function() { 11169 * $('#example').dataTable( { 11170 * "language": { 11171 * "infoEmpty": "No entries to show" 11172 * } 11173 * } ); 11174 * } ); 11175 */ 11176 "sInfoEmpty": "Showing 0 to 0 of 0 entries", 11177 11178 11179 /** 11180 * When a user filters the information in a table, this string is appended 11181 * to the information (`info`) to give an idea of how strong the filtering 11182 * is. The variable _MAX_ is dynamically updated. 11183 * @type string 11184 * @default (filtered from _MAX_ total entries) 11185 * 11186 * @dtopt Language 11187 * @name DataTable.defaults.language.infoFiltered 11188 * 11189 * @example 11190 * $(document).ready( function() { 11191 * $('#example').dataTable( { 11192 * "language": { 11193 * "infoFiltered": " - filtering from _MAX_ records" 11194 * } 11195 * } ); 11196 * } ); 11197 */ 11198 "sInfoFiltered": "(filtered from _MAX_ total entries)", 11199 11200 11201 /** 11202 * If can be useful to append extra information to the info string at times, 11203 * and this variable does exactly that. This information will be appended to 11204 * the `info` (`infoEmpty` and `infoFiltered` in whatever combination they are 11205 * being used) at all times. 11206 * @type string 11207 * @default <i>Empty string</i> 11208 * 11209 * @dtopt Language 11210 * @name DataTable.defaults.language.infoPostFix 11211 * 11212 * @example 11213 * $(document).ready( function() { 11214 * $('#example').dataTable( { 11215 * "language": { 11216 * "infoPostFix": "All records shown are derived from real information." 11217 * } 11218 * } ); 11219 * } ); 11220 */ 11221 "sInfoPostFix": "", 11222 11223 11224 /** 11225 * This decimal place operator is a little different from the other 11226 * language options since DataTables doesn't output floating point 11227 * numbers, so it won't ever use this for display of a number. Rather, 11228 * what this parameter does is modify the sort methods of the table so 11229 * that numbers which are in a format which has a character other than 11230 * a period (`.`) as a decimal place will be sorted numerically. 11231 * 11232 * Note that numbers with different decimal places cannot be shown in 11233 * the same table and still be sortable, the table must be consistent. 11234 * However, multiple different tables on the page can use different 11235 * decimal place characters. 11236 * @type string 11237 * @default 11238 * 11239 * @dtopt Language 11240 * @name DataTable.defaults.language.decimal 11241 * 11242 * @example 11243 * $(document).ready( function() { 11244 * $('#example').dataTable( { 11245 * "language": { 11246 * "decimal": "," 11247 * "thousands": "." 11248 * } 11249 * } ); 11250 * } ); 11251 */ 11252 "sDecimal": "", 11253 11254 11255 /** 11256 * DataTables has a build in number formatter (`formatNumber`) which is 11257 * used to format large numbers that are used in the table information. 11258 * By default a comma is used, but this can be trivially changed to any 11259 * character you wish with this parameter. 11260 * @type string 11261 * @default , 11262 * 11263 * @dtopt Language 11264 * @name DataTable.defaults.language.thousands 11265 * 11266 * @example 11267 * $(document).ready( function() { 11268 * $('#example').dataTable( { 11269 * "language": { 11270 * "thousands": "'" 11271 * } 11272 * } ); 11273 * } ); 11274 */ 11275 "sThousands": ",", 11276 11277 11278 /** 11279 * Detail the action that will be taken when the drop down menu for the 11280 * pagination length option is changed. The '_MENU_' variable is replaced 11281 * with a default select list of 10, 25, 50 and 100, and can be replaced 11282 * with a custom select box if required. 11283 * @type string 11284 * @default Show _MENU_ entries 11285 * 11286 * @dtopt Language 11287 * @name DataTable.defaults.language.lengthMenu 11288 * 11289 * @example 11290 * // Language change only 11291 * $(document).ready( function() { 11292 * $('#example').dataTable( { 11293 * "language": { 11294 * "lengthMenu": "Display _MENU_ records" 11295 * } 11296 * } ); 11297 * } ); 11298 * 11299 * @example 11300 * // Language and options change 11301 * $(document).ready( function() { 11302 * $('#example').dataTable( { 11303 * "language": { 11304 * "lengthMenu": 'Display <select>'+ 11305 * '<option value="10">10</option>'+ 11306 * '<option value="20">20</option>'+ 11307 * '<option value="30">30</option>'+ 11308 * '<option value="40">40</option>'+ 11309 * '<option value="50">50</option>'+ 11310 * '<option value="-1">All</option>'+ 11311 * '</select> records' 11312 * } 11313 * } ); 11314 * } ); 11315 */ 11316 "sLengthMenu": "Show _MENU_ entries", 11317 11318 11319 /** 11320 * When using Ajax sourced data and during the first draw when DataTables is 11321 * gathering the data, this message is shown in an empty row in the table to 11322 * indicate to the end user the the data is being loaded. Note that this 11323 * parameter is not used when loading data by server-side processing, just 11324 * Ajax sourced data with client-side processing. 11325 * @type string 11326 * @default Loading... 11327 * 11328 * @dtopt Language 11329 * @name DataTable.defaults.language.loadingRecords 11330 * 11331 * @example 11332 * $(document).ready( function() { 11333 * $('#example').dataTable( { 11334 * "language": { 11335 * "loadingRecords": "Please wait - loading..." 11336 * } 11337 * } ); 11338 * } ); 11339 */ 11340 "sLoadingRecords": "Loading...", 11341 11342 11343 /** 11344 * Text which is displayed when the table is processing a user action 11345 * (usually a sort command or similar). 11346 * @type string 11347 *
11347 @default Processing... 11348 * 11349 * @dtopt Language 11350 * @name DataTable.defaults.language.processing 11351 * 11352 * @example 11353 * $(document).ready( function() { 11354 * $('#example').dataTable( { 11355 * "language": { 11356 * "processing": "DataTables is currently busy" 11357 * } 11358 * } ); 11359 * } ); 11360 */ 11361 "sProcessing": "Processing...", 11362 11363 11364 /** 11365 * Details the actions that will be taken when the user types into the 11366 * filtering input text box. The variable "_INPUT_", if used in the string, 11367 * is replaced with the HTML text box for the filtering input allowing 11368 * control over where it appears in the string. If "_INPUT_" is not given 11369 * then the input box is appended to the string automatically. 11370 * @type string 11371 * @default Search: 11372 * 11373 * @dtopt Language 11374 * @name DataTable.defaults.language.search 11375 * 11376 * @example 11377 * // Input text box will be appended at the end automatically 11378 * $(document).ready( function() { 11379 * $('#example').dataTable( { 11380 * "language": { 11381 * "search": "Filter records:" 11382 * } 11383 * } ); 11384 * } ); 11385 * 11386 * @example 11387 * // Specify where the filter should appear 11388 * $(document).ready( function() { 11389 * $('#example').dataTable( { 11390 * "language": { 11391 * "search": "Apply filter _INPUT_ to table" 11392 * } 11393 * } ); 11394 * } ); 11395 */ 11396 "sSearch": "Search:", 11397 11398 11399 /** 11400 * Assign a `placeholder` attribute to the search `input` element 11401 * @type string 11402 * @default 11403 * 11404 * @dtopt Language 11405 * @name DataTable.defaults.language.searchPlaceholder 11406 */ 11407 "sSearchPlaceholder": "", 11408 11409 11410 /** 11411 * All of the language information can be stored in a file on the 11412 * server-side, which DataTables will look up if this parameter is passed. 11413 * It must store the URL of the language file, which is in a JSON format, 11414 * and the object has the same properties as the oLanguage object in the 11415 * initialiser object (i.e. the above parameters). Please refer to one of 11416 * the example language files to see how this works in action. 11417 * @type string 11418 * @default <i>Empty string - i.e. disabled</i> 11419 * 11420 * @dtopt Language 11421 * @name DataTable.defaults.language.url 11422 * 11423 * @example 11424 * $(document).ready( function() { 11425 * $('#example').dataTable( { 11426 * "language": { 11427 * "url": "http://www.sprymedia.co.uk/dataTables/lang.txt" 11428 * } 11429 * } ); 11430 * } ); 11431 */ 11432 "sUrl": "", 11433 11434 11435 /** 11436 * Text shown inside the table records when the is no information to be 11437 * displayed after filtering. `emptyTable` is shown when there is simply no 11438 * information in the table at all (regardless of filtering). 11439 * @type string 11440 * @default No matching records found 11441 * 11442 * @dtopt Language 11443 * @name DataTable.defaults.language.zeroRecords 11444 * 11445 * @example 11446 * $(document).ready( function() { 11447 * $('#example').dataTable( { 11448 * "language": { 11449 * "zeroRecords": "No records to display" 11450 * } 11451 * } ); 11452 * } ); 11453 */ 11454 "sZeroRecords": "No matching records found" 11455 }, 11456 11457 11458 /** 11459 * This parameter allows you to have define the global filtering state at 11460 * initialisation time. As an object the `search` parameter must be 11461 * defined, but all other parameters are optional. When `regex` is true, 11462 * the search string will be treated as a regular expression, when false 11463 * (default) it will be treated as a straight string. When `smart` 11464 * DataTables will use it's smart filtering methods (to word match at 11465 * any point in the data), when false this will not be done. 11466 * @namespace 11467 * @extends DataTable.models.oSearch 11468 * 11469 * @dtopt Options 11470 * @name DataTable.defaults.search 11471 * 11472 * @example 11473 * $(document).ready( function() { 11474 * $('#example').dataTable( { 11475 * "search": {"search": "Initial search"} 11476 * } ); 11477 * } ) 11478 */ 11479 "oSearch": $.extend( {}, DataTable.models.oSearch ), 11480 11481 11482 /** 11483 * __Deprecated__ The functionality provided by this parameter has now been 11484 * superseded by that provided through `ajax`, which should be used instead. 11485 * 11486 * By default DataTables will look for the property `data` (or `aaData` for 11487 * compatibility with DataTables 1.9-) when obtaining data from an Ajax 11488 * source or for server-side processing - this parameter allows that 11489 * property to be changed. You can use Javascript dotted object notation to 11490 * get a data source for multiple levels of nesting. 11491 * @type string 11492 * @default data 11493 * 11494 * @dtopt Options 11495 * @dtopt Server-side 11496 * @name DataTable.defaults.ajaxDataProp 11497 * 11498 * @deprecated 1.10. Please use `ajax` for this functionality now. 11499 */ 11500 "sAjaxDataProp": "data", 11501 11502 11503 /** 11504 * __Deprecated__ The functionality provided by this parameter has now been 11505 * superseded by that provided through `ajax`, which should be used instead. 11506 * 11507 * You can instruct DataTables to load data from an external 11508 * source using this parameter (use aData if you want to pass data in you 11509 * already have). Simply provide a url a JSON object can be obtained from. 11510 * @type string 11511 * @default null 11512 * 11513 * @dtopt Options 11514 * @dtopt Server-side 11515 * @name DataTable.defaults.ajaxSource 11516 * 11517 * @deprecated 1.10. Please use `ajax` for this functionality now. 11518 */ 11519 "sAjaxSource": null, 11520 11521 11522 /** 11523 * This initialisation variable allows you to specify exactly where in the 11524 * DOM you want DataTables to inject the various controls it adds to the page 11525 * (for example you might want the pagination controls at the top of the 11526 * table). DIV elements (with or without a custom class) can also be added to 11527 * aid styling. The follow syntax is used: 11528 * <ul> 11529 * <li>The following options are allowed: 11530 * <ul> 11531 * <li>'l' - Length changing</li> 11532 * <li>'f' - Filtering input</li> 11533 * <li>'t' - The table!</li> 11534 * <li>'i' - Information</li> 11535 * <li>'p' - Pagination</li> 11536 * <li>'r' - pRocessing</li> 11537 * </ul> 11538 * </li> 11539 * <li>The following constants are allowed: 11540 * <ul> 11541 * <li>'H' - jQueryUI theme "header" classes ('fg-toolbar ui-widget-header ui-corner-tl ui-corner-tr ui-helper-clearfix')</li> 11542 * <li>'F' - jQueryUI theme "footer" classes ('fg-toolbar ui-widget-header ui-corner-bl ui-corner-br ui-helper-clearfix')</li> 11543 * </ul> 11544 * </li> 11545 * <li>The following syntax is expected: 11546 * <ul> 11547 * <li>'<' and '>' - div elements</li> 11548 * <li>'<"class" and '>' - div with a class</li> 11549 * <li>'<"#id" and '>' - div with an ID</li> 11550 * </ul> 11551 * </li> 11552 * <li>Examples: 11553 * <ul> 11554 * <li>'<"wrapper"flipt>'</li> 11555 * <li>'<lf<t>ip>'</li> 11556 * </ul> 11557 * </li> 11558 * </ul> 11559 * @type string 11560 * @default lfrtip <i>(when `jQueryUI` is false)</i> <b>or</b> 11561 * <"H"lfr>t<"F"ip> <i>(when `jQueryUI` is true)</i> 11562 * 11563 * @dtopt Options 11564 * @name DataTable.defaults.dom 11565 * 11566 * @example 11567 * $(document).ready( function() { 11568 * $('#example').dataTable( { 11569 * "dom": '<"top"i>rt<"bottom"flp><"clear">' 11570 * } ); 11571 * } ); 11572 */ 11573 "sDom": "lfrtip", 11574 11575 11576 /** 11577 * Search delay option. This will throttle full table searches that use the 11578 * DataTables provided search input element (it does not effect calls to 11579 * `dt-api search()`, providing a delay before the search is made. 11580 * @type integer 11581 * @default 0 11582 * 11583 * @dtopt Options 11584 * @name DataTable.defaults.searchDelay 11585 * 11586 * @example 11587 * $(document).ready( function() { 11588 * $('#example').dataTable( { 11589 * "searchDelay": 200 11590 * } ); 11591 * } ) 11592 */ 11593 "searchDelay": null, 11594 11595 11596 /** 11597 * DataTables features four different built-in options for the buttons to 11598 * display for pagination control: 11599 * 11600 * * `simple` - 'Previous' and 'Next' buttons only 11601 * * 'simple_numbers` - 'Previous' and 'Next' buttons, plus page numbers 11602 * * `full` - 'First', 'Previous', 'Next' and 'Last' buttons 11603 * * `full_numbers` - 'First', 'Previous', 'Next' and 'Last' buttons, plus 11604 * page numbers 11605 * 11606 * Further methods can be added using {@link DataTable.ext.oPagination}. 11607 * @type string 11608 * @default simple_numbers 11609 * 11610 * @dtopt Options 11611 * @name DataTable.defaults.pagingType 11612 * 11613 * @example 11614 * $(document).ready( function() { 11615 * $('#example').dataTable( { 11616 * "pagingType": "full_numbers" 11617 * } ); 11618 * } ) 11619 */ 11620 "sPaginationType": "simple_numbers", 11621 11622 11623 /** 11624 * Enable horizontal scrolling. When a table is too wide to fit into a 11625 * certain layout, or you have a large number of columns in the table, you 11626 * can enable x-scrolling to show the table in a viewport, which can be 11627 * scrolled. This property can be `true` which will allow the table to 11628 * scroll horizontally when needed, or any CSS unit, or a number (in which 11629 * case it will be treated as a pixel measurement). Setting as simply `true` 11630 * is recommended.
11631 * @type boolean|string 11632 * @default <i>blank string - i.e. disabled</i> 11633 * 11634 * @dtopt Features 11635 * @name DataTable.defaults.scrollX 11636 * 11637 * @example 11638 * $(document).ready( function() { 11639 * $('#example').dataTable( { 11640 * "scrollX": true, 11641 * "scrollCollapse": true 11642 * } ); 11643 * } ); 11644 */ 11645 "sScrollX": "", 11646 11647 11648 /** 11649 * This property can be used to force a DataTable to use more width than it 11650 * might otherwise do when x-scrolling is enabled. For example if you have a 11651 * table which requires to be well spaced, this parameter is useful for 11652 * "over-sizing" the table, and thus forcing scrolling. This property can by 11653 * any CSS unit, or a number (in which case it will be treated as a pixel 11654 * measurement). 11655 * @type string 11656 * @default <i>blank string - i.e. disabled</i> 11657 * 11658 * @dtopt Options 11659 * @name DataTable.defaults.scrollXInner 11660 * 11661 * @example 11662 * $(document).ready( function() { 11663 * $('#example').dataTable( { 11664 * "scrollX": "100%", 11665 * "scrollXInner": "110%" 11666 * } ); 11667 * } ); 11668 */ 11669 "sScrollXInner": "", 11670 11671 11672 /** 11673 * Enable vertical scrolling. Vertical scrolling will constrain the DataTable 11674 * to the given height, and enable scrolling for any data which overflows the 11675 * current viewport. This can be used as an alternative to paging to display 11676 * a lot of data in a small area (although paging and scrolling can both be 11677 * enabled at the same time). This property can be any CSS unit, or a number 11678 * (in which case it will be treated as a pixel measurement). 11679 * @type string 11680 * @default <i>blank string - i.e. disabled</i> 11681 * 11682 * @dtopt Features 11683 * @name DataTable.defaults.scrollY 11684 * 11685 * @example 11686 * $(document).ready( function() { 11687 * $('#example').dataTable( { 11688 * "scrollY": "200px", 11689 * "paginate": false 11690 * } ); 11691 * } ); 11692 */ 11693 "sScrollY": "", 11694 11695 11696 /** 11697 * __Deprecated__ The functionality provided by this parameter has now been 11698 * superseded by that provided through `ajax`, which should be used instead. 11699 * 11700 * Set the HTTP method that is used to make the Ajax call for server-side 11701 * processing or Ajax sourced data. 11702 * @type string 11703 * @default GET 11704 * 11705 * @dtopt Options 11706 * @dtopt Server-side 11707 * @name DataTable.defaults.serverMethod 11708 * 11709 * @deprecated 1.10. Please use `ajax` for this functionality now. 11710 */ 11711 "sServerMethod": "GET", 11712 11713 11714 /** 11715 * DataTables makes use of renderers when displaying HTML elements for 11716 * a table. These renderers can be added or modified by plug-ins to 11717 * generate suitable mark-up for a site. For example the Bootstrap 11718 * integration plug-in for DataTables uses a paging button renderer to 11719 * display pagination buttons in the mark-up required by Bootstrap. 11720 * 11721 * For further information about the renderers available see 11722 * DataTable.ext.renderer 11723 * @type string|object 11724 * @default null 11725 * 11726 * @name DataTable.defaults.renderer 11727 * 11728 */ 11729 "renderer": null 11730 }; 11731 11732 _fnHungarianMap( DataTable.defaults ); 11733 11734 11735 11736 /* 11737 * Developer note - See note in model.defaults.js about the use of Hungarian 11738 * notation and camel case. 11739 */ 11740 11741 /** 11742 * Column options that can be given to DataTables at initialisation time. 11743 * @namespace 11744 */ 11745 DataTable.defaults.column = { 11746 /** 11747 * Define which column(s) an order will occur on for this column. This 11748 * allows a column's ordering to take multiple columns into account when 11749 * doing a sort or use the data from a different column. For example first 11750 * name / last name columns make sense to do a multi-column sort over the 11751 * two columns. 11752 * @type array|int 11753 * @default null <i>Takes the value of the column index automatically</i> 11754 * 11755 * @name DataTable.defaults.column.orderData 11756 * @dtopt Columns 11757 * 11758 * @example 11759 * // Using `columnDefs` 11760 * $(document).ready( function() { 11761 * $('#example').dataTable( { 11762 * "columnDefs": [ 11763 * { "orderData": [ 0, 1 ], "targets": [ 0 ] }, 11764 * { "orderData": [ 1, 0 ], "targets": [ 1 ] }, 11765 * { "orderData": 2, "targets": [ 2 ] } 11766 * ] 11767 * } ); 11768 * } ); 11769 * 11770 * @example 11771 * // Using `columns` 11772 * $(document).ready( function() { 11773 * $('#example').dataTable( { 11774 * "columns": [ 11775 * { "orderData": [ 0, 1 ] }, 11776 * { "orderData": [ 1, 0 ] }, 11777 * { "orderData": 2 }, 11778 * null, 11779 * null 11780 * ] 11781 * } ); 11782 * } ); 11783 */ 11784 "aDataSort": null, 11785 "iDataSort": -1, 11786 11787 11788 /** 11789 * You can control the default ordering direction, and even alter the 11790 * behaviour of the sort handler (i.e. only allow ascending ordering etc) 11791 * using this parameter. 11792 * @type array 11793 * @default [ 'asc', 'desc' ] 11794 * 11795 * @name DataTable.defaults.column.orderSequence 11796 * @dtopt Columns 11797 * 11798 * @example 11799 * // Using `columnDefs` 11800 * $(document).ready( function() { 11801 * $('#example').dataTable( { 11802 * "columnDefs": [ 11803 * { "orderSequence": [ "asc" ], "targets": [ 1 ] }, 11804 * { "orderSequence": [ "desc", "asc", "asc" ], "targets": [ 2 ] }, 11805 * { "orderSequence": [ "desc" ], "targets": [ 3 ] } 11806 * ] 11807 * } ); 11808 * } ); 11809 * 11810 * @example 11811 * // Using `columns` 11812 * $(document).ready( function() { 11813 * $('#example').dataTable( { 11814 * "columns": [ 11815 * null, 11816 * { "orderSequence": [ "asc" ] }, 11817 * { "orderSequence": [ "desc", "asc", "asc" ] }, 11818 * { "orderSequence": [ "desc" ] }, 11819 * null 11820 * ] 11821 * } ); 11822 * } ); 11823 */ 11824 "asSorting": [ 'asc', 'desc' ], 11825 11826 11827 /** 11828 * Enable or disable filtering on the data in this column. 11829 * @type boolean 11830 * @default true 11831 * 11832 * @name DataTable.defaults.column.searchable 11833 * @dtopt Columns 11834 * 11835 * @example 11836 * // Using `columnDefs` 11837 * $(document).ready( function() { 11838 * $('#example').dataTable( { 11839 * "columnDefs": [ 11840 * { "searchable": false, "targets": [ 0 ] } 11841 * ] } ); 11842 * } ); 11843 * 11844 * @example 11845 * // Using `columns` 11846 * $(document).ready( function() { 11847 * $('#example').dataTable( { 11848 * "columns": [ 11849 * { "searchable": false }, 11850 * null, 11851 * null, 11852 * null, 11853 * null 11854 * ] } ); 11855 * } ); 11856 */ 11857 "bSearchable": true, 11858 11859 11860 /** 11861 * Enable or disable ordering on this column. 11862 * @type boolean 11863 * @default true 11864 * 11865 * @name DataTable.defaults.column.orderable 11866 * @dtopt Columns 11867 * 11868 * @example 11869 * // Using `columnDefs` 11870 * $(document).ready( function() { 11871 * $('#example').dataTable( { 11872 * "columnDefs": [ 11873 * { "orderable": false, "targets": [ 0 ] } 11874 * ] } ); 11875 * } ); 11876 * 11877 * @example 11878 * // Using `columns` 11879 * $(document).ready( function() { 11880 * $('#example').dataTable( { 11881 * "columns": [ 11882 * { "orderable": false }, 11883 * null, 11884 * null, 11885 * null, 11886 * null 11887 * ] } ); 11888 * } ); 11889 */ 11890 "bSortable": true, 11891 11892 11893 /** 11894 * Enable or disable the display of this column. 11895 * @type boolean 11896 * @default true 11897 * 11898 * @name DataTable.defaults.column.visible 11899 * @dtopt Columns 11900 * 11901 * @example 11902 * // Using `columnDefs` 11903 * $(document).ready( function() { 11904 * $('#example').dataTable( { 11905 * "columnDefs": [ 11906 * { "visible": false, "targets": [ 0 ] } 11907 * ] } ); 11908 * } ); 11909 * 11910 * @example 11911 * // Using `columns` 11912 * $(document).ready( function() { 11913 * $('#example').dataTable( { 11914 * "columns": [ 11915 * { "visible": false }, 11916 * null, 11917 * null, 11918 * null, 11919 * null 11920 * ] } ); 11921 * } ); 11922 */ 11923 "bVisible": true, 11924 11925 11926 /** 11927 * Developer definable function that is called whenever a cell is created (Ajax source, 11928 * etc) or processed for input (DOM source). This can be used as a compliment to mRender 11929 * allowing you to modify the DOM element (add background colour for example) when the 11930 * element is available. 11931 * @type function 11932 * @param {element} td The TD node that has been created 11933 * @param {*} cellData The Data for the cell 11934 * @param {array|object} rowData The data for the whole row 11935 * @param {int} row The row index for the aoData data store 11936 * @param {int} col The column index for aoColumns 11937 * 11938 * @name DataTable.defaults.column.createdCell 11939 * @dtopt Columns 11940 * 11941 * @example 11942 * $(document).ready( function() { 11943 * $('#example').dataTable( { 11944 * "columnDefs": [ { 11945 * "targets": [3], 11946 * "createdCell": function (td, cellData, rowData, row, c
11946ol) { 11947 * if ( cellData == "1.7" ) { 11948 * $(td).css('color', 'blue') 11949 * } 11950 * } 11951 * } ] 11952 * }); 11953 * } ); 11954 */ 11955 "fnCreatedCell": null, 11956 11957 11958 /** 11959 * This parameter has been replaced by `data` in DataTables to ensure naming 11960 * consistency. `dataProp` can still be used, as there is backwards 11961 * compatibility in DataTables for this option, but it is strongly 11962 * recommended that you use `data` in preference to `dataProp`. 11963 * @name DataTable.defaults.column.dataProp 11964 */ 11965 11966 11967 /** 11968 * This property can be used to read data from any data source property, 11969 * including deeply nested objects / properties. `data` can be given in a 11970 * number of different ways which effect its behaviour: 11971 * 11972 * * `integer` - treated as an array index for the data source. This is the 11973 * default that DataTables uses (incrementally increased for each column). 11974 * * `string` - read an object property from the data source. There are 11975 * three 'special' options that can be used in the string to alter how 11976 * DataTables reads the data from the source object: 11977 * * `.` - Dotted Javascript notation. Just as you use a `.` in 11978 * Javascript to read from nested objects, so to can the options 11979 * specified in `data`. For example: `browser.version` or 11980 * `browser.name`. If your object parameter name contains a period, use 11981 * `\\` to escape it - i.e. `first\\.name`. 11982 * * `[]` - Array notation. DataTables can automatically combine data 11983 * from and array source, joining the data with the characters provided 11984 * between the two brackets. For example: `name[, ]` would provide a 11985 * comma-space separated list from the source array. If no characters 11986 * are provided between the brackets, the original array source is 11987 * returned. 11988 * * `()` - Function notation. Adding `()` to the end of a parameter will 11989 * execute a function of the name given. For example: `browser()` for a 11990 * simple function on the data source, `browser.version()` for a 11991 * function in a nested property or even `browser().version` to get an 11992 * object property if the function called returns an object. Note that 11993 * function notation is recommended for use in `render` rather than 11994 * `data` as it is much simpler to use as a renderer. 11995 * * `null` - use the original data source for the row rather than plucking 11996 * data directly from it. This action has effects on two other 11997 * initialisation options: 11998 * * `defaultContent` - When null is given as the `data` option and 11999 * `defaultContent` is specified for the column, the value defined by 12000 * `defaultContent` will be used for the cell. 12001 * * `render` - When null is used for the `data` option and the `render` 12002 * option is specified for the column, the whole data source for the 12003 * row is used for the renderer. 12004 * * `function` - the function given will be executed whenever DataTables 12005 * needs to set or get the data for a cell in the column. The function 12006 * takes three parameters: 12007 * * Parameters: 12008 * * `{array|object}` The data source for the row 12009 * * `{string}` The type call data requested - this will be 'set' when 12010 * setting data or 'filter', 'display', 'type', 'sort' or undefined 12011 * when gathering data. Note that when `undefined` is given for the 12012 * type DataTables expects to get the raw data for the object back< 12013 * * `{*}` Data to set when the second parameter is 'set'. 12014 * * Return: 12015 * * The return value from the function is not required when 'set' is 12016 * the type of call, but otherwise the return is what will be used 12017 * for the data requested. 12018 * 12019 * Note that `data` is a getter and setter option. If you just require 12020 * formatting of data for output, you will likely want to use `render` which 12021 * is simply a getter and thus simpler to use. 12022 * 12023 * Note that prior to DataTables 1.9.2 `data` was called `mDataProp`. The 12024 * name change reflects the flexibility of this property and is consistent 12025 * with the naming of mRender. If 'mDataProp' is given, then it will still 12026 * be used by DataTables, as it automatically maps the old name to the new 12027 * if required. 12028 * 12029 * @type string|int|function|null 12030 * @default null <i>Use automatically calculated column index</i> 12031 * 12032 * @name DataTable.defaults.column.data 12033 * @dtopt Columns 12034 * 12035 * @example 12036 * // Read table data from objects 12037 * // JSON structure for each row: 12038 * // { 12039 * // "engine": {value}, 12040 * // "browser": {value}, 12041 * // "platform": {value}, 12042 * // "version": {value}, 12043 * // "grade": {value} 12044 * // } 12045 * $(document).ready( function() { 12046 * $('#example').dataTable( { 12047 * "ajaxSource": "sources/objects.txt", 12048 * "columns": [ 12049 * { "data": "engine" }, 12050 * { "data": "browser" }, 12051 * { "data": "platform" }, 12052 * { "data": "version" }, 12053 * { "data": "grade" } 12054 * ] 12055 * } ); 12056 * } ); 12057 * 12058 * @example 12059 * // Read information from deeply nested objects 12060 * // JSON structure for each row: 12061 * // { 12062 * // "engine": {value}, 12063 * // "browser": {value}, 12064 * // "platform": { 12065 * // "inner": {value} 12066 * // }, 12067 * // "details": [ 12068 * // {value}, {value} 12069 * // ] 12070 * // } 12071 * $(document).ready( function() { 12072 * $('#example').dataTable( { 12073 * "ajaxSource": "sources/deep.txt", 12074 * "columns": [ 12075 * { "data": "engine" }, 12076 * { "data": "browser" }, 12077 * { "data": "platform.inner" }, 12078 * { "data": "platform.details.0" }, 12079 * { "data": "platform.details.1" } 12080 * ] 12081 * } ); 12082 * } ); 12083 * 12084 * @example 12085 * // Using `data` as a function to provide different information for 12086 * // sorting, filtering and display. In this case, currency (price) 12087 * $(document).ready( function() { 12088 * $('#example').dataTable( { 12089 * "columnDefs": [ { 12090 * "targets": [ 0 ], 12091 * "data": function ( source, type, val ) { 12092 * if (type === 'set') { 12093 * source.price = val; 12094 * // Store the computed dis
vendor: 18,284 bytes, lines 12094-12643
12094lay and filter values for efficiency 12095 * source.price_display = val=="" ? "" : "$"+numberFormat(val); 12096 * source.price_filter = val=="" ? "" : "$"+numberFormat(val)+" "+val; 12097 * return; 12098 * } 12099 * else if (type === 'display') { 12100 * return source.price_display; 12101 * } 12102 * else if (type === 'filter') { 12103 * return source.price_filter; 12104 * } 12105 * // 'sort', 'type' and undefined all just use the integer 12106 * return source.price; 12107 * } 12108 * } ] 12109 * } ); 12110 * } ); 12111 * 12112 * @example 12113 * // Using default content 12114 * $(document).ready( function() { 12115 * $('#example').dataTable( { 12116 * "columnDefs": [ { 12117 * "targets": [ 0 ], 12118 * "data": null, 12119 * "defaultContent": "Click to edit" 12120 * } ] 12121 * } ); 12122 * } ); 12123 * 12124 * @example 12125 * // Using array notation - outputting a list from an array 12126 * $(document).ready( function() { 12127 * $('#example').dataTable( { 12128 * "columnDefs": [ { 12129 * "targets": [ 0 ], 12130 * "data": "name[, ]" 12131 * } ] 12132 * } ); 12133 * } ); 12134 * 12135 */ 12136 "mData": null, 12137 12138 12139 /** 12140 * This property is the rendering partner to `data` and it is suggested that 12141 * when you want to manipulate data for display (including filtering, 12142 * sorting etc) without altering the underlying data for the table, use this 12143 * property. `render` can be considered to be the the read only companion to 12144 * `data` which is read / write (then as such more complex). Like `data` 12145 * this option can be given in a number of different ways to effect its 12146 * behaviour: 12147 * 12148 * * `integer` - treated as an array index for the data source. This is the 12149 * default that DataTables uses (incrementally increased for each column). 12150 * * `string` - read an object property from the data source. There are 12151 * three 'special' options that can be used in the string to alter how 12152 * DataTables reads the data from the source object: 12153 * * `.` - Dotted Javascript notation. Just as you use a `.` in 12154 * Javascript to read from nested objects, so to can the options 12155 * specified in `data`. For example: `browser.version` or 12156 * `browser.name`. If your object parameter name contains a period, use 12157 * `\\` to escape it - i.e. `first\\.name`. 12158 * * `[]` - Array notation. DataTables can automatically combine data 12159 * from and array source, joining the data with the characters provided 12160 * between the two brackets. For example: `name[, ]` would provide a 12161 * comma-space separated list from the source array. If no characters 12162 * are provided between the brackets, the original array source is 12163 * returned. 12164 * * `()` - Function notation. Adding `()` to the end of a parameter will 12165 * execute a function of the name given. For example: `browser()` for a 12166 * simple function on the data source, `browser.version()` for a 12167 * function in a nested property or even `browser().version` to get an 12168 * object property if the function called returns an object. 12169 * * `object` - use different data for the different data types requested by 12170 * DataTables ('filter', 'display', 'type' or 'sort'). The property names 12171 * of the object is the data type the property refers to and the value can 12172 * defined using an integer, string or function using the same rules as 12173 * `render` normally does. Note that an `_` option _must_ be specified. 12174 * This is the default value to use if you haven't specified a value for 12175 * the data type requested by DataTables. 12176 * * `function` - the function given will be executed whenever DataTables 12177 * needs to set or get the data for a cell in the column. The function 12178 * takes three parameters: 12179 * * Parameters: 12180 * * {array|object} The data source for the row (based on `data`) 12181 * * {string} The type call data requested - this will be 'filter', 12182 * 'display', 'type' or 'sort'. 12183 * * {array|object} The full data source for the row (not based on 12184 * `data`) 12185 * * Return: 12186 * * The return value from the function is what will be used for the 12187 * data requested. 12188 * 12189 * @type string|int|function|object|null 12190 * @default null Use the data source value. 12191 * 12192 * @name DataTable.defaults.column.render 12193 * @dtopt Columns 12194 * 12195 * @example 12196 * // Create a comma separated list from an array of objects 12197 * $(document).ready( function() { 12198 * $('#example').dataTable( { 12199 * "ajaxSource": "sources/deep.txt", 12200 * "columns": [ 12201 * { "data": "engine" }, 12202 * { "data": "browser" }, 12203 * { 12204 * "data": "platform", 12205 * "render": "[, ].name" 12206 * } 12207 * ] 12208 * } ); 12209 * } ); 12210 * 12211 * @example 12212 * // Execute a function to obtain data 12213 * $(document).ready( function() { 12214 * $('#example').dataTable( { 12215 * "columnDefs": [ { 12216 * "targets": [ 0 ], 12217 * "data": null, // Use the full data source object for the renderer's source 12218 * "render": "browserName()" 12219 * } ] 12220 * } ); 12221 * } ); 12222 * 12223 * @example 12224 * // As an object, extracting different data for the different types 12225 * // This would be used with a data source such as: 12226 * // { "phone": 5552368, "phone_filter": "5552368 555-2368", "phone_display": "555-2368" } 12227 * // Here the `phone` integer is used for sorting and type detection, while `phone_filter` 12228 * // (which has both forms) is used for filtering for if a user inputs either format, while 12229 * // the formatted phone number is the one that is shown in the table. 12230 * $(document).ready( function() { 12231 * $('#example').dataTable( { 12232 * "columnDefs": [ { 12233 * "targets": [ 0 ], 12234 * "data": null, // Use the full data source object for the renderer's source 12235 * "render": { 12236 * "_": "phone", 12237 * "filter": "phone_filter", 12238 * "display": "phone_display" 12239 * } 12240 * } ] 12241 * } ); 12242 * } ); 12243 * 12244 * @example 12245 * // Use as a function to create a link from the data source 12246 * $(document).ready( function() { 12247 * $('#example').dataTable( { 12248 * "columnDefs": [ { 12249 * "targets": [ 0 ], 12250 * "data": "download_link", 12251 * "render": function ( data, type, full ) { 12252 * return '<a href="'+data+'">Download</a>'; 12253 * } 12254 * } ] 12255 * } ); 12256 * } ); 12257 */ 12258 "mRender": null, 12259 12260 12261 /** 12262 * Change the cell type created for the column - either TD cells or TH cells. This 12263 * can be useful as TH cells have semantic meaning in the table body, allowing them 12264 * to act as a header for a row (you may wish to add scope='row' to the TH elements). 12265 * @type string 12266 * @default td 12267 * 12268 * @name DataTable.defaults.column.cellType 12269 * @dtopt Columns 12270 * 12271 * @example 12272 * // Make the first column use TH cells 12273 * $(document).ready( function() { 12274 * $('#example').dataTable( { 12275 * "columnDefs": [ { 12276 * "targets": [ 0 ], 12277 * "cellType": "th" 12278 * } ] 12279 * } ); 12280 * } ); 12281 */ 12282 "sCellType": "td", 12283 12284 12285 /** 12286 * Class to give to each cell in this column. 12287 * @type string 12288 * @default <i>Empty string</i> 12289 * 12290 * @name DataTable.defaults.column.class 12291 * @dtopt Columns 12292 * 12293 * @example 12294 * // Using `columnDefs` 12295 * $(document).ready( function() { 12296 * $('#example').dataTable( { 12297 * "columnDefs": [ 12298 * { "class": "my_class", "targets": [ 0 ] } 12299 * ] 12300 * } ); 12301 * } ); 12302 * 12303 * @example 12304 * // Using `columns` 12305 * $(document).ready( function() { 12306 * $('#example').dataTable( { 12307 * "columns": [ 12308 * { "class": "my_class" }, 12309 * null, 12310 * null, 12311 * null, 12312 * null 12313 * ] 12314 * } ); 12315 * } ); 12316 */ 12317 "sClass": "", 12318 12319 /** 12320 * When DataTables calculates the column widths to assign to each column, 12321 * it finds the longest string in each column and then constructs a 12322 * temporary table and reads the widths from that. The problem with this 12323 * is that "mmm" is much wider then "iiii", but the latter is a longer 12324 * string - thus the calculation can go wrong (doing it properly and putting 12325 * it into an DOM object and measuring that is horribly(!) slow). Thus as 12326 * a "work around" we provide this option. It will append its value to the 12327 * text that is found to be the longest string for the column - i.e. padding. 12328 * Generally you shouldn't need this! 12329 * @type string 12330 * @default <i>Empty string<i> 12331 * 12332 * @name DataTable.defaults.column.contentPadding 12333 * @dtopt Columns 12334 * 12335 * @example 12336 * // Using `columns` 12337 * $(document).ready( function() { 12338 * $('#example').dataTable( { 12339 * "columns": [ 12340 * null, 12341 * null, 12342 * null, 12343 * { 12344 * "contentPadding": "mmm" 12345 * } 12346 * ] 12347 * } ); 12348 * } ); 12349 */ 12350 "sContentPadding": "", 12351 12352 12353 /** 12354 * Allows a default value to be given for a column's data, and will be used 12355 * whenever a null data source is encountered (this can be because `data` 12356 * is set to null, or because the data source itself is null). 12357 * @type string 12358 * @default null 12359 * 12360 * @name DataTable.defaults.column.defaultContent 12361 * @dtopt Columns 12362 * 12363 * @example 12364 * // Using `columnDefs` 12365 * $(document).ready( function() { 12366 * $('#example').dataTable( { 12367 * "columnDefs": [ 12368 * { 12369 * "data": null, 12370 * "defaultContent": "Edit", 12371 * "targets": [ -1 ] 12372 * } 12373 * ] 12374 * } ); 12375 * } ); 12376 * 12377 * @example 12378 * // Using `columns` 12379 * $(document).ready( function() { 12380 * $('#example').dataTable( { 12381 * "columns": [ 12382 * null, 12383 * null, 12384 * null, 12385 * { 12386 * "data": null, 12387 * "defaultContent": "Edit" 12388 * } 12389 * ] 12390 * } ); 12391 * } ); 12392 */ 12393 "sDefaultContent": null, 12394 12395 12396 /** 12397 * This parameter is only used in DataTables' server-side processing. It can 12398 * be exceptionally useful to know what columns are being displayed on the 12399 * client side, and to map these to database fields. When defined, the names 12400 * also allow DataTables to reorder information from the server if it comes 12401 * back in an unexpected order (i.e. if you switch your columns around on the 12402 * client-side, your server-side code does not also need updating). 12403 * @type string 12404 * @default <i>Empty string</i> 12405 * 12406 * @name DataTable.defaults.column.name 12407 * @dtopt Columns 12408 * 12409 * @example 12410 * // Using `columnDefs` 12411 * $(document).ready( function() { 12412 * $('#example').dataTable( { 12413 * "columnDefs": [ 12414 * { "name": "engine", "targets": [ 0 ] }, 12415 * { "name": "browser", "targets": [ 1 ] }, 12416 * { "name": "platform", "targets": [ 2 ] }, 12417 * { "name": "version", "targets": [ 3 ] }, 12418 * { "name": "grade", "targets": [ 4 ] } 12419 * ] 12420 * } ); 12421 * } ); 12422 * 12423 * @example 12424 * // Using `columns` 12425 * $(document).ready( function() { 12426 * $('#example').dataTable( { 12427 * "columns": [ 12428 * { "name": "engine" }, 12429 * { "name": "browser" }, 12430 * { "name": "platform" }, 12431 * { "name": "version" }, 12432 * { "name": "grade" } 12433 * ] 12434 * } ); 12435 * } ); 12436 */ 12437 "sName": "", 12438 12439 12440 /** 12441 * Defines a data source type for the ordering which can be used to read 12442 * real-time information from the table (updating the internally cached 12443 * version) prior to ordering. This allows ordering to occur on user 12444 * editable elements such as form inputs. 12445 * @type string 12446 * @default std 12447 * 12448 * @name DataTable.defaults.column.orderDataType 12449 * @dtopt Columns 12450 * 12451 * @example 12452 * // Using `columnDefs` 12453 * $(document).ready( function() { 12454 * $('#example').dataTable( { 12455 * "columnDefs": [ 12456 * { "orderDataType": "dom-text", "targets": [ 2, 3 ] }, 12457 * { "type": "numeric", "targets": [ 3 ] }, 12458 * { "orderDataType": "dom-select", "targets": [ 4 ] }, 12459 * { "orderDataType": "dom-checkbox", "targets": [ 5 ] } 12460 * ] 12461 * } ); 12462 * } ); 12463 * 12464 * @example 12465 * // Using `columns` 12466 * $(document).ready( function() { 12467 * $('#example').dataTable( { 12468 * "columns": [ 12469 * null, 12470 * null, 12471 * { "orderDataType": "dom-text" }, 12472 * { "orderDataType": "dom-text", "type": "numeric" }, 12473 * { "orderDataType": "dom-select" }, 12474 * { "orderDataType": "dom-checkbox" } 12475 * ] 12476 * } ); 12477 * } ); 12478 */ 12479 "sSortDataType": "std", 12480 12481 12482 /** 12483 * The title of this column. 12484 * @type string 12485 * @default null <i>Derived from the 'TH' value for this column in the 12486 * original HTML table.</i> 12487 * 12488 * @name DataTable.defaults.column.title 12489 * @dtopt Columns 12490 * 12491 * @example 12492 * // Using `columnDefs` 12493 * $(document).ready( function() { 12494 * $('#example').dataTable( { 12495 * "columnDefs": [ 12496 * { "title": "My column title", "targets": [ 0 ] } 12497 * ] 12498 * } ); 12499 * } ); 12500 * 12501 * @example 12502 * // Using `columns` 12503 * $(document).ready( function() { 12504 * $('#example').dataTable( { 12505 * "columns": [ 12506 * { "title": "My column title" }, 12507 * null, 12508 * null, 12509 * null, 12510 * null 12511 * ] 12512 * } ); 12513 * } ); 12514 */ 12515 "sTitle": null, 12516 12517 12518 /** 12519 * The type allows you to specify how the data for this column will be 12520 * ordered. Four types (string, numeric, date and html (which will strip 12521 * HTML tags before ordering)) are currently available. Note that only date 12522 * formats understood by Javascript's Date() object will be accepted as type 12523 * date. For example: "Mar 26, 2008 5:03 PM". May take the values: 'string', 12524 * 'numeric', 'date' or 'html' (by default). Further types can be adding 12525 * through plug-ins. 12526 * @type string 12527 * @default null <i>Auto-detected from raw data</i> 12528 * 12529 * @name DataTable.defaults.column.type 12530 * @dtopt Columns 12531 * 12532 * @example 12533 * // Using `columnDefs` 12534 * $(document).ready( function() { 12535 * $('#example').dataTable( { 12536 * "columnDefs": [ 12537 * { "type": "html", "targets": [ 0 ] } 12538 * ] 12539 * } ); 12540 * } ); 12541 * 12542 * @example 12543 * // Using `columns` 12544 * $(document).ready( function() { 12545 * $('#example').dataTable( { 12546 * "columns": [ 12547 * { "type": "html" }, 12548 * null, 12549 * null, 12550 * null, 12551 * null 12552 * ] 12553 * } ); 12554 * } ); 12555 */ 12556 "sType": null, 12557 12558 12559 /** 12560 * Defining the width of the column, this parameter may take any CSS value 12561 * (3em, 20px etc). DataTables applies 'smart' widths to columns which have not 12562 * been given a specific width through this interface ensuring that the table 12563 * remains readable. 12564 * @type string 12565 * @default null <i>Automatic</i> 12566 * 12567 * @name DataTable.defaults.column.width 12568 * @dtopt Columns 12569 * 12570 * @example 12571 * // Using `columnDefs` 12572 * $(document).ready( function() { 12573 * $('#example').dataTable( { 12574 * "columnDefs": [ 12575 * { "width": "20%", "targets": [ 0 ] } 12576 * ] 12577 * } ); 12578 * } ); 12579 * 12580 * @example 12581 * // Using `columns` 12582 * $(document).ready( function() { 12583 * $('#example').dataTable( { 12584 * "columns": [ 12585 * { "width": "20%" }, 12586 * null, 12587 * null, 12588 * null, 12589 * null 12590 * ] 12591 * } ); 12592 * } ); 12593 */ 12594 "sWidth": null 12595 }; 12596 12597 _fnHungarianMap( DataTable.defaults.column ); 12598 12599 12600 12601 /** 12602 * DataTables settings object - this holds all the information needed for a 12603 * given table, including configuration, data and current application of the 12604 * table options. DataTables does not have a single instance for each DataTable 12605 * with the settings attached to that instance, but rather instances of the 12606 * DataTable "class" are created on-the-fly as needed (typically by a 12607 * $().dataTable() call) and the settings object is then applied to that 12608 * instance. 12609 * 12610 * Note that this object is related to {@link DataTable.defaults} but this 12611 * one is the internal data store for DataTables's cache of columns. It should 12612 * NOT be manipulated outside of DataTables. Any configuration should be done 12613 * through the initialisation options. 12614 * @namespace 12615 * @todo Really should attach the settings object to individual instances so we 12616 * don't need to create new instances on each $().dataTable() call (if the 12617 * table already exists). It would also save passing oSettings around and 12618 * into every single function. However, this is a very significant 12619 * architecture change for DataTables and will almost certainly break 12620 * backwards compatibility with older installations. This is something that 12621 * will be done in 2.0. 12622 */ 12623 DataTable.models.oSettings = { 12624 /** 12625 * Primary features of DataTables and their enablement state. 12626 * @namespace 12627 */ 12628 "oFeatures": { 12629 12630 /** 12631 * Flag to say if DataTables should automatically try to calculate the 12632 * optimum table and columns widths (true) or not (false). 12633 * Note that this parameter will be set by the initialisation routine. To 12634 * set a default use {@link DataTable.defaults}. 12635 * @type boolean 12636 */ 12637 "bAutoWidth": null, 12638 12639 /** 12640 * Delay the creation of TR and TD elements until they are actually 12641 * needed by a driven page draw. This can give a significant speed 12642 * increase for Ajax source and Javascript source data, but makes no 12643 * difference at all f
12643ro DOM and server-side processing tables. 12644 * Note that this parameter will be set by the initialisation routine. To 12645 * set a default use {@link DataTable.defaults}. 12646 * @type boolean 12647 */ 12648 "bDeferRender": null, 12649 12650 /** 12651 * Enable filtering on the table or not. Note that if this is disabled 12652 * then there is no filtering at all on the table, including fnFilter. 12653 * To just remove the filtering input use sDom and remove the 'f' option. 12654 * Note that this parameter will be set by the initialisation routine. To 12655 * set a default use {@link DataTable.defaults}. 12656 * @type boolean 12657 */ 12658 "bFilter": null, 12659 12660 /** 12661 * Table information element (the 'Showing x of y records' div) enable 12662 * flag. 12663 * Note that this parameter will be set by the initialisation routine. To 12664 * set a default use {@link DataTable.defaults}. 12665 * @type boolean 12666 */ 12667 "bInfo": null, 12668 12669 /** 12670 * Present a user control allowing the end user to change the page size 12671 * when pagination is enabled. 12672 * Note that this parameter will be set by the initialisation routine. To 12673 * set a default use {@link DataTable.defaults}. 12674 * @type boolean 12675 */ 12676 "bLengthChange": null, 12677 12678 /** 12679 * Pagination enabled or not. Note that if this is disabled then length 12680 * changing must also be disabled. 12681 * Note that this parameter will be set by the initialisation routine. To 12682 * set a default use {@link DataTable.defaults}. 12683 * @type boolean 12684 */ 12685 "bPaginate": null, 12686 12687 /** 12688 * Processing indicator enable flag whenever DataTables is enacting a 12689 * user request - typically an Ajax request for server-side processing. 12690 * Note that this parameter will be set by the initialisation routine. To 12691 * set a default use {@link DataTable.defaults}. 12692 * @type boolean 12693 */ 12694 "bProcessing": null, 12695 12696 /** 12697 * Server-side processing enabled flag - when enabled DataTables will 12698 * get all data from the server for every draw - there is no filtering, 12699 * sorting or paging done on the client-side. 12700 * Note that this parameter will be set by the initialisation routine. To 12701 * set a default use {@link DataTable.defaults}. 12702 * @type boolean 12703 */ 12704 "bServerSide": null, 12705 12706 /** 12707 * Sorting enablement flag. 12708 * Note that this parameter will be set by the initialisation routine. To 12709 * set a default use {@link DataTable.defaults}. 12710 * @type boolean 12711 */ 12712 "bSort": null, 12713 12714 /**
vendor: 9,250 bytes, lines 12715-13102
12715 * Multi-column sorting 12716 * Note that this parameter will be set by the initialisation routine. To 12717 * set a default use {@link DataTable.defaults}. 12718 * @type boolean 12719 */ 12720 "bSortMulti": null, 12721 12722 /** 12723 * Apply a class to the columns which are being sorted to provide a 12724 * visual highlight or not. This can slow things down when enabled since 12725 * there is a lot of DOM interaction. 12726 * Note that this parameter will be set by the initialisation routine. To 12727 * set a default use {@link DataTable.defaults}. 12728 * @type boolean 12729 */ 12730 "bSortClasses": null, 12731 12732 /** 12733 * State saving enablement flag. 12734 * Note that this parameter will be set by the initialisation routine. To 12735 * set a default use {@link DataTable.defaults}. 12736 * @type boolean 12737 */ 12738 "bStateSave": null 12739 }, 12740 12741 12742 /** 12743 * Scrolling settings for a table. 12744 * @namespace 12745 */ 12746 "oScroll": { 12747 /** 12748 * When the table is shorter in height than sScrollY, collapse the 12749 * table container down to the height of the table (when true). 12750 * Note that this parameter will be set by the initialisation routine. To 12751 * set a default use {@link DataTable.defaults}. 12752 * @type boolean 12753 */ 12754 "bCollapse": null, 12755 12756 /** 12757 * Width of the scrollbar for the web-browser's platform. Calculated 12758 * during table initialisation. 12759 * @type int 12760 * @default 0 12761 */ 12762 "iBarWidth": 0, 12763 12764 /** 12765 * Viewport width for horizontal scrolling. Horizontal scrolling is 12766 * disabled if an empty string. 12767 * Note that this parameter will be set by the initialisation routine. To 12768 * set a default use {@link DataTable.defaults}. 12769 * @type string 12770 */ 12771 "sX": null, 12772 12773 /** 12774 * Width to expand the table to when using x-scrolling. Typically you 12775 * should not need to use this. 12776 * Note that this parameter will be set by the initialisation routine. To 12777 * set a default use {@link DataTable.defaults}. 12778 * @type string 12779 * @deprecated 12780 */ 12781 "sXInner": null, 12782 12783 /** 12784 * Viewport height for vertical scrolling. Vertical scrolling is disabled 12785 * if an empty string. 12786 * Note that this parameter will be set by the initialisation routine. To 12787 * set a default use {@link DataTable.defaults}. 12788 * @type string 12789 */ 12790 "sY": null 12791 }, 12792 12793 /** 12794 * Language information for the table. 12795 * @namespace 12796 * @extends DataTable.defaults.oLanguage 12797 */ 12798 "oLanguage": { 12799 /** 12800 * Information callback function. See 12801 * {@link DataTable.defaults.fnInfoCallback} 12802 * @type function 12803 * @default null 12804 */ 12805 "fnInfoCallback": null 12806 }, 12807 12808 /** 12809 * Browser support parameters 12810 * @namespace 12811 */ 12812 "oBrowser": { 12813 /** 12814 * Indicate if the browser incorrectly calculates width:100% inside a 12815 * scrolling element (IE6/7) 12816 * @type boolean 12817 * @default false 12818 */ 12819 "bScrollOversize": false, 12820 12821 /** 12822 * Determine if the vertical scrollbar is on the right or left of the 12823 * scrolling container - needed for rtl language layout, although not 12824 * all browsers move the scrollbar (Safari). 12825 * @type boolean 12826 * @default false 12827 */ 12828 "bScrollbarLeft": false 12829 }, 12830 12831 12832 "ajax": null, 12833 12834 12835 /** 12836 * Array referencing the nodes which are used for the features. The 12837 * parameters of this object match what is allowed by sDom - i.e. 12838 * <ul> 12839 * <li>'l' - Length changing</li> 12840 * <li>'f' - Filtering input</li> 12841 * <li>'t' - The table!</li> 12842 * <li>'i' - Information</li> 12843 * <li>'p' - Pagination</li> 12844 * <li>'r' - pRocessing</li> 12845 * </ul> 12846 * @type array 12847 * @default [] 12848 */ 12849 "aanFeatures": [], 12850 12851 /** 12852 * Store data information - see {@link DataTable.models.oRow} for detailed 12853 * information. 12854 * @type array 12855 * @default [] 12856 */ 12857 "aoData": [], 12858 12859 /** 12860 * Array of indexes which are in the current display (after filtering etc) 12861 * @type array 12862 * @default [] 12863 */ 12864 "aiDisplay": [], 12865 12866 /** 12867 * Array of indexes for display - no filtering 12868 * @type array 12869 * @default [] 12870 */ 12871 "aiDisplayMaster": [], 12872 12873 /** 12874 * Store information about each column that is in use 12875 * @type array 12876 * @default [] 12877 */ 12878 "aoColumns": [], 12879 12880 /** 12881 * Store information about the table's header 12882 * @type array 12883 * @default [] 12884 */ 12885 "aoHeader": [], 12886 12887 /** 12888 * Store information about the table's footer 12889 * @type array 12890 * @default [] 12891 */ 12892 "aoFooter": [], 12893 12894 /** 12895 * Store the applied global search information in case we want to force a 12896 * research or compare the old search to a new one. 12897 * Note that this parameter will be set by the initialisation routine. To 12898 * set a default use {@link DataTable.defaults}. 12899 * @namespace 12900 * @extends DataTable.models.oSearch 12901 */ 12902 "oPreviousSearch": {}, 12903 12904 /** 12905 * Store the applied search for each column - see 12906 * {@link DataTable.models.oSearch} for the format that is used for the 12907 * filtering information for each column. 12908 * @type array 12909 * @default [] 12910 */ 12911 "aoPreSearchCols": [], 12912 12913 /** 12914 * Sorting that is applied to the table. Note that the inner arrays are 12915 * used in the following manner: 12916 * <ul> 12917 * <li>Index 0 - column number</li> 12918 * <li>Index 1 - current sorting direction</li> 12919 * </ul> 12920 * Note that this parameter will be set by the initialisation routine. To 12921 * set a default use {@link DataTable.defaults}. 12922 * @type array 12923 * @todo These inner arrays should really be objects 12924 */ 12925 "aaSorting": null, 12926 12927 /** 12928 * Sorting that is always applied to the table (i.e. prefixed in front of 12929 * aaSorting). 12930 * Note that this parameter will be set by the initialisation routine. To 12931 * set a default use {@link DataTable.defaults}. 12932 * @type array 12933 * @default [] 12934 */ 12935 "aaSortingFixed": [], 12936 12937 /** 12938 * Classes to use for the striping of a table. 12939 * Note that this parameter will be set by the initialisation routine. To 12940 * set a default use {@link DataTable.defaults}. 12941 * @type array 12942 * @default [] 12943 */ 12944 "asStripeClasses": null, 12945 12946 /** 12947 * If restoring a table - we should restore its striping classes as well 12948 * @type array 12949 * @default [] 12950 */ 12951 "asDestroyStripes": [], 12952 12953 /** 12954 * If restoring a table - we should restore its width 12955 * @type int 12956 * @default 0 12957 */ 12958 "sDestroyWidth": 0, 12959 12960 /** 12961 * Callback functions array for every time a row is inserted (i.e. on a draw). 12962 * @type array 12963 * @default [] 12964 */ 12965 "aoRowCallback": [], 12966 12967 /** 12968 * Callback functions for the header on each draw. 12969 * @type array 12970 * @default [] 12971 */ 12972 "aoHeaderCallback": [], 12973 12974 /** 12975 * Callback function for the footer on each draw. 12976 * @type array 12977 * @default [] 12978 */ 12979 "aoFooterCallback": [], 12980 12981 /** 12982 * Array of callback functions for draw callback functions 12983 * @type array 12984 * @default [] 12985 */ 12986 "aoDrawCallback": [], 12987 12988 /** 12989 * Array of callback functions for row created function 12990 * @type array 12991 * @default [] 12992 */ 12993 "aoRowCreatedCallback": [], 12994 12995 /** 12996 * Callback functions for just before the table is redrawn. A return of 12997 * false will be used to cancel the draw. 12998 * @type array 12999 * @default [] 13000 */ 13001 "aoPreDrawCallback": [], 13002 13003 /** 13004 * Callback functions for when the table has been initialised. 13005 * @type array 13006 * @default [] 13007 */ 13008 "aoInitComplete": [], 13009 13010 13011 /** 13012 * Callbacks for modifying the settings to be stored for state saving, prior to 13013 * saving state. 13014 * @type array 13015 * @default [] 13016 */ 13017 "aoStateSaveParams": [], 13018 13019 /** 13020 * Callbacks for modifying the settings that have been stored for state saving 13021 * prior to using the stored values to restore the state. 13022 * @type array 13023 * @default [] 13024 */ 13025 "aoStateLoadParams": [], 13026 13027 /** 13028 * Callbacks for operating on the settings object once the saved state has been 13029 * loaded 13030 * @type array 13031 * @default [] 13032 */ 13033 "aoStateLoaded": [], 13034 13035 /** 13036 * Cache the table ID for quick access 13037 * @type string 13038 * @default <i>Empty string</i> 13039 */ 13040 "sTableId": "", 13041 13042 /** 13043 * The TABLE node for the main table 13044 * @type node 13045 * @default null 13046 */ 13047 "nTable": null, 13048 13049 /** 13050 * Permanent ref to the thead element 13051 * @type node 13052 * @default null 13053 */ 13054 "nTHead": null, 13055 13056 /** 13057 * Permanent ref to the tfoot element - if it exists 13058 * @type node 13059 * @default null 13060 */ 13061 "nTFoot": null, 13062 13063 /** 13064 * Permanent ref to the tbody element 13065 * @type node 13066 * @default null 13067 */ 13068 "nTBody": null, 13069 13070 /** 13071 * Cache the wrapper node (contains all DataTables controlled elements) 13072 * @type node 13073 * @default null 13074 */ 13075 "nTableWrapper": null, 13076 13077 /** 13078 * Indicate if when using server-side processing the loading of data 13079 * should be deferred until the second draw. 13080 * Note that this parameter will be set by the initialisation routine. To 13081 * set a default use {@link DataTable.defaults}. 13082 * @type boolean 13083 * @default false 13084 */ 13085 "bDeferLoading": false, 13086 13087 /** 13088 * Indicate if all required information has been read in 13089 * @type boolean 13090 * @default false 13091 */ 13092 "bInitialised": false, 13093 13094 /** 13095 * Information about open rows. Each object in the array has the parameters 13096 * 'nTr' and 'nParent' 13097 * @type array 13098 * @default [] 13099 */ 13100 "aoOpenRows": [], 13101 13102 /**
13103 * Dictate the positioning of DataTables' control elements - see 13104 * {@link DataTable.model.oInit.sDom}. 13105 * Note that this parameter will be set by the initialisation routine. To 13106 * set a default use {@link DataTable.defaults}. 13107 * @type string 13108 * @default null 13109 */ 13110 "sDom": null, 13111 13112 /** 13113 * Search delay (in mS) 13114 * @type integer 13115 * @default null 13116 */ 13117 "searchDelay": null, 13118 13119 /** 13120 * Which type of pagination should be used. 13121 * Note that this parameter will be set by the initialisation routine. To 13122 * set a default use {@link DataTable.defaults}. 13123 * @type string 13124 * @default two_button 13125 */ 13126 "sPaginationType": "two_button", 13127 13128 /** 13129 * The state duration (for `stateSave`) in seconds. 13130 * Note that this parameter will be set by the initialisation routine. To 13131 * set a default use {@link DataTable.defaults}. 13132 * @type int 13133 * @default 0 13134 */ 13135 "iStateDuration": 0, 13136 13137 /** 13138 * Array of callback functions for state saving. Each array element is an 13139 * object with the following parameters: 13140 * <ul> 13141 * <li>function:fn - function to call. Takes two parameters, oSettings 13142 * and the JSON string to save that has been thus far created. Returns 13143 * a JSON string to be inserted into a json object 13144 * (i.e. '"param": [ 0, 1, 2]')</li> 13145 * <li>string:sName - name of callback</li> 13146 * </ul> 13147 * @type array 13148 * @default [] 13149 */ 13150 "aoStateSave": [], 13151 13152 /** 13153 * Array of callback functions for state loading. Each array element is an 13154 * object with the following parameters: 13155 * <ul> 13156 * <li>function:fn - function to call. Takes two parameters, oSettings 13157 * and the object stored. May return false to cancel state loading</li> 13158 * <li>string:sName - name of callback</li> 13159 * </ul> 13160 * @type array 13161 * @default [] 13162 */ 13163 "aoStateLoad": [], 13164 13165 /** 13166 * State that was saved. Useful for back reference 13167 * @type object 13168 * @default null 13169 */ 13170 "oSavedState": null, 13171 13172 /** 13173 * State that was loaded. Useful for back reference 13174 * @type object 13175 * @default null 13176 */ 13177 "oLoadedState": null, 13178 13179 /** 13180 * Source url for AJAX data for the table. 13181 * Note that this parameter will be set by the initialisation routine. To 13182 * set a default use {@link DataTable.defaults}. 13183 * @type string 13184 * @default null 13185 */ 13186 "sAjaxSource": null, 13187 13188 /** 13189 * Property from a given object from which to read the table data from. This 13190 * can be an empty string (when not server-side processing), in which case 13191 * it is assumed an an array is given directly. 13192 * Note that this parameter will be set by the initialisation routine. To 13193 * set a default use {@link DataTable.defaults}. 13194 * @type string 13195 */ 13196 "sAjaxDataProp": null, 13197 13198 /** 13199 * Note if draw should be blocked while getting data 13200 * @type boolean 13201 * @default true 13202 */ 13203 "bAjaxDataGet": true, 13204 13205 /** 13206 * The last jQuery XHR object that was used for server-side data gathering. 13207 * This can be used for working with the XHR information in one of the 13208 * callbacks 13209 * @type object 13210 * @default null 13211 */ 13212 "jqXHR": null, 13213 13214 /** 13215 * JSON returned from the server in the last Ajax request 13216 * @type object 13217 * @default undefined 13218 */ 13219 "json": undefined, 13220 13221 /** 13222 * Data submitted as part of the last Ajax request 13223 * @type object 13224 * @default undefined 13225 */ 13226 "oAjaxData": undefined, 13227 13228 /** 13229 * Function to get the server-side data. 13230 * Note that this parameter will be set by the initialisation routine. To 13231 * set a default use {@link DataTable.defaults}. 13232 * @type function 13233 */ 13234 "fnServerData": null, 13235 13236 /** 13237 * Functions which are called prior to sending an Ajax request so extra 13238 * parameters can easily be sent to the server 13239 * @type array 13240 * @default [] 13241 */ 13242 "aoServerParams": [], 13243 13244 /** 13245 * Send the XHR HTTP method - GET or POST (could be PUT or DELETE if 13246 * required). 13247 * Note that this parameter will be set by the initialisation routine. To 13248 * set a default use {@link DataTable.defaults}. 13249 * @type string 13250 */ 13251 "sServerMethod": null, 13252 13253 /** 13254 * Format numbers for display. 13255 * Note that this parameter will be set by the initialisation routine. To 13256 * set a default use {@link DataTable.defaults}. 13257 * @type function 13258 */ 13259 "fnFormatNumber": null, 13260 13261 /** 13262 * List of options that can be used for the user selectable length menu. 13263 * Note that this parameter will be set by the initialisation routine. To 13264 * set a default use {@link DataTable.defaults}. 13265 * @type array 13266 * @default [] 13267 */ 13268 "aLengthMenu": null, 13269 13270 /** 13271 * Counter for the draws that the table does. Also used as a tracker for 13272 * server-side processing 13273 * @type int 13274 * @default 0 13275 */ 13276 "iDraw": 0, 13277 13278 /** 13279 * Indicate if a redraw is being done - useful for Ajax 13280 * @type boolean 13281 * @default false 13282 */ 13283 "bDrawing": false, 13284 13285 /** 13286 * Draw index (iDraw) of the last error when parsing the returned data 13287 * @type int 13288 * @default -1 13289 */ 13290 "iDrawError": -1, 13291 13292 /** 13293 * Paging display length 13294 * @type int 13295 * @default 10 13296 */ 13297 "_iDisplayLength": 10, 13298 13299 /** 13300 * Paging start point - aiDisplay index 13301 * @type int 13302 * @default 0 13303 */ 13304 "_iDisplayStart": 0, 13305 13306 /** 13307 * Server-side processing - number of records in the result set 13308 * (i.e. before filtering), Use fnRecordsTotal rather than 13309 * this property to get the value of the number of records, regardless of 13310 * the server-side processing setting. 13311 * @type int 13312 * @default 0 13313 * @private 13314 */ 13315 "_iRecordsTotal": 0, 13316 13317 /** 13318 * Server-side processing - number of records in the current display set 13319 * (i.e. after filtering). Use fnRecordsDisplay rather than 13320 * this property to get the value of the number of records, regardless of 13321 * the server-side processing setting. 13322 * @type boolean 13323 * @default 0 13324 * @private 13325 */ 13326 "_iRecordsDisplay": 0, 13327 13328 /** 13329 * Flag to indicate if jQuery UI marking and classes should be used. 13330 * Note that this parameter will be set by the initialisation routine. To 13331 * set a default use {@link DataTable.defaults}. 13332 * @type boolean 13333 */ 13334 "bJUI": null, 13335 13336 /** 13337 * The classes to use for the table 13338 * @type object 13339 * @default {} 13340 */
vendor: 4,450 bytes, lines 13341-13527
13341 "oClasses": {}, 13342 13343 /** 13344 * Flag attached to the settings object so you can check in the draw 13345 * callback if filtering has been done in the draw. Deprecated in favour of 13346 * events. 13347 * @type boolean 13348 * @default false 13349 * @deprecated 13350 */ 13351 "bFiltered": false, 13352 13353 /** 13354 * Flag attached to the settings object so you can check in the draw 13355 * callback if sorting has been done in the draw. Deprecated in favour of 13356 * events. 13357 * @type boolean 13358 * @default false 13359 * @deprecated 13360 */ 13361 "bSorted": false, 13362 13363 /** 13364 * Indicate that if multiple rows are in the header and there is more than 13365 * one unique cell per column, if the top one (true) or bottom one (false) 13366 * should be used for sorting / title by DataTables. 13367 * Note that this parameter will be set by the initialisation routine. To 13368 * set a default use {@link DataTable.defaults}. 13369 * @type boolean 13370 */ 13371 "bSortCellsTop": null, 13372 13373 /** 13374 * Initialisation object that is used for the table 13375 * @type object 13376 * @default null 13377 */ 13378 "oInit": null, 13379 13380 /** 13381 * Destroy callback functions - for plug-ins to attach themselves to the 13382 * destroy so they can clean up markup and events. 13383 * @type array 13384 * @default [] 13385 */ 13386 "aoDestroyCallback": [], 13387 13388 13389 /** 13390 * Get the number of records in the current record set, before filtering 13391 * @type function 13392 */ 13393 "fnRecordsTotal": function () 13394 { 13395 return _fnDataSource( this ) == 'ssp' ? 13396 this._iRecordsTotal * 1 : 13397 this.aiDisplayMaster.length; 13398 }, 13399 13400 /** 13401 * Get the number of records in the current record set, after filtering 13402 * @type function 13403 */ 13404 "fnRecordsDisplay": function () 13405 { 13406 return _fnDataSource( this ) == 'ssp' ? 13407 this._iRecordsDisplay * 1 : 13408 this.aiDisplay.length; 13409 }, 13410 13411 /** 13412 * Get the display end point - aiDisplay index 13413 * @type function 13414 */ 13415 "fnDisplayEnd": function () 13416 { 13417 var 13418 len = this._iDisplayLength, 13419 start = this._iDisplayStart, 13420 calc = start + len, 13421 records = this.aiDisplay.length, 13422 features = this.oFeatures, 13423 paginate = features.bPaginate; 13424 13425 if ( features.bServerSide ) { 13426 return paginate === false || len === -1 ? 13427 start + records : 13428 Math.min( start+len, this._iRecordsDisplay ); 13429 } 13430 else { 13431 return ! paginate || calc>records || len===-1 ? 13432 records : 13433 calc; 13434 } 13435 }, 13436 13437 /** 13438 * The DataTables object for this table 13439 * @type object 13440 * @default null 13441 */ 13442 "oInstance": null, 13443 13444 /** 13445 * Unique identifier for each instance of the DataTables object. If there 13446 * is an ID on the table node, then it takes that value, otherwise an 13447 * incrementing internal counter is used. 13448 * @type string 13449 * @default null 13450 */ 13451 "sInstance": null, 13452 13453 /** 13454 * tabindex attribute value that is added to DataTables control elements, allowing 13455 * keyboard navigation of the table and its controls. 13456 */ 13457 "iTabIndex": 0, 13458 13459 /** 13460 * DIV container for the footer scrolling table if scrolling 13461 */ 13462 "nScrollHead": null, 13463 13464 /** 13465 * DIV container for the footer scrolling table if scrolling 13466 */ 13467 "nScrollFoot": null, 13468 13469 /** 13470 * Last applied sort 13471 * @type array 13472 * @default [] 13473 */ 13474 "aLastSort": [], 13475 13476 /** 13477 * Stored plug-in instances 13478 * @type object 13479 * @default {} 13480 */ 13481 "oPlugins": {} 13482 }; 13483 13484 /** 13485 * Extension object for DataTables that is used to provide all extension 13486 * options. 13487 * 13488 * Note that the `DataTable.ext` object is available through 13489 * `jQuery.fn.dataTable.ext` where it may be accessed and manipulated. It is 13490 * also aliased to `jQuery.fn.dataTableExt` for historic reasons. 13491 * @namespace 13492 * @extends DataTable.models.ext 13493 */ 13494 13495 13496 /** 13497 * DataTables extensions 13498 * 13499 * This namespace acts as a collection area for plug-ins that can be used to 13500 * extend DataTables capabilities. Indeed many of the build in methods 13501 * use this method to provide their own capabilities (sorting methods for 13502 * example). 13503 * 13504 * Note that this namespace is aliased to `jQuery.fn.dataTableExt` for legacy 13505 * reasons 13506 * 13507 * @namespace 13508 */ 13509 DataTable.ext = _ext = { 13510 /** 13511 * Buttons. For use with the Buttons extension for DataTables. This is 13512 * defined here so other extensions can define buttons regardless of load 13513 * order. It is _not_ used by DataTables core. 13514 * 13515 * @type object 13516 * @default {} 13517 */ 13518 buttons: {}, 13519 13520 13521 /** 13522 * Element class names 13523 * 13524 * @type object 13525 * @default {} 13526 */ 13527 classes: {}
vendor: 10,711 bytes, lines 13527-13841
13527, 13528 13529 13530 /** 13531 * Error reporting. 13532 * 13533 * How should DataTables report an error. Can take the value 'alert', 13534 * 'throw', 'none' or a function. 13535 * 13536 * @type string|function 13537 * @default alert 13538 */ 13539 errMode: "alert", 13540 13541 13542 /** 13543 * Feature plug-ins. 13544 * 13545 * This is an array of objects which describe the feature plug-ins that are 13546 * available to DataTables. These feature plug-ins are then available for 13547 * use through the `dom` initialisation option. 13548 * 13549 * Each feature plug-in is described by an object which must have the 13550 * following properties: 13551 * 13552 * * `fnInit` - function that is used to initialise the plug-in, 13553 * * `cFeature` - a character so the feature can be enabled by the `dom` 13554 * instillation option. This is case sensitive. 13555 * 13556 * The `fnInit` function has the following input parameters: 13557 * 13558 * 1. `{object}` DataTables settings object: see 13559 * {@link DataTable.models.oSettings} 13560 * 13561 * And the following return is expected: 13562 * 13563 * * {node|null} The element which contains your feature. Note that the 13564 * return may also be void if your plug-in does not require to inject any 13565 * DOM elements into DataTables control (`dom`) - for example this might 13566 * be useful when developing a plug-in which allows table control via 13567 * keyboard entry 13568 * 13569 * @type array 13570 * 13571 * @example 13572 * $.fn.dataTable.ext.features.push( { 13573 * "fnInit": function( oSettings ) { 13574 * return new TableTools( { "oDTSettings": oSettings } ); 13575 * }, 13576 * "cFeature": "T" 13577 * } ); 13578 */ 13579 feature: [], 13580 13581 13582 /** 13583 * Row searching. 13584 * 13585 * This method of searching is complimentary to the default type based 13586 * searching, and a lot more comprehensive as it allows you complete control 13587 * over the searching logic. Each element in this array is a function 13588 * (parameters described below) that is called for every row in the table, 13589 * and your logic decides if it should be included in the searching data set 13590 * or not. 13591 * 13592 * Searching functions have the following input parameters: 13593 * 13594 * 1. `{object}` DataTables settings object: see 13595 * {@link DataTable.models.oSettings} 13596 * 2. `{array|object}` Data for the row to be processed (same as the 13597 * original format that was passed in as the data source, or an array 13598 * from a DOM data source 13599 * 3. `{int}` Row index ({@link DataTable.models.oSettings.aoData}), which 13600 * can be useful to retrieve the `TR` element if you need DOM interaction. 13601 * 13602 * And the following return is expected: 13603 * 13604 * * {boolean} Include the row in the searched result set (true) or not 13605 * (false) 13606 * 13607 * Note that as with the main search ability in DataTables, technically this 13608 * is "filtering", since it is subtractive. However, for consistency in 13609 * naming we call it searching here. 13610 * 13611 * @type array 13612 * @default [] 13613 * 13614 * @example 13615 * // The following example shows custom search being applied to the 13616 * // fourth column (i.e. the data[3] index) based on two input values 13617 * // from the end-user, matching the data in a certain range. 13618 * $.fn.dataTable.ext.search.push( 13619 * function( settings, data, dataIndex ) { 13620 * var min = document.getElementById('min').value * 1; 13621 * var max = document.getElementById('max').value * 1; 13622 * var version = data[3] == "-" ? 0 : data[3]*1; 13623 * 13624 * if ( min == "" && max == "" ) { 13625 * return true; 13626 * } 13627 * else if ( min == "" && version < max ) { 13628 * return true; 13629 * } 13630 * else if ( min < version && "" == max ) { 13631 * return true; 13632 * } 13633 * else if ( min < version && version < max ) { 13634 * return true; 13635 * } 13636 * return false; 13637 * } 13638 * ); 13639 */ 13640 search: [], 13641 13642 13643 /** 13644 * Selector extensions 13645 * 13646 * The `selector` option can be used to extend the options available for the 13647 * selector modifier options (`selector-modifier` object data type) that 13648 * each of the three built in selector types offer (row, column and cell + 13649 * their plural counterparts). For example the Select extension uses this 13650 * mechanism to provide an option to select only rows, columns and cells 13651 * that have been marked as selected by the end user (`{selected: true}`), 13652 * which can be used in conjunction with the existing built in selector 13653 * options. 13654 * 13655 * Each property is an array to which functions can be pushed. The functions 13656 * take three attributes: 13657 * 13658 * * Settings object for the host table 13659 * * Options object (`selector-modifier` object type) 13660 * * Array of selected item indexes 13661 * 13662 * The return is an array of the resulting item indexes after the custom 13663 * selector has been applied. 13664 * 13665 * @type object 13666 */ 13667 selector: { 13668 cell: [], 13669 column: [], 13670 row: [] 13671 }, 13672 13673 13674 /** 13675 * Internal functions, exposed for used in plug-ins. 13676 * 13677 * Please note that you should not need to use the internal methods for 13678 * anything other than a plug-in (and even then, try to avoid if possible). 13679 * The internal function may change between releases. 13680 * 13681 * @type object 13682 * @default {} 13683 */ 13684 internal: {}, 13685 13686 13687 /** 13688 * Legacy configuration options. Enable and disable legacy options that 13689 * are available in DataTables. 13690 * 13691 * @type object 13692 */ 13693 legacy: { 13694 /** 13695 * Enable / disable DataTables 1.9 compatible server-side processing 13696 * requests 13697 * 13698 * @type boolean 13699 * @default null 13700 */ 13701 ajax: null 13702 }, 13703 13704 13705 /** 13706 * Pagination plug-in methods. 13707 * 13708 * Each entry in this object is a function and defines which buttons should 13709 * be shown by the pagination rendering method that is used for the table: 13710 * {@link DataTable.ext.renderer.pageButton}. The renderer addresses how the 13711 * buttons are displayed in the document, while the functions here tell it 13712 * what buttons to display. This is done by returning an array of button 13713 * descriptions (what each button will do). 13714 * 13715 * Pagination types (the four built in options and any additional plug-in 13716 * options defined here) can be used through the `paginationType` 13717 * initialisation parameter. 13718 * 13719 * The functions defined take two parameters: 13720 * 13721 * 1. `{int} page` The current page index 13722 * 2. `{int} pages` The number of pages in the table 13723 * 13724 * Each function is expected to return an array where each element of the 13725 * array can be one of: 13726 * 13727 * * `first` - Jump to first page when activated 13728 * * `last` - Jump to last page when activated 13729 * * `previous` - Show previous page when activated 13730 * * `next` - Show next page when activated 13731 * * `{int}` - Show page of the index given 13732 * * `{array}` - A nested array containing the above elements to add a 13733 * containing 'DIV' element (might be useful for styling). 13734 * 13735 * Note that DataTables v1.9- used this object slightly differently whereby 13736 * an object with two functions would be defined for each plug-in. That 13737 * ability is still supported by DataTables 1.10+ to provide backwards 13738 * compatibility, but this option of use is now decremented and no longer 13739 * documented in DataTables 1.10+. 13740 * 13741 * @type object 13742 * @default {} 13743 * 13744 * @example 13745 * // Show previous, next and current page buttons only 13746 * $.fn.dataTableExt.oPagination.current = function ( page, pages ) { 13747 * return [ 'previous', page, 'next' ]; 13748 * }; 13749 */ 13750 pager: {}, 13751 13752 13753 renderer: { 13754 pageButton: {}, 13755 header: {} 13756 }, 13757 13758 13759 /** 13760 * Ordering plug-ins - custom data source 13761 * 13762 * The extension options for ordering of data available here is complimentary 13763 * to the default type based ordering that DataTables typically uses. It 13764 * allows much greater control over the the data that is being used to 13765 * order a column, but is necessarily therefore more complex. 13766 * 13767 * This type of ordering is useful if you want to do ordering based on data 13768 * live from the DOM (for example the contents of an 'input' element) rather 13769 * than just the static string that DataTables knows of. 13770 * 13771 * The way these plug-ins work is that you create an array of the values you 13772 * wish to be ordering for the column in question and then return that 13773 * array. The data in the array much be in the index order of the rows in 13774 * the table (not the currently ordering order!). Which order data gathering 13775 * function is run here depends on the `dt-init columns.orderDataType` 13776 * parameter that is used for the column (if any). 13777 * 13778 * The functions defined take two parameters: 13779 * 13780 * 1. `{object}` DataTables settings object: see 13781 * {@link DataTable.models.oSettings} 13782 * 2. `{int}` Target column index 13783 * 13784 * Each function is expected to return an array: 13785 * 13786 * * `{array}` Data for the column to be ordering upon 13787 * 13788 * @type array 13789 * 13790 * @example 13791 * // Ordering using `input` node values 13792 * $.fn.dataTable.ext.order['dom-text'] = function ( settings, col ) 13793 * { 13794 * return this.api().column( col, {order:'index'} ).nodes().map( function ( td, i ) { 13795 * return $('input', td).val(); 13796 * } ); 13797 * } 13798 */ 13799 order: {}, 13800 13801 13802 /** 13803 * Type based plug-ins. 13804 * 13805 * Each column in DataTables has a type assigned to it, either by automatic 13806 * detection or by direct assignment using the `type` option for the column. 13807 * The type of a column will effect how it is ordering and search (plug-ins 13808 * can also make use of the column type if required). 13809 * 13810 * @namespace 13811 */ 13812 type: { 13813 /** 13814 * Type detection functions. 13815 * 13816 * The functions defined in this object are used to automatically detect 13817 * a column's type, making initialisation of DataTables super easy, even 13818 * when complex data is in the table. 13819 * 13820 * The functions defined take two parameters: 13821 * 13822 * 1. `{*}` Data from the column cell to be analysed 13823 * 2. `{settings}` DataTables settings object. This can be used to 13824 * perform context specific type detection - for example detection 13825 * based on language settings such as using a comma for a decimal 13826 * place. Generally speaking the options from the settings will not 13827 * be required 13828 * 13829 * Each function is expected to return: 13830 * 13831 * * `{string|null}` Data type detected, or null if unknown (and thus 13832 * pass it on to the other type detection functions. 13833 * 13834 * @type array 13835 * 13836 * @example 13837 * // Currency type detection plug-in: 13838 * $.fn.dataTable.ext.type.detect.push( 13839 * function ( data, settings ) { 13840 * // Check the numeric part 13841 * if ( !
13841$.isNumeric( data.substring(1) ) ) { 13842 * return null; 13843 * } 13844 * 13845 * // Check prefixed by currency 13846 * if ( data.charAt(0) == '$' || data.charAt(0) == '£' ) { 13847 * return 'currency'; 13848 * } 13849 * return null; 13850 * } 13851 * ); 13852 */ 13853 detect: [], 13854 13855 13856 /** 13857 * Type based search formatting. 13858 * 13859 * The type based searching functions can be used to pre-format the 13860 * data to be search on. For example, it can be used to strip HTML 13861 * tags or to de-format telephone numbers for numeric only searching. 13862 * 13863 * Note that is a search is not defined for a column of a given type, 13864 * no search formatting will be performed. 13865 * 13866 * Pre-processing of searching data plug-ins - When you assign the sType 13867 * for a column (or have it automatically detected for you by DataTables 13868 * or a type detection plug-in), you will typically be using this for 13869 * custom sorting, but it can also be used to provide custom searching 13870 * by allowing you to pre-processing the data and returning the data in 13871 * the format that should be searched upon. This is done by adding 13872 * functions this object with a parameter name which matches the sType 13873 * for that target column. This is the corollary of <i>afnSortData</i> 13874 * for searching data. 13875 * 13876 * The functions defined take a single parameter: 13877 * 13878 * 1. `{*}` Data from the column cell to be prepared for searching 13879 * 13880 * Each function is expected to return: 13881 * 13882 * * `{string|null}` Formatted string that will be used for the searching. 13883 * 13884 * @type object 13885 * @default {} 13886 * 13887 * @example 13888 * $.fn.dataTable.ext.type.search['title-numeric'] = function ( d ) { 13889 * return d.replace(/\n/g," ").replace( /<.*?>/g, "" ); 13890 * } 13891 */ 13892 search: {}, 13893 13894 13895 /** 13896 * Type based ordering. 13897 * 13898 * The column type tells DataTables what ordering to apply to the table 13899 * when a column is sorted upon. The order for each type that is defined, 13900 * is defined by the functions available in this object. 13901 * 13902 * Each ordering option can be described by three properties added to 13903 * this object: 13904 * 13905 * * `{type}-pre` - Pre-formatting function 13906 * * `{type}-asc` - Ascending order function 13907 * * `{type}-desc` - Descending order function 13908 * 13909 * All three can be used together, only `{type}-pre` or only 13910 * `{type}-asc` and `{type}-desc` together. It is generally recommended 13911 * that only `{type}-pre` is used, as this provides the optimal 13912 * implementation in terms of speed, although the others are provided 13913 * for compatibility with existing Javascript sort functions. 13914 * 13915 * `{type}-pre`: Functions defined take a single parameter: 13916 * 13917 * 1. `{*}` Data from the column cell to be prepared for ordering 13918 * 13919 * And return: 13920 * 13921 * * `{*}` Data to be sorted upon 13922 * 13923 * `{type}-asc` and `{type}-desc`: Functions are typical Javascript sort 13924 * functions, taking two parameters: 13925 * 13926 * 1. `{*}` Data to compare to the second parameter 13927 * 2. `{*}` Data to compare to the first parameter 13928 * 13929 * And returning: 13930 * 13931 * * `{*}` Ordering match: <0 if first parameter should be sorted lower 13932 * than the second parameter, ===0 if the two parameters are equal and 13933 * >0 if the first parameter should be sorted height than the second 13934 * parameter. 13935 * 13936 * @type object 13937 * @default {} 13938 * 13939 * @example 13940 * // Numeric ordering of formatted numbers with a pre-formatter 13941 * $.extend( $.fn.dataTable.ext.type.order, { 13942 * "string-pre": function(x) { 13943 * a = (a === "-" || a === "") ? 0 : a.replace( /[^\d\-\.]/g, "" ); 13944 * return parseFloat( a ); 13945 * } 13946 * } ); 13947 * 13948 * @example 13949 * // Case-sensitive string ordering, with no pre-formatting method 13950 * $.extend( $.fn.dataTable.ext.order, { 13951 * "string-case-asc": function(x,y) { 13952 * return ((x < y) ? -1 : ((x > y) ? 1 : 0)); 13953 * }, 13954 * "string-case-desc": function(x,y) { 13955 * return ((x < y) ? 1 : ((x > y) ? -1 : 0)); 13956 * } 13957 * } ); 13958 */ 13959 order: {} 13960 }, 13961 13962 /** 13963 * Unique DataTables instance counter 13964 * 13965 * @type int 13966 * @private 13967 */ 13968 _unique: 0, 13969 13970 13971 // 13972 // Depreciated 13973 // The following properties are retained for backwards compatiblity only. 13974 // The should not be used in new projects and will be removed in a future 13975 // version 13976 // 13977 13978 /** 13979 * Version check function. 13980 * @type function 13981 * @depreciated Since 1.10 13982 */ 13983 fnVersionCheck: DataTable.fnVersionCheck, 13984 13985 13986 /** 13987 * Index for what 'this' index API functions should use 13988 * @type int 13989 * @deprecated Since v1.10 13990 */ 13991 iApiIndex: 0, 13992 13993 13994 /** 13995 * jQuery UI class container 13996 * @type object 13997 * @deprecated Since v1.10 13998 */ 13999 oJUIClasses: {}, 14000 14001 14002 /** 14003 * Software version 14004 * @type string 14005 * @deprecated Since v1.10 14006 */
14007 sVersion: DataTable.version 14008 }; 14009 14010 14011 // 14012 // Backwards compatibility. Alias to pre 1.10 Hungarian notation counter parts 14013 // 14014 $.extend( _ext, { 14015 afnFiltering: _ext.search, 14016 aTypes: _ext.type.detect, 14017 ofnSearch: _ext.type.search, 14018 oSort: _ext.type.order, 14019 afnSortData: _ext.order, 14020 aoFeatures: _ext.feature, 14021 oApi: _ext.internal, 14022 oStdClasses: _ext.classes, 14023 oPagination: _ext.pager 14024 } ); 14025 14026 14027 $.extend( DataTable.ext.classes, { 14028 "sTable": "dataTable", 14029 "sNoFooter": "no-footer", 14030 14031 /* Paging buttons */ 14032 "sPageButton": "paginate_button", 14033 "sPageButtonActive": "current", 14034 "sPageButtonDisabled": "disabled", 14035 14036 /* Striping classes */ 14037 "sStripeOdd": "odd", 14038 "sStripeEven": "even", 14039 14040 /* Empty row */ 14041 "sRowEmpty": "dataTables_empty", 14042 14043 /* Features */ 14044 "sWrapper": "dataTables_wrapper", 14045 "sFilter": "dataTables_filter", 14046 "sInfo": "dataTables_info", 14047 "sPaging": "dataTables_paginate paging_", /* Note that the type is postfixed */ 14048 "sLength": "dataTables_length", 14049 "sProcessing": "dataTables_processing", 14050 14051 /* Sorting */ 14052 "sSortAsc": "sorting_asc", 14053 "sSortDesc": "sorting_desc", 14054 "sSortable": "sorting", /* Sortable in both directions */ 14055 "sSortableAsc": "sorting_asc_disabled", 14056 "sSortableDesc": "sorting_desc_disabled", 14057 "sSortableNone": "sorting_disabled", 14058 "sSortColumn": "sorting_", /* Note that an int is postfixed for the sorting order */ 14059 14060 /* Filtering */ 14061 "sFilterInput": "", 14062 14063 /* Page length */ 14064 "sLengthSelect": "", 14065 14066 /* Scrolling */ 14067 "sScrollWrapper": "dataTables_scroll", 14068 "sScrollHead": "dataTables_scrollHead", 14069 "sScrollHeadInner": "dataTables_scrollHeadInner", 14070 "sScrollBody": "dataTables_scrollBody", 14071 "sScrollFoot": "dataTables_scrollFoot", 14072 "sScrollFootInner": "dataTables_scrollFootInner", 14073 14074 /* Misc */ 14075 "sHeaderTH": "", 14076 "sFooterTH": "", 14077 14078 // Deprecated 14079 "sSortJUIAsc": "", 14080 "sSortJUIDesc": "", 14081 "sSortJUI": "", 14082 "sSortJUIAscAllowed": "", 14083 "sSortJUIDescAllowed": "", 14084 "sSortJUIWrapper": "", 14085 "sSortIcon": "", 14086 "sJUIHeader": "", 14087 "sJUIFooter": "" 14088 } ); 14089 14090 14091 (function() { 14092 14093 // Reused strings for better compression. Closure compiler appears to have a
vendor: 23,939 bytes, lines 14094-14883
14094 // weird edge case where it is trying to expand strings rather than use the 14095 // variable version. This results in about 200 bytes being added, for very 14096 // little preference benefit since it this run on script load only. 14097 var _empty = ''; 14098 _empty = ''; 14099 14100 var _stateDefault = _empty + 'ui-state-default'; 14101 var _sortIcon = _empty + 'css_right ui-icon ui-icon-'; 14102 var _headerFooter = _empty + 'fg-toolbar ui-toolbar ui-widget-header ui-helper-clearfix'; 14103 14104 $.extend( DataTable.ext.oJUIClasses, DataTable.ext.classes, { 14105 /* Full numbers paging buttons */ 14106 "sPageButton": "fg-button ui-button "+_stateDefault, 14107 "sPageButtonActive": "ui-state-disabled", 14108 "sPageButtonDisabled": "ui-state-disabled", 14109 14110 /* Features */ 14111 "sPaging": "dataTables_paginate fg-buttonset ui-buttonset fg-buttonset-multi "+ 14112 "ui-buttonset-multi paging_", /* Note that the type is postfixed */ 14113 14114 /* Sorting */ 14115 "sSortAsc": _stateDefault+" sorting_asc", 14116 "sSortDesc": _stateDefault+" sorting_desc", 14117 "sSortable": _stateDefault+" sorting", 14118 "sSortableAsc": _stateDefault+" sorting_asc_disabled", 14119 "sSortableDesc": _stateDefault+" sorting_desc_disabled", 14120 "sSortableNone": _stateDefault+" sorting_disabled", 14121 "sSortJUIAsc": _sortIcon+"triangle-1-n", 14122 "sSortJUIDesc": _sortIcon+"triangle-1-s", 14123 "sSortJUI": _sortIcon+"carat-2-n-s", 14124 "sSortJUIAscAllowed": _sortIcon+"carat-1-n", 14125 "sSortJUIDescAllowed": _sortIcon+"carat-1-s", 14126 "sSortJUIWrapper": "DataTables_sort_wrapper", 14127 "sSortIcon": "DataTables_sort_icon", 14128 14129 /* Scrolling */ 14130 "sScrollHead": "dataTables_scrollHead "+_stateDefault, 14131 "sScrollFoot": "dataTables_scrollFoot "+_stateDefault, 14132 14133 /* Misc */ 14134 "sHeaderTH": _stateDefault, 14135 "sFooterTH": _stateDefault, 14136 "sJUIHeader": _headerFooter+" ui-corner-tl ui-corner-tr", 14137 "sJUIFooter": _headerFooter+" ui-corner-bl ui-corner-br" 14138 } ); 14139 14140 }()); 14141 14142 14143 14144 var extPagination = DataTable.ext.pager; 14145 14146 function _numbers ( page, pages ) { 14147 var 14148 numbers = [], 14149 buttons = extPagination.numbers_length, 14150 half = Math.floor( buttons / 2 ), 14151 i = 1; 14152 14153 if ( pages <= buttons ) { 14154 numbers = _range( 0, pages ); 14155 } 14156 else if ( page <= half ) { 14157 numbers = _range( 0, buttons-2 ); 14158 numbers.push( 'ellipsis' ); 14159 numbers.push( pages-1 ); 14160 } 14161 else if ( page >= pages - 1 - half ) { 14162 numbers = _range( pages-(buttons-2), pages ); 14163 numbers.splice( 0, 0, 'ellipsis' ); // no unshift in ie6 14164 numbers.splice( 0, 0, 0 ); 14165 } 14166 else { 14167 numbers = _range( page-half+2, page+half-1 ); 14168 numbers.push( 'ellipsis' ); 14169 numbers.push( pages-1 ); 14170 numbers.splice( 0, 0, 'ellipsis' ); 14171 numbers.splice( 0, 0, 0 ); 14172 } 14173 14174 numbers.DT_el = 'span'; 14175 return numbers; 14176 } 14177 14178 14179 $.extend( extPagination, { 14180 simple: function ( page, pages ) { 14181 return [ 'previous', 'next' ]; 14182 }, 14183 14184 full: function ( page, pages ) { 14185 return [ 'first', 'previous', 'next', 'last' ]; 14186 }, 14187 14188 simple_numbers: function ( page, pages ) { 14189 return [ 'previous', _numbers(page, pages), 'next' ]; 14190 }, 14191 14192 full_numbers: function ( page, pages ) { 14193 return [ 'first', 'previous', _numbers(page, pages), 'next', 'last' ]; 14194 }, 14195 14196 // For testing and plug-ins to use 14197 _numbers: _numbers, 14198 14199 // Number of number buttons (including ellipsis) to show. _Must be odd!_ 14200 numbers_length: 7 14201 } ); 14202 14203 14204 $.extend( true, DataTable.ext.renderer, { 14205 pageButton: { 14206 _: function ( settings, host, idx, buttons, page, pages ) { 14207 var classes = settings.oClasses; 14208 var lang = settings.oLanguage.oPaginate; 14209 var btnDisplay, btnClass, counter=0; 14210 14211 var attach = function( container, buttons ) { 14212 var i, ien, node, button; 14213 var clickHandler = function ( e ) { 14214 _fnPageChange( settings, e.data.action, true ); 14215 }; 14216 14217 for ( i=0, ien=buttons.length ; i<ien ; i++ ) { 14218 button = buttons[i]; 14219 14220 if ( $.isArray( button ) ) { 14221 var inner = $( '<'+(button.DT_el || 'div')+'/>' ) 14222 .appendTo( container ); 14223 attach( inner, button ); 14224 } 14225 else { 14226 btnDisplay = ''; 14227 btnClass = ''; 14228 14229 switch ( button ) { 14230 case 'ellipsis': 14231 container.append('<span class="ellipsis">…</span>'); 14232 break; 14233 14234 case 'first': 14235 btnDisplay = lang.sFirst; 14236 btnClass = button + (page > 0 ? 14237 '' : ' '+classes.sPageButtonDisabled); 14238 break; 14239 14240 case 'previous': 14241 btnDisplay = lang.sPrevious; 14242 btnClass = button + (page > 0 ? 14243 '' : ' '+classes.sPageButtonDisabled); 14244 break; 14245 14246 case 'next': 14247 btnDisplay = lang.sNext; 14248 btnClass = button + (page < pages-1 ? 14249 '' : ' '+classes.sPageButtonDisabled); 14250 break; 14251 14252 case 'last': 14253 btnDisplay = lang.sLast; 14254 btnClass = button + (page < pages-1 ? 14255 '' : ' '+classes.sPageButtonDisabled); 14256 break; 14257 14258 default: 14259 btnDisplay = button + 1; 14260 btnClass = page === button ? 14261 classes.sPageButtonActive : ''; 14262 break; 14263 } 14264 14265 if ( btnDisplay ) { 14266 node = $('<a>', { 14267 'class': classes.sPageButton+' '+btnClass, 14268 'aria-controls': settings.sTableId, 14269 'data-dt-idx': counter, 14270 'tabindex': settings.iTabIndex, 14271 'id': idx === 0 && typeof button === 'string' ? 14272 settings.sTableId +'_'+ button : 14273 null 14274 } ) 14275 .html( btnDisplay ) 14276 .appendTo( container ); 14277 14278 _fnBindAction( 14279 node, {action: button}, clickHandler 14280 ); 14281 14282 counter++; 14283 } 14284 } 14285 } 14286 }; 14287 14288 // IE9 throws an 'unknown error' if document.activeElement is used 14289 // inside an iframe or frame. Try / catch the error. Not good for 14290 // accessibility, but neither are frames. 14291 var activeEl; 14292 14293 try { 14294 // Because this approach is destroying and recreating the paging 14295 // elements, focus is lost on the select button which is bad for 14296 // accessibility. So we want to restore focus once the draw has 14297 // completed 14298 activeEl = $(document.activeElement).data('dt-idx'); 14299 } 14300 catch (e) {} 14301 14302 attach( $(host).empty(), buttons ); 14303 14304 if ( activeEl ) { 14305 $(host).find( '[data-dt-idx='+activeEl+']' ).focus(); 14306 } 14307 } 14308 } 14309 } ); 14310 14311 14312 14313 // Built in type detection. See model.ext.aTypes for information about 14314 // what is required from this methods. 14315 $.extend( DataTable.ext.type.detect, [ 14316 // Plain numbers - first since V8 detects some plain numbers as dates 14317 // e.g. Date.parse('55') (but not all, e.g. Date.parse('22')...). 14318 function ( d, settings ) 14319 { 14320 var decimal = settings.oLanguage.sDecimal; 14321 return _isNumber( d, decimal ) ? 'num'+decimal : null; 14322 }, 14323 14324 // Dates (only those recognised by the browser's Date.parse) 14325 function ( d, settings ) 14326 { 14327 // V8 will remove any unknown characters at the start and end of the 14328 // expression, leading to false matches such as `$245.12` or `10%` being 14329 // a valid date. See forum thread 18941 for detail. 14330 if ( d && !(d instanceof Date) && ( ! _re_date_start.test(d) || ! _re_date_end.test(d) ) ) { 14331 return null; 14332 } 14333 var parsed = Date.parse(d); 14334 return (parsed !== null && !isNaN(parsed)) || _empty(d) ? 'date' : null; 14335 }, 14336 14337 // Formatted numbers 14338 function ( d, settings ) 14339 { 14340 var decimal = settings.oLanguage.sDecimal; 14341 return _isNumber( d, decimal, true ) ? 'num-fmt'+decimal : null; 14342 }, 14343 14344 // HTML numeric 14345 function ( d, settings ) 14346 { 14347 var decimal = settings.oLanguage.sDecimal; 14348 return _htmlNumeric( d, decimal ) ? 'html-num'+decimal : null; 14349 }, 14350 14351 // HTML numeric, formatted 14352 function ( d, settings ) 14353 { 14354 var decimal = settings.oLanguage.sDecimal; 14355 return _htmlNumeric( d, decimal, true ) ? 'html-num-fmt'+decimal : null; 14356 }, 14357 14358 // HTML (this is strict checking - there must be html) 14359 function ( d, settings ) 14360 { 14361 return _empty( d ) || (typeof d === 'string' && d.indexOf('<') !== -1) ? 14362 'html' : null; 14363 } 14364 ] ); 14365 14366 14367 14368 // Filter formatting functions. See model.ext.ofnSearch for information about 14369 // what is required from these methods. 14370 // 14371 // Note that additional search methods are added for the html numbers and 14372 // html formatted numbers by `_addNumericSort()` when we know what the decimal 14373 // place is 14374 14375 14376 $.extend( DataTable.ext.type.search, { 14377 html: function ( data ) { 14378 return _empty(data) ? 14379 data : 14380 typeof data === 'string' ? 14381 data 14382 .replace( _re_new_lines, " " ) 14383 .replace( _re_html, "" ) : 14384 ''; 14385 }, 14386 14387 string: function ( data ) { 14388 return _empty(data) ? 14389 data : 14390 typeof data === 'string' ? 14391 data.replace( _re_new_lines, " " ) : 14392 data; 14393 } 14394 } ); 14395 14396 14397 14398 var __numericReplace = function ( d, decimalPlace, re1, re2 ) { 14399 if ( d !== 0 && (!d || d === '-') ) { 14400 return -Infinity; 14401 } 14402 14403 // If a decimal place other than `.` is used, it needs to be given to the 14404 // function so we can detect it and replace with a `.` which is the only 14405 // decimal place Javascript recognises - it is not locale aware. 14406 if ( decimalPlace ) { 14407 d = _numToDecimal( d, decimalPlace ); 14408 } 14409 14410 if ( d.replace ) { 14411 if ( re1 ) { 14412 d = d.replace( re1, '' ); 14413 } 14414 14415 if ( re2 ) { 14416 d = d.replace( re2, '' ); 14417 } 14418 } 14419 14420 return d * 1; 14421 }; 14422 14423 14424 // Add the numeric 'deformatting' functions for sorting and search. This is done 14425 // in a function to provide an easy ability for the language options to add 14426 // additional methods if a non-period decimal place is used. 14427 function _addNumericSort ( decimalPlace ) { 14428 $.each( 14429 { 14430 // Plain numbers 14431 "num": function ( d ) { 14432 return __numericReplace( d, decimalPlace ); 14433 }, 14434 14435 // Formatted numbers 14436 "num-fmt": function ( d ) { 14437 return __numericReplace( d, decimalPlace, _re_formatted_numeric ); 14438 }, 14439 14440 // HTML numeric 14441 "html-num": function ( d ) { 14442 return __numericReplace( d, decimalPlace, _re_html ); 14443 }, 14444 14445 // HTML numeric, formatted 14446 "html-num-fmt": function ( d ) { 14447 return __numericReplace( d, decimalPlace, _re_html, _re_formatted_numeric ); 14448 } 14449 }, 14450 function ( key, fn ) { 14451 // Add the ordering method 14452 _ext.type.order[ key+decimalPlace+'-pre' ] = fn; 14453 14454 // For HTML types add a search formatter that will strip the HTML 14455 if ( key.match(/^html\-/) ) { 14456 _ext.type.search[ key+decimalPlace ] = _ext.type.search.html; 14457 } 14458 } 14459 ); 14460 } 14461 14462 14463 // Default sort methods 14464 $.extend( _ext.type.order, { 14465 // Dates 14466 "date-pre": function ( d ) { 14467 return Date.parse( d ) || 0; 14468 }, 14469 14470 // html 14471 "html-pre": function ( a ) { 14472 return _empty(a) ? 14473 '' : 14474 a.replace ? 14475 a.replace( /<.*?>/g, "" ).toLowerCase() : 14476 a+''; 14477 }, 14478 14479 // string 14480 "string-pre": function ( a ) { 14481 // This is a little complex, but faster than always calling toString, 14482 // http://jsperf.com/tostring-v-check 14483 return _empty(a) ? 14484 '' : 14485 typeof a === 'string' ? 14486 a.toLowerCase() : 14487 ! a.toString ? 14488 '' : 14489 a.toString(); 14490 }, 14491 14492 // string-asc and -desc are retained only for compatibility with the old 14493 // sort methods 14494 "string-asc": function ( x, y ) { 14495 return ((x < y) ? -1 : ((x > y) ? 1 : 0)); 14496 }, 14497 14498 "string-desc": function ( x, y ) { 14499 return ((x < y) ? 1 : ((x > y) ? -1 : 0)); 14500 } 14501 } ); 14502 14503 14504 // Numeric sorting types - order doesn't matter here 14505 _addNumericSort( '' ); 14506 14507 14508 $.extend( true, DataTable.ext.renderer, { 14509 header: { 14510 _: function ( settings, cell, column, classes ) { 14511 // No additional mark-up required 14512 // Attach a sort listener to update on sort - note that using the 14513 // `DT` namespace will allow the event to be removed automatically 14514 // on destroy, while the `dt` namespaced event is the one we are 14515 // listening for 14516 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) { 14517 if ( settings !== ctx ) { // need to check this this is the host 14518 return; // table, not a nested one 14519 } 14520 14521 var colIdx = column.idx; 14522 14523 cell 14524 .removeClass( 14525 column.sSortingClass +' '+ 14526 classes.sSortAsc +' '+ 14527 classes.sSortDesc 14528 ) 14529 .addClass( columns[ colIdx ] == 'asc' ? 14530 classes.sSortAsc : columns[ colIdx ] == 'desc' ? 14531 classes.sSortDesc : 14532 column.sSortingClass 14533 ); 14534 } ); 14535 }, 14536 14537 jqueryui: function ( settings, cell, column, classes ) { 14538 $('<div/>') 14539 .addClass( classes.sSortJUIWrapper ) 14540 .append( cell.contents() ) 14541 .append( $('<span/>') 14542 .addClass( classes.sSortIcon+' '+column.sSortingClassJUI ) 14543 ) 14544 .appendTo( cell ); 14545 14546 // Attach a sort listener to update on sort 14547 $(settings.nTable).on( 'order.dt.DT', function ( e, ctx, sorting, columns ) { 14548 if ( settings !== ctx ) { 14549 return; 14550 } 14551 14552 var colIdx = column.idx; 14553 14554 cell 14555 .removeClass( classes.sSortAsc +" "+classes.sSortDesc ) 14556 .addClass( columns[ colIdx ] == 'asc' ? 14557 classes.sSortAsc : columns[ colIdx ] == 'desc' ? 14558 classes.sSortDesc : 14559 column.sSortingClass 14560 ); 14561 14562 cell 14563 .find( 'span.'+classes.sSortIcon ) 14564 .removeClass( 14565 classes.sSortJUIAsc +" "+ 14566 classes.sSortJUIDesc +" "+ 14567 classes.sSortJUI +" "+ 14568 classes.sSortJUIAscAllowed +" "+ 14569 classes.sSortJUIDescAllowed 14570 ) 14571 .addClass( columns[ colIdx ] == 'asc' ? 14572 classes.sSortJUIAsc : columns[ colIdx ] == 'desc' ? 14573 classes.sSortJUIDesc : 14574 column.sSortingClassJUI 14575 ); 14576 } ); 14577 } 14578 } 14579 } ); 14580 14581 /* 14582 * Public helper functions. These aren't used internally by DataTables, or 14583 * called by any of the options passed into DataTables, but they can be used 14584 * externally by developers working with DataTables. They are helper functions 14585 * to make working with DataTables a little bit easier. 14586 */ 14587 14588 /** 14589 * Helpers for `columns.render`. 14590 * 14591 * The options defined here can be used with the `columns.render` initialisation 14592 * option to provide a display renderer. The following functions are defined: 14593 * 14594 * * `number` - Will format numeric data (defined by `columns.data`) for 14595 * display, retaining the original unformatted data for sorting and filtering. 14596 * It takes 4 parameters: 14597 * * `string` - Thousands grouping separator 14598 * * `string` - Decimal point indicator 14599 * * `integer` - Number of decimal points to show 14600 * * `string` (optional) - Prefix. 14601 * 14602 * @example 14603 * // Column definition using the number renderer 14604 * { 14605 * data: "salary", 14606 * render: $.fn.dataTable.render.number( '\'', '.', 0, '$' ) 14607 * } 14608 * 14609 * @namespace 14610 */ 14611 DataTable.render = { 14612 number: function ( thousands, decimal, precision, prefix ) { 14613 return { 14614 display: function ( d ) { 14615 if ( typeof d !== 'number' && typeof d !== 'string' ) { 14616 return d; 14617 } 14618 14619 var negative = d < 0 ? '-' : ''; 14620 d = Math.abs( parseFloat( d ) ); 14621 14622 var intPart = parseInt( d, 10 ); 14623 var floatPart = precision ? 14624 decimal+(d - intPart).toFixed( precision ).substring( 2 ): 14625 ''; 14626 14627 return negative + (prefix||'') + 14628 intPart.toString().replace( 14629 /\B(?=(\d{3})+(?!\d))/g, thousands 14630 ) + 14631 floatPart; 14632 } 14633 }; 14634 } 14635 }; 14636 14637 14638 /* 14639 * This is really a good bit rubbish this method of exposing the internal methods 14640 * publicly... - To be fixed in 2.0 using methods on the prototype 14641 */ 14642 14643 14644 /** 14645 * Create a wrapper function for exporting an internal functions to an external API. 14646 * @param {string} fn API function name 14647 * @returns {function} wrapped function 14648 * @memberof DataTable#internal 14649 */ 14650 function _fnExternApiFunc (fn) 14651 { 14652 return function() { 14653 var args = [_fnSettingsFromNode( this[DataTable.ext.iApiIndex] )].concat( 14654 Array.prototype.slice.call(arguments) 14655 ); 14656 return DataTable.ext.internal[fn].apply( this, args ); 14657 }; 14658 } 14659 14660 14661 /** 14662 * Reference to internal functions for use by plug-in developers. Note that 14663 * these methods are references to internal functions and are considered to be 14664 * private. If you use these methods, be aware that they are liable to change 14665 * between versions. 14666 * @namespace 14667 */ 14668 $.extend( DataTable.ext.internal, { 14669 _fnExternApiFunc: _fnExternApiFunc, 14670 _fnBuildAjax: _fnBuildAjax, 14671 _fnAjaxUpdate: _fnAjaxUpdate, 14672 _fnAjaxParameters: _fnAjaxParameters, 14673 _fnAjaxUpdateDraw: _fnAjaxUpdateDraw, 14674 _fnAjaxDataSrc: _fnAjaxDataSrc, 14675 _fnAddColumn: _fnAddColumn, 14676 _fnColumnOptions: _fnColumnOptions, 14677 _fnAdjustColumnSizing: _fnAdjustColumnSizing, 14678 _fnVisibleToColumnIndex: _fnVisibleToColumnIndex, 14679 _fnColumnIndexToVisible: _fnColumnIndexToVisible, 14680 _fnVisbleColumns: _fnVisbleColumns, 14681 _fnGetColumns: _fnGetColumns, 14682 _fnColumnTypes: _fnColumnTypes, 14683 _fnApplyColumnDefs: _fnApplyColumnDefs, 14684 _fnHungarianMap: _fnHungarianMap, 14685 _fnCamelToHungarian: _fnCamelToHungarian, 14686 _fnLanguageCompat: _fnLanguageCompat, 14687 _fnBrowserDetect: _fnBrowserDetect, 14688 _fnAddData: _fnAddData, 14689 _fnAddTr: _fnAddTr, 14690 _fnNodeToDataIndex: _fnNodeToDataIndex, 14691 _fnNodeToColumnIndex: _fnNodeToColumnIndex, 14692 _fnGetCellData: _fnGetCellData, 14693 _fnSetCellData: _fnSetCellData, 14694 _fnSplitObjNotation: _fnSplitObjNotation, 14695 _fnGetObjectDataFn: _fnGetObjectDataFn, 14696 _fnSetObjectDataFn: _fnSetObjectDataFn, 14697 _fnGetDataMaster: _fnGetDataMaster, 14698 _fnClearTable: _fnClearTable, 14699 _fnDeleteIndex: _fnDeleteIndex, 14700 _fnInvalidate: _fnInvalidate, 14701 _fnGetRowElements: _fnGetRowElements, 14702 _fnCreateTr: _fnCreateTr, 14703 _fnBuildHead: _fnBuildHead, 14704 _fnDrawHead: _fnDrawHead, 14705 _fnDraw: _fnDraw, 14706 _fnReDraw: _fnReDraw, 14707 _fnAddOptionsHtml: _fnAddOptionsHtml, 14708 _fnDetectHeader: _fnDetectHeader, 14709 _fnGetUniqueThs: _fnGetUniqueThs, 14710 _fnFeatureHtmlFilter: _fnFeatureHtmlFilter, 14711 _fnFilterComplete: _fnFilterComplete, 14712 _fnFilterCustom: _fnFilterCustom, 14713 _fnFilterColumn: _fnFilterColumn, 14714 _fnFilter: _fnFilter, 14715 _fnFilterCreateSearch: _fnFilterCreateSearch, 14716 _fnEscapeRegex: _fnEscapeRegex, 14717 _fnFilterData: _fnFilterData, 14718 _fnFeatureHtmlInfo: _fnFeatureHtmlInfo, 14719 _fnUpdateInfo: _fnUpdateInfo, 14720 _fnInfoMacros: _fnInfoMacros, 14721 _fnInitialise: _fnInitialise, 14722 _fnInitComplete: _fnInitComplete, 14723 _fnLengthChange: _fnLengthChange, 14724 _fnFeatureHtmlLength: _fnFeatureHtmlLength, 14725 _fnFeatureHtmlPaginate: _fnFeatureHtmlPaginate, 14726 _fnPageChange: _fnPageChange, 14727 _fnFeatureHtmlProcessing: _fnFeatureHtmlProcessing, 14728 _fnProcessingDisplay: _fnProcessingDisplay, 14729 _fnFeatureHtmlTable: _fnFeatureHtmlTable, 14730 _fnScrollDraw: _fnScrollDraw, 14731 _fnApplyToChildren: _fnApplyToChildren, 14732 _fnCalculateColumnWidths: _fnCalculateColumnWidths, 14733 _fnThrottle: _fnThrottle, 14734 _fnConvertToWidth: _fnConvertToWidth, 14735 _fnScrollingWidthAdjust: _fnScrollingWidthAdjust, 14736 _fnGetWidestNode: _fnGetWidestNode, 14737 _fnGetMaxLenString: _fnGetMaxLenString, 14738 _fnStringToCss: _fnStringToCss, 14739 _fnScrollBarWidth: _fnScrollBarWidth, 14740 _fnSortFlatten: _fnSortFlatten, 14741 _fnSort: _fnSort, 14742 _fnSortAria: _fnSortAria, 14743 _fnSortListener: _fnSortListener, 14744 _fnSortAttachListener: _fnSortAttachListener, 14745 _fnSortingClasses: _fnSortingClasses, 14746 _fnSortData: _fnSortData, 14747 _fnSaveState: _fnSaveState, 14748 _fnLoadState: _fnLoadState, 14749 _fnSettingsFromNode: _fnSettingsFromNode, 14750 _fnLog: _fnLog, 14751 _fnMap: _fnMap, 14752 _fnBindAction: _fnBindAction, 14753 _fnCallbackReg: _fnCallbackReg, 14754 _fnCallbackFire: _fnCallbackFire, 14755 _fnLengthOverflow: _fnLengthOverflow, 14756 _fnRenderer: _fnRenderer, 14757 _fnDataSource: _fnDataSource, 14758 _fnRowAttributes: _fnRowAttributes, 14759 _fnCalculateEnd: function () {} // Used by a lot of plug-ins, but redundant 14760 // in 1.10, so this dead-end function is 14761 // added to prevent errors 14762 } ); 14763 14764 14765 // jQuery access 14766 $.fn.dataTable = DataTable; 14767 14768 // Legacy aliases 14769 $.fn.dataTableSettings = DataTable.settings; 14770 $.fn.dataTableExt = DataTable.ext; 14771 14772 // With a capital `D` we return a DataTables API instance rather than a 14773 // jQuery object 14774 $.fn.DataTable = function ( opts ) { 14775 return $(this).dataTable( opts ).api(); 14776 }; 14777 14778 // All properties that are available to $.fn.dataTable should also be 14779 // available on $.fn.DataTable 14780 $.each( DataTable, function ( prop, val ) { 14781 $.fn.DataTable[ prop ] = val; 14782 } ); 14783 14784 14785 // Information about events fired by DataTables - for documentation. 14786 /** 14787 * Draw event, fired whenever the table is redrawn on the page, at the same 14788 * point as fnDrawCallback. This may be useful for binding events or 14789 * performing calculations when the table is altered at all. 14790 * @name DataTable#draw.dt 14791 * @event 14792 * @param {event} e jQuery event object 14793 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 14794 */ 14795 14796 /** 14797 * Search event, fired when the searching applied to the table (using the 14798 * built-in global search, or column filters) is altered. 14799 * @name DataTable#search.dt 14800 * @event 14801 * @param {event} e jQuery event object 14802 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 14803 */ 14804 14805 /** 14806 * Page change event, fired when the paging of the table is altered. 14807 * @name DataTable#page.dt 14808 * @event 14809 * @param {event} e jQuery event object 14810 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 14811 */ 14812 14813 /** 14814 * Order event, fired when the ordering applied to the table is altered. 14815 * @name DataTable#order.dt 14816 * @event 14817 * @param {event} e jQuery event object 14818 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 14819 */ 14820 14821 /** 14822 * DataTables initialisation complete event, fired when the table is fully 14823 * drawn, including Ajax data loaded, if Ajax data is required. 14824 * @name DataTable#init.dt 14825 * @event 14826 * @param {event} e jQuery event object 14827 * @param {object} oSettings DataTables settings object 14828 * @param {object} json The JSON object request from the server - only 14829 * present if client-side Ajax sourced data is used</li></ol> 14830 */ 14831 14832 /** 14833 * State save event, fired when the table has changed state a new state save 14834 * is required. This event allows modification of the state saving object 14835 * prior to actually doing the save, including addition or other state 14836 * properties (for plug-ins) or modification of a DataTables core property. 14837 * @name DataTable#stateSaveParams.dt 14838 * @event 14839 * @param {event} e jQuery event object 14840 * @param {object} oSettings DataTables settings object 14841 * @param {object} json The state information to be saved 14842 */ 14843 14844 /** 14845 * State load event, fired when the table is loading state from the stored 14846 * data, but prior to the settings object being modified by the saved state 14847 * - allowing modification of the saved state is required or loading of 14848 * state for a plug-in. 14849 * @name DataTable#stateLoadParams.dt 14850 * @event 14851 * @param {event} e jQuery event object 14852 * @param {object} oSettings DataTables settings object 14853 * @param {object} json The saved state information 14854 */ 14855 14856 /** 14857 * State loaded event, fired when state has been loaded from stored data and 14858 * the settings object has been modified by the loaded data. 14859 * @name DataTable#stateLoaded.dt 14860 * @event 14861 * @param {event} e jQuery event object 14862 * @param {object} oSettings DataTables settings object 14863 * @param {object} json The saved state information 14864 */ 14865 14866 /** 14867 * Processing event, fired when DataTables is doing some kind of processing 14868 * (be it, order, searcg or anything else). It can be used to indicate to 14869 * the end user that there is something happening, or that something has 14870 * finished. 14871 * @name DataTable#processing.dt 14872 * @event 14873 * @param {event} e jQuery event object 14874 * @param {object} oSettings DataTables settings object 14875 * @param {boolean} bShow Flag for if DataTables is doing processing or not 14876 */ 14877 14878 /** 14879 * Ajax (XHR) event, fired whenever an Ajax request is completed from a 14880 * request to made to the server for new data. This event is called before 14881 * DataTables processed the returned data, so it can also be used to pre- 14882 * process the data returned from the server, if needed. 14883 *
14884 * Note that this trigger is called in `fnServerData`, if you override 14885 * `fnServerData` and which to use this event, you need to trigger it in you 14886 * success function. 14887 * @name DataTable#xhr.dt 14888 * @event 14889 * @param {event} e jQuery event object 14890 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 14891 * @param {object} json JSON returned from the server 14892 * 14893 * @example 14894 * // Use a custom property returned from the server in another DOM element 14895 * $('#table').dataTable().on('xhr.dt', function (e, settings, json) { 14896 * $('#status').html( json.status ); 14897 * } ); 14898 * 14899 * @example 14900 * // Pre-process the data returned from the server 14901 * $('#table').dataTable().on('xhr.dt', function (e, settings, json) { 14902 * for ( var i=0, ien=json.aaData.length ; i<ien ; i++ ) { 14903 * json.aaData[i].sum = json.aaData[i].one + json.aaData[i].two; 14904 * } 14905 * // Note no return - manipulate the data directly in the JSON object. 14906 * } ); 14907 */ 14908 14909 /** 14910 * Destroy event, fired when the DataTable is destroyed by calling fnDestroy 14911 * or passing the bDestroy:true parameter in the initialisation object. This 14912 * can be used to remove bound events, added DOM nodes, etc. 14913 * @name DataTable#destroy.dt 14914 * @event 14915 * @param {event} e jQuery event object 14916 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 14917 */ 14918 14919 /** 14920 * Page length change event, fired when number of records to show on each 14921 * page (the length) is changed. 14922 * @name DataTable#length.dt 14923 * @event 14924 * @param {event} e jQuery event object 14925 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 14926 * @param {integer} len New length 14927 */ 14928 14929 /** 14930 * Column sizing has changed. 14931 * @name DataTable#column-sizing.dt 14932 * @event 14933 * @param {event} e jQuery event object 14934 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 14935 */ 14936 14937 /** 14938 * Column visibility has changed. 14939 * @name DataTable#column-visibility.dt 14940 * @event 14941 * @param {event} e jQuery event object 14942 * @param {object} o DataTables settings object {@link DataTable.models.oSettings} 14943 * @param {int} column Column index 14944 * @param {bool} vis `false` if column now hidden, or `true` if visible 14945 */ 14946 14947 return $.fn.dataTable; 14948})); 14949 14950}(window, document)); 14951
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.